1 /*
2    block.c
3 
4    allows multiple arrays to be malloc'ed in one easy step
5 
6    Simon Kilvington, University of Southampton, 1995
7 */
8 
9 #include "bbltyp.h"
10 #include <stdarg.h>
11 
12 /* the routine that does all the work */
13 static int block__doalloc(int, block_ptr *, const char *, va_list);
14 
15 /*
16    block_alloc
17    allocates a block of memory for a set of arrays
18    the types string determines what the arrays are arrays of, one char per array, types are:
19    c - char
20    i - int
21    f - float
22    d - double
23    B - int
24    v - void *
25    eg int *intarray;
26       float *floatarray1, *floatarray2;
27       block_alloc(&handle, "iff", &intarray, nentries1, &floatarray1, nentries2, &floatarray2, nentries3);
28       ...code...
29       block_free(&handle);
30    returns TRUE if all went well
31 */
32 
33 int
block_alloc(block_ptr * handle,const char * types,...)34 block_alloc(block_ptr *handle, const char *types, ...)
35 {
36    int okay;
37    va_list ap;
38 
39    va_start(ap, types);
40    okay = block__doalloc(FALSE, handle, types, ap);
41    va_end(ap);
42 
43    return okay;
44 }
45 
46 /*
47    block_calloc
48    as block_alloc, but all the space is initialised to 0
49 */
50 
51 int
block_calloc(block_ptr * handle,const char * types,...)52 block_calloc(block_ptr *handle, const char *types, ...)
53 {
54    int okay;
55    va_list ap;
56 
57    va_start(ap, types);
58    okay = block__doalloc(TRUE, handle, types, ap);
59    va_end(ap);
60 
61    return okay;
62 }
63 
64 /*
65    block_free
66    deallocates space claimed with block_[c]alloc
67 */
68 
69 void
block_free(block_ptr * handle)70 block_free(block_ptr *handle)
71 {
72    free(*handle);
73    *handle = NULL;
74 
75    return;
76 }
77 
78 /*
79    block__doalloc
80    does all the work for both the above alloc'ing routines
81 */
82 
83 #define typesize(CHAR, TYPE)	if(types[i] == CHAR)	{			\
84 				   (void) va_arg(ap, TYPE **);			\
85 				   size += va_arg(ap, int) * sizeof(TYPE);	\
86 				   continue;		}
87 
88 #define typeptr(CHAR, TYPE)	if(types[i] == CHAR)	{					\
89 				   array = (void *) va_arg(ap, TYPE **);			\
90 				   *((TYPE **) array) = (TYPE *) ((long) (*handle) + ptr);	\
91 				   ptr += va_arg(ap, int) * sizeof(TYPE);			\
92 				   continue;		}
93 
94 static int
block__doalloc(int clear,block_ptr * handle,const char * types,va_list initap)95 block__doalloc(int clear, block_ptr *handle, const char *types, va_list initap)
96 {
97    va_list ap;
98    int i, size;
99    long ptr;
100    void *array;
101 
102 /* calc how much space we are gonna need */
103    va_copy(ap, initap);
104    size = 0;
105    for(i=0; types[i] != '\0'; i++)
106    {
107       typesize('c', char);
108       typesize('i', int);
109       typesize('f', float);
110       typesize('d', double);
111       typesize('B', int);
112       typesize('v', void *);
113    }
114 
115    *handle = (block_ptr) ((clear) ? calloc(size, 1) : malloc(size));
116 
117 /* set up the ptrs if we can alloc the memory */
118    if(*handle != NULL)
119    {
120       va_copy(ap, initap);
121       ptr = 0;
122       for(i=0; types[i] != '\0'; i++)
123       {
124 	 typeptr('c', char);
125 	 typeptr('i', int);
126 	 typeptr('f', float);
127 	 typeptr('d', double);
128 	 typeptr('B', int);
129 	 typeptr('v', void *);
130       }
131    }
132 
133    return (*handle != NULL);
134 }
135 
136