1 /*********************************************************************
2 * Copyright 1993, UCAR/Unidata
3 * See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 * $Header: /upc/share/CVS/netcdf-3/ncgen/offsets.c,v 1.1 2009/09/25 18:22:40 dmh Exp $
5 *********************************************************************/
6
7 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8 * Copyright by The HDF Group. *
9 * Copyright by the Board of Trustees of the University of Illinois. *
10 * All rights reserved. *
11 * *
12 * This file is part of HDF5. The full HDF5 copyright notice, including *
13 * terms governing use, modification, and redistribution, is contained in *
14 * the files COPYING and Copyright.html. COPYING can be found at the root *
15 * of the source code distribution tree; Copyright.html can be found at the *
16 * root level of an installed copy of the electronic HDF5 document set and *
17 * is linked from the top-level documents page. It can also be found at *
18 * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
19 * access to either file, you may request a copy from help@hdfgroup.org. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 /*
23 This code is a variantion of the H5detect.c code from HDF5.
24 Author: D. Heimbigner 10/7/2008
25 */
26
27 #include "config.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32
33 #ifdef OFFSETTEST
34
35 static void* emalloc(size_t);
36
37 typedef int nc_type;
38 typedef struct nc_vlen_t {
39 size_t len;
40 void* p;
41 } nc_vlen_t;
42
43 #define NC_NAT 0 /* NAT = 'Not A Type' (c.f. NaN) */
44 #define NC_BYTE 1 /* signed 1 byte integer */
45 #define NC_CHAR 2 /* ISO/ASCII character */
46 #define NC_SHORT 3 /* signed 2 byte integer */
47 #define NC_INT 4 /* signed 4 byte integer */
48 #define NC_FLOAT 5 /* single precision floating point number */
49 #define NC_DOUBLE 6 /* double precision floating point number */
50 #define NC_UBYTE 7 /* unsigned 1 byte int */
51 #define NC_USHORT 8 /* unsigned 2-byte int */
52 #define NC_UINT 9 /* unsigned 4-byte int */
53 #define NC_INT64 10 /* signed 8-byte int */
54 #define NC_UINT64 11 /* unsigned 8-byte int */
55 #define NC_STRING 12 /* string */
56 #define NC_STRING 12 /* string */
57 #define NC_VLEN 13
58 #define NC_OPAQUE 14
59 #define NC_ENUM 15
60 #define NC_COMPOUND 16
61 #endif
62
63 #include "xxxnetcdf.h"
64 #include "ncoffsets.h"
65
66
67 /*
68 The heart of this is the following macro,
69 which computes the offset of a field x
70 when preceded by a char field.
71 The assumptions appear to be as follows:
72 1. the offset produced in this situation indicates
73 the alignment for x relative in such a way that it
74 depends only on the types that precede it in the struct.
75 2. the compiler does not reorder fields.
76 3. arrays are tightly packed.
77 4. nested structs are alignd according to their first member
78 (this actually follows from C language requirement that
79 a struct can legally be cast to an instance of its first member).
80 Given the alignments for the various common primitive types,
81 it is assumed that one can use them anywhere to construct
82 the layout of a struct of such types.
83 It seems to work for HDF5 for a wide variety of machines.
84 Note that technically, this is compiler dependent, but in practice
85 all compilers seem to mimic the gcc rules.
86 */
87
88 #define COMP_ALIGNMENT(DST,TYPE) {\
89 struct {char f1; TYPE x;} tmp; \
90 DST.typename = #TYPE ; \
91 DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));}
92
93 #if 0
94 char* ctypenames[NCTYPES] = {
95 (char*)NULL,
96 "char","unsigned char",
97 "short","unsigned short",
98 "int","unsigned int",
99 "long long","unsigned long long",
100 "float","double",
101 "void*","nc_vlen_t"
102 };
103 #endif
104
105 static Typealignvec vec[NCTYPES];
106 static Typealignset set;
107 static int computed = 0;
108
109 /*Forward*/
110 static void compute_alignments(void);
111
112 unsigned int
nctypealignment(nc_type nctype)113 nctypealignment(nc_type nctype)
114 {
115 Alignment* align = NULL;
116 int index = 0;
117 if(!computed) {
118 compute_alignments();
119 computed = 1;
120 }
121 switch (nctype) {
122 case NC_BYTE: index = UCHARINDEX; break;
123 case NC_CHAR: index = CHARINDEX; break;
124 case NC_SHORT: index = SHORTINDEX; break;
125 case NC_INT: index = INTINDEX; break;
126 case NC_FLOAT: index = FLOATINDEX; break;
127 case NC_DOUBLE: index = DOUBLEINDEX; break;
128 case NC_UBYTE: index = UCHARINDEX; break;
129 case NC_USHORT: index = USHORTINDEX; break;
130 case NC_UINT: index = UINTINDEX; break;
131 case NC_INT64: index = LONGLONGINDEX; break;
132 case NC_UINT64: index = ULONGLONGINDEX; break;
133 case NC_STRING: index = PTRINDEX; break;
134 case NC_VLEN: index = NCVLENINDEX; break;
135 case NC_OPAQUE: index = UCHARINDEX; break;
136 default:
137 fprintf(stderr,"nctypealignment: bad type code: %d",nctype);
138 exit(1);
139 }
140 align = &vec[index];
141 return align->alignment;
142 }
143
144
145 static void
compute_alignments(void)146 compute_alignments(void)
147 {
148 /* Compute the alignments for all the common C data types*/
149 /* First for the struct*/
150 /* initialize*/
151 memset((void*)&set,0,sizeof(set));
152 memset((void*)vec,0,sizeof(vec));
153
154 COMP_ALIGNMENT(set.charalign,char);
155 COMP_ALIGNMENT(set.ucharalign,unsigned char);
156 COMP_ALIGNMENT(set.shortalign,short);
157 COMP_ALIGNMENT(set.ushortalign,unsigned short);
158 COMP_ALIGNMENT(set.intalign,int);
159 COMP_ALIGNMENT(set.uintalign,unsigned int);
160 COMP_ALIGNMENT(set.longlongalign,long long);
161 COMP_ALIGNMENT(set.ulonglongalign,unsigned long long);
162 COMP_ALIGNMENT(set.floatalign,float);
163 COMP_ALIGNMENT(set.doublealign,double);
164 COMP_ALIGNMENT(set.ptralign,void*);
165 COMP_ALIGNMENT(set.ncvlenalign,nc_vlen_t);
166
167 /* Then the vector*/
168 COMP_ALIGNMENT(vec[CHARINDEX],char);
169 COMP_ALIGNMENT(vec[UCHARINDEX],unsigned char);
170 COMP_ALIGNMENT(vec[SHORTINDEX],short);
171 COMP_ALIGNMENT(vec[USHORTINDEX],unsigned short);
172 COMP_ALIGNMENT(vec[INTINDEX],int);
173 COMP_ALIGNMENT(vec[UINTINDEX],unsigned int);
174 COMP_ALIGNMENT(vec[LONGLONGINDEX],long long);
175 COMP_ALIGNMENT(vec[ULONGLONGINDEX],unsigned long long);
176 COMP_ALIGNMENT(vec[FLOATINDEX],float);
177 COMP_ALIGNMENT(vec[DOUBLEINDEX],double);
178 COMP_ALIGNMENT(vec[PTRINDEX],void*);
179 COMP_ALIGNMENT(vec[NCVLENINDEX],nc_vlen_t);
180 }
181
182 #ifdef OFFSETTEST
183
184 /* Compute the alignment of TYPE when it is preceded
185 by a field of type TYPE1
186 */
187 #define COMP_ALIGNMENT1(DST,TYPE1,TYPE) {\
188 struct {TYPE1 f1; TYPE x;} tmp; \
189 DST.typename = #TYPE ; \
190 DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));}
191
192 /* Compute the alignment of TYPE when it is preceded
193 by a field of type TYPE1 and a field of type TYPE2
194 */
195 #define COMP_ALIGNMENT2(DST,TYPE1,TYPE2,TYPE) {\
196 struct {TYPE1 f1, TYPE2 f2; TYPE x;} tmp; \
197 DST.typename = #TYPE ; \
198 DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));}
199
200 /* Compute the alignment of TYPE when it is preceded
201 by a field of type TYPE1 and a field of type TYPE2
202 */
203 #define COMP_SIZE0(DST,TYPE1,TYPE2) {\
204 struct {TYPE1 c; TYPE2 x;} tmp; \
205 DST = sizeof(tmp); }
206
207 static char*
padname(char * name)208 padname(char* name)
209 {
210 #define MAX 20
211 if(name == NULL) name = "null";
212 int len = strlen(name);
213 if(len > MAX) len = MAX;
214 char* s = (char*)emalloc(MAX+1);
215 memset(s,' ',MAX);
216 s[MAX+1] = '\0';
217 strncpy(s,name,len);
218 return s;
219 }
220
221 static void
verify(Typealignvec * vec)222 verify(Typealignvec* vec)
223 {
224 int i,j;
225 Typealignvec* vec16;
226 Typealignvec* vec32;
227 int* sizes8;
228 int* sizes16;
229 int* sizes32;
230
231 vec16 = (Typealignvec*)emalloc(sizeof(Typealignvec)*NCTYPES);
232 vec32 = (Typealignvec*)emalloc(sizeof(Typealignvec)*NCTYPES);
233 sizes8 = (int*)emalloc(sizeof(int)*NCTYPES);
234 sizes16 = (int*)emalloc(sizeof(int)*NCTYPES);
235 sizes32 = (int*)emalloc(sizeof(int)*NCTYPES);
236
237 COMP_SIZE0(sizes8[1],char,char);
238 COMP_SIZE0(sizes8[2],unsigned char,char);
239 COMP_SIZE0(sizes8[3],short,char);
240 COMP_SIZE0(sizes8[4],unsigned short,char);
241 COMP_SIZE0(sizes8[5],int,char);
242 COMP_SIZE0(sizes8[6],unsigned int,char);
243 COMP_SIZE0(sizes8[7],long long,char);
244 COMP_SIZE0(sizes8[8],unsigned long long,char);
245 COMP_SIZE0(sizes8[9],float,char);
246 COMP_SIZE0(sizes8[10],double,char) ;
247 COMP_SIZE0(sizes8[11],void*,char);
248 COMP_SIZE0(sizes8[12],nc_vlen_t,char);
249
250 COMP_SIZE0(sizes16[1],char,short);
251 COMP_SIZE0(sizes16[2],unsigned char,short);
252 COMP_SIZE0(sizes16[3],short,short);
253 COMP_SIZE0(sizes16[4],unsigned short,short);
254 COMP_SIZE0(sizes16[5],int,short);
255 COMP_SIZE0(sizes16[6],unsigned int,short);
256 COMP_SIZE0(sizes16[7],long long,short);
257 COMP_SIZE0(sizes16[8],unsigned long long,short);
258 COMP_SIZE0(sizes16[9],float,short);
259 COMP_SIZE0(sizes16[10],double,short) ;
260 COMP_SIZE0(sizes16[11],void*,short);
261 COMP_SIZE0(sizes16[12],nc_vlen_t*,short);
262
263 COMP_SIZE0(sizes32[1],char,int);
264 COMP_SIZE0(sizes32[2],unsigned char,int);
265 COMP_SIZE0(sizes32[3],short,int);
266 COMP_SIZE0(sizes32[4],unsigned short,int);
267 COMP_SIZE0(sizes32[5],int,int);
268 COMP_SIZE0(sizes32[6],unsigned int,int);
269 COMP_SIZE0(sizes32[7],long long,int);
270 COMP_SIZE0(sizes32[8],unsigned long long,int);
271 COMP_SIZE0(sizes32[9],float,int);
272 COMP_SIZE0(sizes32[10],double,int) ;
273 COMP_SIZE0(sizes32[11],void*,int);
274 COMP_SIZE0(sizes32[12],nc_vlen_t*,int);
275
276 COMP_ALIGNMENT1(vec16[1],char,short);
277 COMP_ALIGNMENT1(vec16[2],unsigned char,short);
278 COMP_ALIGNMENT1(vec16[3],short,short);
279 COMP_ALIGNMENT1(vec16[4],unsigned short,short);
280 COMP_ALIGNMENT1(vec16[5],int,short);
281 COMP_ALIGNMENT1(vec16[6],unsigned int,short);
282 COMP_ALIGNMENT1(vec32[7],long long,short);
283 COMP_ALIGNMENT1(vec32[8],unsigned long long,short);
284 COMP_ALIGNMENT1(vec16[9],float,short);
285 COMP_ALIGNMENT1(vec16[10],double,short);
286 COMP_ALIGNMENT1(vec16[11],void*,short);
287 COMP_ALIGNMENT1(vec16[12],nc_vlen_t*,short);
288
289 COMP_ALIGNMENT1(vec32[1],char,short);
290 COMP_ALIGNMENT1(vec32[2],unsigned char,short);
291 COMP_ALIGNMENT1(vec32[3],char,short);
292 COMP_ALIGNMENT1(vec32[4],unsigned short,short);
293 COMP_ALIGNMENT1(vec32[5],int,int);
294 COMP_ALIGNMENT1(vec32[6],unsigned int,int);
295 COMP_ALIGNMENT1(vec32[7],long long,int);
296 COMP_ALIGNMENT1(vec32[8],unsigned long long,int);
297 COMP_ALIGNMENT1(vec32[9],float,int);
298 COMP_ALIGNMENT1(vec32[10],double,int);
299 COMP_ALIGNMENT1(vec32[11],void*,int);
300 COMP_ALIGNMENT1(vec32[12],nc_vlen_t*,int);
301
302 for(i=0;i<NCTYPES;i++) {
303 printf("%s: size=%2d alignment=%2d\n",
304 padname(vec[i].typename),sizes8[i],vec[i].alignment);
305 }
306 for(i=0;i<NCTYPES;i++) {
307 printf("short vs %s: size=%2d alignment=%2d\n",
308 padname(vec[i].typename),sizes16[i],vec16[i].alignment);
309 }
310 for(i=0;i<NCTYPES;i++) {
311 printf("int vs %s: size=%2d alignment=%2d\n",
312 padname(vec[i].typename),sizes32[i],vec32[i].alignment);
313 }
314
315 }
316
317 void *
emalloc(size_t bytes)318 emalloc(size_t bytes) {
319 size_t *memory;
320 memory = malloc(bytes);
321 if(memory == 0) {
322 printf("malloc failed\n");
323 exit(2);
324 }
325 return memory;
326 }
327
328 int
main(int argc,char ** argv)329 main(int argc, char** argv)
330 {
331 int i;
332
333 compute_alignments();
334
335 verify(vec);
336
337 /*
338 for(i=0;i<NCTYPES;i++) {
339 printf("%s:\talignment=%d\n",vec[i].typename,vec[i].alignment);
340 }
341 */
342 exit(0);
343 }
344 #endif /*OFFSETTEST*/
345