1 
2 /* Vis5D version 5.0 */
3 
4 /*
5    Vis5D system for visualizing five dimensional gridded data sets
6    Copyright (C) 1990 - 1997 Bill Hibbard, Johan Kellum, Brian Paul,
7    Dave Santek, and Andre Battaiola.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 1, or (at your option)
12    any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /*
25  * Functions to do binary I/O of floats, ints.
26  *
27  * >>>> These functions are built on top of Unix I/O functions, not stdio! <<<<
28  *
29  * The file format is assumed to be BIG-ENDIAN.
30  * If this code is compiled with -DLITTLE and executes on a little endian
31  * CPU then byte-swapping will be done.
32  *
33  * If an ANSI compiler is used prototypes and ANSI function declarations
34  * are used.  Otherwise use K&R conventions.
35  *
36  * If we're running on a CRAY (8-byte ints and floats), conversions will
37  * be done as needed.
38  */
39 
40 
41 /*
42  * Updates:
43  *
44  * April 13, 1995, brianp
45  *   added cray_to_ieee and iee_to_cray array conversion functions.
46  *   fixed potential cray bug in write_float4_array function.
47  *
48  */
49 
50 
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #ifdef _CRAY
56 #  include <string.h>
57 #include <grass/gis.h>
58 #endif
59 #include "binio.h"
60 
61 
62 
63 
64 /**********************************************************************/
65 
66 /******                     Byte Flipping                         *****/
67 
68 /**********************************************************************/
69 
70 
71 #define FLIP4( n )  (  (n & 0xff000000) >> 24     \
72                      | (n & 0x00ff0000) >> 8      \
73                      | (n & 0x0000ff00) << 8      \
74                      | (n & 0x000000ff) << 24  )
75 
76 
77 #define FLIP2( n )  (((unsigned short) (n & 0xff00)) >> 8  |  (n & 0x00ff) << 8)
78 
79 
80 
81 /*
82  * Flip the order of the 4 bytes in an array of 4-byte words.
83  */
flip4(const unsigned int * src,unsigned int * dest,int n)84 void flip4(const unsigned int *src, unsigned int *dest, int n)
85 {
86     int i;
87 
88     for (i = 0; i < n; i++) {
89 	unsigned int tmp = src[i];
90 
91 	dest[i] = FLIP4(tmp);
92     }
93 }
94 
95 
96 
97 /*
98  * Flip the order of the 2 bytes in an array of 2-byte words.
99  */
flip2(const unsigned short * src,unsigned short * dest,int n)100 void flip2(const unsigned short *src, unsigned short *dest, int n)
101 {
102     int i;
103 
104     for (i = 0; i < n; i++) {
105 	unsigned short tmp = src[i];
106 
107 	dest[i] = FLIP2(tmp);
108     }
109 }
110 
111 
112 #ifdef _CRAY
113 
114 /*****************************************************************************
115 *
116 * The following source code is in the public domain.
117 * Specifically, we give to the public domain all rights for future licensing
118 * of the source code, all resale rights, and all publishing rights.
119 *
120 * We ask, but do not require, that the following message be included in all
121 * derived works:
122 *
123 * Portions developed at the National Center for Supercomputing Applications at
124 * the University of Illinois at Urbana-Champaign.
125 *
126 * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
127 * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
128 * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
129 *
130 ****************************************************************************/
131 
132 /** THESE ROUTINES MUST BE COMPILED ON THE CRAY ONLY SINCE THEY **/
133 
134 /** REQUIRE 8-BYTES PER C-TYPE LONG                             **/
135 
136 /* Cray to IEEE single precision */
c_to_if(long * t,const long * f)137 static void c_to_if(long *t, const long *f)
138 {
139     if (*f != 0) {
140 	*t = (((*f & 0x8000000000000000) |	/* sign bit */
141 	       ((((*f & 0x7fff000000000000) >> 48) - 16258) << 55)) +	/* exp */
142 	      (((*f & 0x00007fffff000000) + ((*f & 0x0000000000800000) << 1)) << 8));	/* mantissa */
143     }
144     else
145 	*t = *f;
146 }
147 
148 
149 #define C_TO_IF( T, F )							\
150 	if (F != 0) {							\
151 		T = (((F & 0x8000000000000000) |			\
152 		((((F & 0x7fff000000000000) >> 48)-16258) << 55)) +	\
153 		(((F & 0x00007fffff000000) +				\
154 		((F & 0x0000000000800000) << 1)) << 8));		\
155 	}								\
156 	else {								\
157 		T = F;							\
158 	}
159 
160 
161 
162 /* IEEE single precison to Cray */
if_to_c(long * t,const long * f)163 static void if_to_c(long *t, const long *f)
164 {
165     if (*f != 0) {
166 	*t = (((*f & 0x8000000000000000) |
167 	       ((*f & 0x7f80000000000000) >> 7) +
168 	       (16258 << 48)) |
169 	      (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000)));
170 	if ((*f << 1) == 0)
171 	    *t = 0;
172     }
173     else
174 	*t = *f;
175 }
176 
177 /* T and F must be longs! */
178 #define IF_TO_C( T, F )							\
179 	if (F != 0) {							\
180 		T = (((F & 0x8000000000000000) |			\
181 		((F & 0x7f80000000000000) >> 7) +			\
182 		(16258 << 48)) |					\
183 		(((F & 0x007fffff00000000) >> 8) | (0x0000800000000000)));  \
184 		if ((F << 1) == 0) T = 0;				\
185 	}								\
186 	else {								\
187 		T = F;							\
188 	}
189 
190 
191 
192 
193 /*
194  * Convert an array of Cray 8-byte floats to an array of IEEE 4-byte floats.
195  */
cray_to_ieee_array(long * dest,const float * source,int n)196 void cray_to_ieee_array(long *dest, const float *source, int n)
197 {
198     long *dst;
199     const long *src;
200     long tmp1, tmp2;
201     int i;
202 
203     dst = dest;
204     src = (const long *)source;
205 
206     for (i = 0; i < n; i += 2) {	/* add 1 in case n is odd */
207 	c_to_if(&tmp1, &src[i]);
208 	c_to_if(&tmp2, &src[i + 1]);
209 	*dst = (tmp1 & 0xffffffff00000000) | (tmp2 >> 32);
210 	dst++;
211     }
212 }
213 
214 
215 
216 /*
217  * Convert an array of IEEE 4-byte floats to an array of 8-byte Cray floats.
218  */
ieee_to_cray_array(float * dest,const long * source,int n)219 void ieee_to_cray_array(float *dest, const long *source, int n)
220 {
221     long *dst;
222     const long *src;
223     int i;
224     long ieee;
225 
226     src = source;
227     dst = (long *)dest;
228 
229     for (i = 0; i < n; i++) {
230 	/* most significant 4-bytes of ieee contain bit pattern to convert */
231 	if ((i & 1) == 0) {
232 	    /* get upper half */
233 	    ieee = src[i / 2] & 0xffffffff00000000;
234 	}
235 	else {
236 	    /* get lower half */
237 	    ieee = src[i / 2] << 32;
238 	}
239 	if_to_c(dst, &ieee);
240 	dst++;
241     }
242 }
243 
244 
245 #endif /*_CRAY*/
246 
247 
248 
249 /**********************************************************************/
250 
251 /*****                     Read Functions                         *****/
252 
253 /**********************************************************************/
254 
255 
256 /*
257  * Read a block of bytes.
258  *  Input:  f - the file descriptor to read from.
259  *         b - address of buffer to read into.
260  *         n - number of bytes to read.
261  * Return:  number of bytes read, 0 if error.
262  */
read_bytes(int f,void * b,int n)263 int read_bytes(int f, void *b, int n)
264 {
265     return read(f, b, n);
266 }
267 
268 
269 
270 /*
271  * Read an array of 2-byte integers.
272  * Input:  f - file descriptor
273  *         iarray - address to put integers
274  *         n - number of integers to read.
275  * Return:  number of integers read.
276  */
read_int2_array(int f,short * iarray,int n)277 int read_int2_array(int f, short *iarray, int n)
278 {
279 #ifdef _CRAY
280     int i;
281     signed char *buffer;
282     int nread;
283 
284     buffer = (signed char *)G_malloc(n * 2);
285     if (!buffer)
286 	return 0;
287     nread = read(f, buffer, n * 2);
288     if (nread <= 0)
289 	return 0;
290     nread /= 2;
291     for (i = 0; i < nread; i++) {
292 	/* don't forget about sign extension! */
293 	iarray[i] = (buffer[i * 2] * 256) | buffer[i * 2 + 1];
294     }
295     G_free(buffer);
296     return nread;
297 #else
298     int nread = read(f, iarray, n * 2);
299 
300     if (nread <= 0)
301 	return 0;
302 #ifdef LITTLE
303     flip2((const unsigned short *)iarray, (unsigned short *)iarray,
304 	  nread / 2);
305 #endif
306     return nread / 2;
307 #endif
308 }
309 
310 
311 
312 /*
313  * Read an array of unsigned 2-byte integers.
314  * Input:  f - file descriptor
315  *         iarray - address to put integers
316  *         n - number of integers to read.
317  * Return:  number of integers read.
318  */
read_uint2_array(int f,unsigned short * iarray,int n)319 int read_uint2_array(int f, unsigned short *iarray, int n)
320 {
321 #ifdef _CRAY
322     int i;
323     unsigned char *buffer;
324     int nread;
325 
326     buffer = (unsigned char *)G_malloc(n * 2);
327     if (!buffer)
328 	return 0;
329     nread = read(f, buffer, n * 2);
330     if (nread <= 0)
331 	return 0;
332     nread /= 2;
333     for (i = 0; i < nread; i++) {
334 	iarray[i] = (buffer[i * 2] << 8) | buffer[i * 2 + 1];
335     }
336     G_free(buffer);
337     return nread;
338 #else
339     int nread = read(f, iarray, n * 2);
340 
341     if (nread <= 0)
342 	return 0;
343 #ifdef LITTLE
344     flip2(iarray, iarray, nread / 2);
345 #endif
346     return nread / 2;
347 #endif
348 }
349 
350 
351 
352 /*
353  * Read a 4-byte integer.
354  * Input:  f - the file descriptor to read from
355  *         i - pointer to integer to put result into.
356  * Return:  1 = ok, 0 = error
357  */
read_int4(int f,int * i)358 int read_int4(int f, int *i)
359 {
360 #ifdef LITTLE
361     /* read big endian and convert to little endian */
362     unsigned int n;
363 
364     if (read(f, &n, 4) == 4) {
365 	*i = FLIP4(n);
366 	return 1;
367     }
368     else {
369 	return 0;
370     }
371 #else
372     if (read(f, i, 4) == 4) {
373 #  ifdef _CRAY
374 	*i = *i >> 32;
375 #  endif
376 	return 1;
377     }
378     else {
379 	return 0;
380     }
381 #endif
382 }
383 
384 
385 
386 /*
387  * Read an array of 4-byte integers.
388  * Input:  f - file descriptor
389  *         iarray - address to put integers
390  *         n - number of integers to read.
391  * Return:  number of integers read.
392  */
read_int4_array(int f,int * iarray,int n)393 int read_int4_array(int f, int *iarray, int n)
394 {
395 #ifdef _CRAY
396     int j, nread;
397     int *buffer;
398 
399     buffer = (int *)G_malloc((n + 1) * 4);
400     if (!buffer)
401 	return 0;
402     nread = read(f, buffer, 4 * n);
403     if (nread <= 0) {
404 	return 0;
405     }
406     nread /= 4;
407 
408     for (j = 0; j < nread; j++) {
409 	if ((j & 1) == 0) {
410 	    iarray[j] = buffer[j / 2] >> 32;
411 	}
412 	else {
413 	    iarray[j] = buffer[j / 2] & 0xffffffff;
414 	}
415     }
416     G_free(buffer);
417     return nread;
418 #else
419     int nread = read(f, iarray, 4 * n);
420 
421     if (nread <= 0)
422 	return 0;
423 #  ifdef LITTLE
424     flip4((const unsigned int *)iarray, (unsigned int *)iarray, nread / 4);
425 #  endif
426     return nread / 4;
427 #endif
428 }
429 
430 
431 
432 /*
433  * Read a 4-byte IEEE float.
434  * Input:  f - the file descriptor to read from.
435  *         x - pointer to float to put result into.
436  * Return:  1 = ok, 0 = error
437  */
read_float4(int f,float * x)438 int read_float4(int f, float *x)
439 {
440 #ifdef _CRAY
441     long buffer = 0;
442 
443     if (read(f, &buffer, 4) == 4) {
444 	/* convert IEEE float (buffer) to Cray float (x) */
445 	if_to_c((long *)x, &buffer);
446 	return 1;
447     }
448     return 0;
449 #else
450 #  ifdef LITTLE
451     unsigned int n, *iptr;
452 
453     if (read(f, &n, 4) == 4) {
454 	iptr = (unsigned int *)x;
455 	*iptr = FLIP4(n);
456 	return 1;
457     }
458     else {
459 	return 0;
460     }
461 #  else
462     if (read(f, x, 4) == 4) {
463 	return 1;
464     }
465     else {
466 	return 0;
467     }
468 #  endif
469 #endif
470 }
471 
472 
473 
474 /*
475  * Read an array of 4-byte IEEE floats.
476  * Input:  f - file descriptor
477  *         x - address to put floats
478  *         n - number of floats to read.
479  * Return:  number of floats read.
480  */
read_float4_array(int f,float * x,int n)481 int read_float4_array(int f, float *x, int n)
482 {
483 #ifdef _CRAY
484     /* read IEEE floats into buffer, then convert to Cray format */
485     long *buffer;
486     int i, nread;
487 
488     buffer = (long *)G_malloc((n + 1) * 4);
489     if (!buffer)
490 	return 0;
491     nread = read(f, buffer, n * 4);
492     if (nread <= 0)
493 	return 0;
494     nread /= 4;
495     ieee_to_cray_array(x, buffer, nread);
496     G_free(buffer);
497     return nread;
498 #else
499     int nread = read(f, x, 4 * n);
500 
501     if (nread <= 0)
502 	return 0;
503 #ifdef LITTLE
504     flip4((const unsigned int *)x, (unsigned int *)x, nread / 4);
505 #endif
506     return nread / 4;
507 #endif
508 }
509 
510 
511 
512 /*
513  * Read a block of memory.
514  * Input:  f - file descriptor
515  *         data - address of first byte
516  *         elements - number of elements to read
517  *         elsize - size of each element to read (1, 2 or 4)
518  * Return: number of elements written
519  */
read_block(int f,void * data,int elements,int elsize)520 int read_block(int f, void *data, int elements, int elsize)
521 {
522     if (elsize == 1) {
523 	return read(f, data, elements);
524     }
525     else if (elsize == 2) {
526 #ifdef LITTLE
527 	int n;
528 
529 	n = read(f, data, elements * 2) / 2;
530 	if (n == elements) {
531 	    flip2((const unsigned short *)data, (unsigned short *)data,
532 		  elements);
533 	}
534 	return n;
535 #else
536 	return read(f, data, elements * 2) / 2;
537 #endif
538     }
539     else if (elsize == 4) {
540 #ifdef LITTLE
541 	int n;
542 
543 	n = read(f, data, elements * 4) / 4;
544 	if (n == elements) {
545 	    flip4((const unsigned int *)data, (unsigned int *)data, elements);
546 	}
547 	return n;
548 #else
549 	return read(f, data, elements * 4) / 4;
550 #endif
551     }
552     else {
553 	printf("Fatal error in read_block(): bad elsize (%d)\n", elsize);
554 	abort();
555     }
556     return 0;
557 }
558 
559 
560 
561 
562 /**********************************************************************/
563 
564 /*****                         Write Functions                    *****/
565 
566 /**********************************************************************/
567 
568 
569 
570 /*
571  * Write a block of bytes.
572  * Input:  f - the file descriptor to write to.
573  *         b - address of buffer to write.
574  *         n - number of bytes to write.
575  * Return:  number of bytes written, 0 if error.
576  */
write_bytes(int f,const void * b,int n)577 int write_bytes(int f, const void *b, int n)
578 {
579     return write(f, b, n);
580 }
581 
582 
583 
584 
585 /*
586  * Write an array of 2-byte integers.
587  * Input:  f - file descriptor
588  *         iarray - address to put integers
589  *         n - number of integers to write.
590  * Return:  number of integers written
591  */
write_int2_array(int f,const short * iarray,int n)592 int write_int2_array(int f, const short *iarray, int n)
593 {
594 #ifdef _CRAY
595     printf("write_int2_array not implemented!\n");
596     exit(1);
597 #else
598     int nwritten;
599 
600 #ifdef LITTLE
601     flip2((const unsigned short *)iarray, (unsigned short *)iarray, n);
602 #endif
603     nwritten = write(f, iarray, 2 * n);
604 #ifdef LITTLE
605     flip2((const unsigned short *)iarray, (unsigned short *)iarray, n);
606 #endif
607     if (nwritten <= 0)
608 	return 0;
609     return nwritten / 2;
610 #endif
611 }
612 
613 
614 
615 /*
616  * Write an array of 2-byte unsigned integers.
617  * Input:  f - file descriptor
618  *         iarray - address to put integers
619  *         n - number of integers to write.
620  * Return:  number of integers written
621  */
write_uint2_array(int f,const unsigned short * iarray,int n)622 int write_uint2_array(int f, const unsigned short *iarray, int n)
623 {
624 #ifdef _CRAY
625     int i, nwritten;
626     unsigned char *buffer;
627 
628     buffer = (unsigned char *)G_malloc(2 * n);
629     if (!buffer)
630 	return 0;
631     for (i = 0; i < n; i++) {
632 	buffer[i * 2] = (iarray[i] >> 8) & 0xff;
633 	buffer[i * 2 + 1] = iarray[i] & 0xff;
634     }
635     nwritten = write(f, buffer, 2 * n);
636     G_free(buffer);
637     if (nwritten <= 0)
638 	return 0;
639     else
640 	return nwritten / 2;
641 #else
642     int nwritten;
643 
644 #ifdef LITTLE
645     flip2(iarray, (unsigned short *)iarray, n);
646 #endif
647     nwritten = write(f, iarray, 2 * n);
648 #ifdef LITTLE
649     flip2(iarray, (unsigned short *)iarray, n);
650 #endif
651     if (nwritten <= 0)
652 	return 0;
653     else
654 	return nwritten / 2;
655 #endif
656 }
657 
658 
659 
660 /*
661  * Write a 4-byte integer.
662  *Input:  f - the file descriptor
663  *         i - the integer
664  * Return:  1 = ok, 0 = error
665  */
write_int4(int f,int i)666 int write_int4(int f, int i)
667 {
668 #ifdef _CRAY
669     i = i << 32;
670     return write(f, &i, 4) > 0;
671 #else
672 #  ifdef LITTLE
673     i = FLIP4(i);
674 #  endif
675     return write(f, &i, 4) > 0;
676 #endif
677 }
678 
679 
680 
681 /*
682  * Write an array of 4-byte integers.
683  * Input:  f - the file descriptor
684  *         i - the array of ints
685  *           n - the number of ints in array
686  *  Return:  number of integers written.
687  */
write_int4_array(int f,const int * i,int n)688 int write_int4_array(int f, const int *i, int n)
689 {
690 #ifdef _CRAY
691     int j, nwritten;
692     char *buf, *b, *ptr;
693 
694     b = buf = (char *)G_malloc(n * 4 + 8);
695     if (!b)
696 	return 0;
697     ptr = (char *)i;
698     for (j = 0; j < n; j++) {
699 	ptr += 4;		/* skip upper 4 bytes */
700 	*b++ = *ptr++;
701 	*b++ = *ptr++;
702 	*b++ = *ptr++;
703 	*b++ = *ptr++;
704     }
705     nwritten = write(f, buf, 4 * n);
706     G_free(buf);
707     if (nwritten <= 0)
708 	return 0;
709     else
710 	return nwritten / 4;
711 #else
712 #  ifdef LITTLE
713     int nwritten;
714 
715     flip4((const unsigned int *)i, (unsigned int *)i, n);
716     nwritten = write(f, i, 4 * n);
717     flip4((const unsigned int *)i, (unsigned int *)i, n);
718     if (nwritten <= 0)
719 	return 0;
720     else
721 	return nwritten / 4;
722 #  else
723     return write(f, i, 4 * n) / 4;
724 #  endif
725 #endif
726 }
727 
728 
729 
730 /*
731  * Write a 4-byte IEEE float.
732  * Input:  f - the file descriptor
733  *         x - the float
734  * Return:  1 = ok, 0 = error
735  */
write_float4(int f,float x)736 int write_float4(int f, float x)
737 {
738 #ifdef _CRAY
739     char buffer[8];
740 
741     c_to_if((long *)buffer, (const long *)&x);
742     return write(f, buffer, 4) > 0;
743 #else
744 #  ifdef LITTLE
745     float y;
746     unsigned int *iptr = (unsigned int *)&y, temp;
747 
748     y = (float)x;
749     temp = FLIP4(*iptr);
750     return write(f, &temp, 4) > 0;
751 #  else
752     float y;
753 
754     y = (float)x;
755     return write(f, &y, 4) > 0;
756 #  endif
757 #endif
758 }
759 
760 
761 
762 /*
763  * Write an array of 4-byte IEEE floating point numbers.
764  * Input:  f - the file descriptor
765  *         x - the array of floats
766  *         n - number of floats in array
767  * Return:  number of float written.
768  */
write_float4_array(int f,const float * x,int n)769 int write_float4_array(int f, const float *x, int n)
770 {
771 #ifdef _CRAY
772     /* convert cray floats to IEEE and put into buffer */
773     int nwritten;
774     long *buffer;
775 
776     buffer = (long *)G_malloc(n * 4 + 8);
777     if (!buffer)
778 	return 0;
779     cray_to_ieee_array(buffer, x, n);
780     nwritten = write(f, buffer, 4 * n);
781     G_free(buffer);
782     if (nwritten <= 0)
783 	return 0;
784     else
785 	return nwritten / 4;
786 #else
787 #  ifdef LITTLE
788     int nwritten;
789 
790     flip4((const unsigned int *)x, (unsigned int *)x, n);
791     nwritten = write(f, x, 4 * n);
792     flip4((const unsigned int *)x, (unsigned int *)x, n);
793     if (nwritten <= 0)
794 	return 0;
795     else
796 	return nwritten / 4;
797 #  else
798     return write(f, x, 4 * n) / 4;
799 #  endif
800 #endif
801 }
802 
803 
804 
805 /*
806  * Write a block of memory.
807  * Input:  f - file descriptor
808  *         data - address of first byte
809  *         elements - number of elements to write
810  *         elsize - size of each element to write (1, 2 or 4)
811  * Return: number of elements written
812  */
write_block(int f,const void * data,int elements,int elsize)813 int write_block(int f, const void *data, int elements, int elsize)
814 {
815     if (elsize == 1) {
816 	return write(f, data, elements);
817     }
818     else if (elsize == 2) {
819 #ifdef LITTLE
820 	int n;
821 
822 	flip2((const unsigned short *)data, (unsigned short *)data, elements);
823 	n = write(f, data, elements * 2) / 2;
824 	flip2((const unsigned short *)data, (unsigned short *)data, elements);
825 	return n;
826 #else
827 	return write(f, data, elements * 2) / 2;
828 #endif
829     }
830     else if (elsize == 4) {
831 #ifdef LITTLE
832 	int n;
833 
834 	flip4((const unsigned int *)data, (unsigned int *)data, elements);
835 	n = write(f, data, elements * 4) / 4;
836 	flip4((const unsigned int *)data, (unsigned int *)data, elements);
837 	return n;
838 #else
839 	return write(f, data, elements * 4) / 4;
840 #endif
841     }
842     else {
843 	printf("Fatal error in write_block(): bad elsize (%d)\n", elsize);
844 	abort();
845     }
846     return 0;
847 }
848