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