1 #include "config.h"
2
3 #include "assert.h"
4 #include <stdio.h>
5 #ifdef STDC_HEADERS
6 #include <stdlib.h>
7 #endif
8 #ifdef HAVE_MEMORY_H
9 #include <memory.h>
10 #endif
11 #ifdef HAVE_STRING_H
12 #include <string.h>
13 #endif
14 #include <sys/types.h>
15 #include <ctype.h>
16 extern char *getenv(const char *name);
17
18 #ifdef DO_DCG
19 #include "dill.h"
20 #else
21 #define dill_stream void*
22 #define dill_create_stream() NULL
23 /*stuff*/
24 enum {
25 DILL_C, /* char */
26 DILL_UC, /* unsigned char */
27 DILL_S, /* short */
28 DILL_US, /* unsigned short */
29 DILL_I, /* int */
30 DILL_U, /* unsigned */
31 DILL_L, /* long */
32 DILL_UL, /* unsigned long */
33 DILL_P, /* pointer */
34 DILL_F, /* floating */
35 DILL_D, /* double */
36 DILL_V, /* void */
37 DILL_B, /* block structure */
38 DILL_ERR /* no type */
39 };
40 static int
dill_type_align(dill_stream s,int t)41 dill_type_align(dill_stream s, int t)
42 {
43 switch (t) {
44 case DILL_C: case DILL_UC: return 1;
45 case DILL_S: case DILL_US: return 2;
46 case DILL_I: case DILL_U: return 4;
47 case DILL_L: case DILL_UL: return sizeof(long);
48 case DILL_P: return sizeof(char*);
49 case DILL_F: return sizeof(float);
50 case DILL_D: return sizeof(double);
51 default:
52 return 0;
53 }
54 }
55 #endif
56 #include "ffs.h"
57 #include "fm_internal.h"
58 #include "assert.h"
59
60 static int
local_size(int field_index,FMFormat f,FMTypeDesc * type,FMStructDescList subformats,int immediate)61 local_size(int field_index, FMFormat f, FMTypeDesc *type,
62 FMStructDescList subformats, int immediate)
63 {
64 switch(type->type) {
65 case FMType_string:
66 return sizeof(char*);
67 break;
68 case FMType_pointer:
69 /* pointer is sizeof(char*), but we want to return size of item */
70 if (immediate) return (sizeof(char*));
71 return local_size(field_index, f, type->next, subformats, 0);
72 break;
73 case FMType_array:
74 /* here, we always return the size of the element */
75 return local_size(field_index, f, type->next, subformats, immediate);
76 break;
77 case FMType_subformat: {
78 char *subformat_name = f->field_subformats[field_index]->format_name;
79 while (subformats && (subformats->format_name != NULL)) {
80 if (strcmp(subformat_name, subformats->format_name) == 0) {
81 return subformats->struct_size;
82 }
83 subformats++;
84 }
85 assert(0);
86 }
87 case FMType_simple: {
88 int given_size = f->field_list[field_index].field_size;
89 switch (type->data_type) {
90 case integer_type:
91 case unsigned_type:
92 case boolean_type:
93 case enumeration_type:
94 if ((given_size == 0) || (given_size > sizeof(long))) {
95 given_size = sizeof(long);
96 }
97 break;
98 case float_type:
99 if ((given_size == 0) || (given_size > SIZEOF_DOUBLE)) {
100 given_size = sizeof(double);
101 }
102 break;
103 case char_type:
104 if (given_size == 0) {
105 given_size = 1;
106 }
107 break;
108 case string_type:
109 given_size = sizeof(char*);
110 break;
111 default:
112 assert(0);
113 }
114 return given_size;
115 }
116 }
117 return 0;
118 }
119
120 static int
min_align_size(size)121 min_align_size(size)
122 int size;
123 {
124 int align_size = 8; /* conservative on current machines */
125 switch (size) {
126 case 7:
127 case 6:
128 case 5:
129 case 4:
130 align_size = 4;
131 break;
132 case 3:
133 align_size = 2;
134 break;
135 case 2:
136 case 1:
137 align_size = size;
138 break;
139 }
140 return align_size;
141 }
142
143 static int
min_align_type(typ,size)144 min_align_type(typ, size)
145 FMdata_type typ;
146 int size;
147 {
148 #ifndef DO_DCG
149 return min_align_size(size);
150 #else
151 static dill_stream s = NULL;
152 if (s == NULL) s = dill_create_raw_stream();
153 switch (typ) {
154 case float_type:
155 if (size == dill_type_size(s, DILL_D)) return dill_type_align(s, DILL_D);
156 if (size == dill_type_size(s, DILL_F)) return dill_type_align(s, DILL_F);
157 /* punt */
158 return min_align_size(size);
159 case integer_type: case char_type: case string_type:
160 if (size == dill_type_size(s, DILL_C)) return dill_type_align(s, DILL_C);
161 if (size == dill_type_size(s, DILL_S)) return dill_type_align(s, DILL_S);
162 if (size == dill_type_size(s, DILL_I)) return dill_type_align(s, DILL_I);
163 if (size == dill_type_size(s, DILL_L)) return dill_type_align(s, DILL_L);
164 /* punt */
165 return min_align_size(size);
166 case unsigned_type: case enumeration_type: case boolean_type:
167 if (size == dill_type_size(s, DILL_UC)) return dill_type_align(s, DILL_UC);
168 if (size == dill_type_size(s, DILL_US)) return dill_type_align(s, DILL_US);
169 if (size == dill_type_size(s, DILL_U)) return dill_type_align(s, DILL_U);
170 if (size == dill_type_size(s, DILL_UL)) return dill_type_align(s, DILL_UL);
171 /* punt */
172 return dill_type_align(s, DILL_B);
173 default:
174 return dill_type_align(s, DILL_B);
175 }
176 #endif
177 }
178
179 static int
align_field(int local_size,int cur_offset,FMTypeDesc * type,dill_stream s,int * max_align_p)180 align_field(int local_size, int cur_offset, FMTypeDesc *type, dill_stream s,
181 int *max_align_p)
182 {
183 int new_offset, align_req;
184 switch(type->type) {
185 case FMType_array:
186 if (type->static_size == 0) {
187 /* variant array */
188 if (s!= NULL) {
189 align_req = dill_type_align(s, DILL_P);
190 } else {
191 align_req = sizeof(char*);
192 }
193 } else {
194 /* alignment of the elements */
195 return align_field(local_size, cur_offset, type->next, s,
196 max_align_p);
197 }
198 break;
199 case FMType_string:
200 case FMType_pointer:
201 if (s!= NULL) {
202 align_req = dill_type_align(s, DILL_P);
203 } else {
204 align_req = sizeof(char*);
205 }
206 break;
207 case FMType_subformat:
208 /* realistically, should be max align of subfields, too hard */
209 if (s != NULL) {
210 align_req = 0;
211 int i;
212 for (i = DILL_C; i <DILL_V; i++) {
213 if (align_req < dill_type_align(s, i)) {
214 align_req = dill_type_align(s, i);
215 }
216 }
217 } else {
218 align_req = sizeof(long); /* just a guess */
219 }
220 break;
221 case FMType_simple:
222 align_req = min_align_type(type->data_type, local_size);
223 break;
224 default:
225 align_req = -1;
226 break;
227 }
228 if (align_req > *max_align_p) {
229 *max_align_p = align_req;
230 }
231 new_offset = (cur_offset + align_req - 1) & (-align_req);
232 return new_offset;
233 }
234
235 static void
generate_localized_subformat(FMFormat f,FMStructDescList subformats,dill_stream s)236 generate_localized_subformat(FMFormat f, FMStructDescList subformats,
237 dill_stream s)
238 {
239 FMFieldList fl = copy_field_list(f->field_list);
240 int i = 0;
241 int last_field_end = 0;
242 int max_align = 0;
243 while (fl[i].field_name != NULL) {
244 int align_size = local_size(i, f, &f->var_list[i].type_desc,
245 subformats+1, 1);
246
247 fl[i].field_size = local_size(i, f, &f->var_list[i].type_desc,
248 subformats+1, 0);
249 if (fl[i].field_offset < last_field_end) {
250 fl[i].field_offset = last_field_end;
251 }
252 fl[i].field_offset = align_field(align_size, fl[i].field_offset,
253 &f->var_list[i].type_desc, s, &max_align);
254 last_field_end = fl[i].field_offset + align_size;
255 i++;
256 }
257 subformats->format_name = strdup(f->format_name);
258 subformats->field_list = fl;
259 subformats->struct_size = (last_field_end + max_align - 1) & (-max_align);
260 subformats->opt_info = NULL;
261 }
262
263 extern FMStructDescList
get_localized_formats_dill(FMFormat f,dill_stream s)264 get_localized_formats_dill(FMFormat f, dill_stream s)
265 {
266 FMStructDescList ret_list;
267 int subformat_count = 0;
268 while(f->subformats && (f->subformats[subformat_count] != NULL)) {
269 subformat_count++;
270 }
271 ret_list = malloc(sizeof(ret_list[0]) * (subformat_count+2));
272 int i = 0;
273 ret_list[subformat_count+1].format_name = NULL;
274 ret_list[subformat_count+1].field_list = NULL;
275 ret_list[subformat_count+1].struct_size = 0;
276 ret_list[subformat_count+1].opt_info = 0;
277 for (i=0; i < subformat_count; i++) {
278 generate_localized_subformat(f->subformats[subformat_count-i-1], &ret_list[subformat_count - i], s);
279 }
280 generate_localized_subformat(f, ret_list, s);
281 return ret_list;
282 }
283
284 extern FMStructDescList
get_localized_formats(FMFormat f)285 get_localized_formats(FMFormat f)
286 {
287 static dill_stream s = NULL;
288 if (s == NULL) {
289 s = dill_create_stream();
290 }
291 return get_localized_formats_dill(f, s);
292 }
293
294