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