1dnl This is m4 source.
2dnl Process using m4 to produce 'C' language file.
3dnl
4dnl If you see this line, you can ignore the next one.
5/* Do not edit this file. It is produced from the corresponding .m4 source */
6dnl
7/*
8 *	Copyright 1996, University Corporation for Atmospheric Research
9 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
10 */
11/* $Id: attr.m4,v 2.39 2010/05/26 18:11:08 dmh Exp $ */
12
13#include "nc.h"
14#include "ncdispatch.h"
15#include "nc3dispatch.h"
16#include <stdlib.h>
17#include <string.h>
18#include <assert.h>
19#include "ncx.h"
20#include "fbits.h"
21#include "rnd.h"
22#include "utf8proc.h"
23
24
25/*
26 * Free attr
27 * Formerly
28NC_free_attr()
29 */
30void
31free_NC_attr(NC_attr *attrp)
32{
33
34	if(attrp == NULL)
35		return;
36	free_NC_string(attrp->name);
37	free(attrp);
38}
39
40
41/*
42 * How much space will 'nelems' of 'type' take in
43 *  external representation (as the values of an attribute)?
44 */
45static size_t
46ncx_len_NC_attrV(nc_type type, size_t nelems)
47{
48	switch(type) {
49	case NC_BYTE:
50	case NC_CHAR:
51		return ncx_len_char(nelems);
52	case NC_SHORT:
53		return ncx_len_short(nelems);
54	case NC_INT:
55		return ncx_len_int(nelems);
56	case NC_FLOAT:
57		return ncx_len_float(nelems);
58	case NC_DOUBLE:
59		return ncx_len_double(nelems);
60	default:
61	        assert("ncx_len_NC_attr bad type" == 0);
62	}
63	return 0;
64}
65
66
67NC_attr *
68new_x_NC_attr(
69	NC_string *strp,
70	nc_type type,
71	size_t nelems)
72{
73	NC_attr *attrp;
74	const size_t xsz = ncx_len_NC_attrV(type, nelems);
75	size_t sz = M_RNDUP(sizeof(NC_attr));
76
77	assert(!(xsz == 0 && nelems != 0));
78
79	sz += xsz;
80
81	attrp = (NC_attr *) malloc(sz);
82	if(attrp == NULL )
83		return NULL;
84
85	attrp->xsz = xsz;
86
87	attrp->name = strp;
88	attrp->type = type;
89	attrp->nelems = nelems;
90	if(xsz != 0)
91		attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
92	else
93		attrp->xvalue = NULL;
94
95	return(attrp);
96}
97
98
99/*
100 * Formerly
101NC_new_attr(name,type,count,value)
102 */
103static NC_attr *
104new_NC_attr(
105	const char *uname,
106	nc_type type,
107	size_t nelems)
108{
109	NC_string *strp;
110	NC_attr *attrp;
111
112	char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
113	if(name == NULL)
114	    return NULL;
115	assert(name != NULL && *name != 0);
116
117	strp = new_NC_string(strlen(name), name);
118	free(name);
119	if(strp == NULL)
120		return NULL;
121
122	attrp = new_x_NC_attr(strp, type, nelems);
123	if(attrp == NULL)
124	{
125		free_NC_string(strp);
126		return NULL;
127	}
128
129	return(attrp);
130}
131
132
133static NC_attr *
134dup_NC_attr(const NC_attr *rattrp)
135{
136	NC_attr *attrp = new_NC_attr(rattrp->name->cp,
137		 rattrp->type, rattrp->nelems);
138	if(attrp == NULL)
139		return NULL;
140	(void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
141	return attrp;
142}
143
144/* attrarray */
145
146/*
147 * Free the stuff "in" (referred to by) an NC_attrarray.
148 * Leaves the array itself allocated.
149 */
150void
151free_NC_attrarrayV0(NC_attrarray *ncap)
152{
153	assert(ncap != NULL);
154
155	if(ncap->nelems == 0)
156		return;
157
158	assert(ncap->value != NULL);
159
160	{
161		NC_attr **app = ncap->value;
162		NC_attr *const *const end = &app[ncap->nelems];
163		for( /*NADA*/; app < end; app++)
164		{
165			free_NC_attr(*app);
166			*app = NULL;
167		}
168	}
169	ncap->nelems = 0;
170}
171
172
173/*
174 * Free NC_attrarray values.
175 * formerly
176NC_free_array()
177 */
178void
179free_NC_attrarrayV(NC_attrarray *ncap)
180{
181	assert(ncap != NULL);
182
183	if(ncap->nalloc == 0)
184		return;
185
186	assert(ncap->value != NULL);
187
188	free_NC_attrarrayV0(ncap);
189
190	free(ncap->value);
191	ncap->value = NULL;
192	ncap->nalloc = 0;
193}
194
195
196int
197dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
198{
199	int status = NC_NOERR;
200
201	assert(ref != NULL);
202	assert(ncap != NULL);
203
204	if(ref->nelems != 0)
205	{
206		const size_t sz = ref->nelems * sizeof(NC_attr *);
207		ncap->value = (NC_attr **) malloc(sz);
208		if(ncap->value == NULL)
209			return NC_ENOMEM;
210
211		(void) memset(ncap->value, 0, sz);
212		ncap->nalloc = ref->nelems;
213	}
214
215	ncap->nelems = 0;
216	{
217		NC_attr **app = ncap->value;
218		const NC_attr **drpp = (const NC_attr **)ref->value;
219		NC_attr *const *const end = &app[ref->nelems];
220		for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++)
221		{
222			*app = dup_NC_attr(*drpp);
223			if(*app == NULL)
224			{
225				status = NC_ENOMEM;
226				break;
227			}
228		}
229	}
230
231	if(status != NC_NOERR)
232	{
233		free_NC_attrarrayV(ncap);
234		return status;
235	}
236
237	assert(ncap->nelems == ref->nelems);
238
239	return NC_NOERR;
240}
241
242
243/*
244 * Add a new handle on the end of an array of handles
245 * Formerly
246NC_incr_array(array, tail)
247 */
248static int
249incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
250{
251	NC_attr **vp;
252
253	assert(ncap != NULL);
254
255	if(ncap->nalloc == 0)
256	{
257		assert(ncap->nelems == 0);
258		vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
259		if(vp == NULL)
260			return NC_ENOMEM;
261
262		ncap->value = vp;
263		ncap->nalloc = NC_ARRAY_GROWBY;
264	}
265	else if(ncap->nelems +1 > ncap->nalloc)
266	{
267		vp = (NC_attr **) realloc(ncap->value,
268			(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
269		if(vp == NULL)
270			return NC_ENOMEM;
271
272		ncap->value = vp;
273		ncap->nalloc += NC_ARRAY_GROWBY;
274	}
275
276	if(newelemp != NULL)
277	{
278		ncap->value[ncap->nelems] = newelemp;
279		ncap->nelems++;
280	}
281	return NC_NOERR;
282}
283
284
285NC_attr *
286elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
287{
288	assert(ncap != NULL);
289	/* cast needed for braindead systems with signed size_t */
290	if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
291		return NULL;
292
293	assert(ncap->value != NULL);
294
295	return ncap->value[elem];
296}
297
298/* End attarray per se */
299
300/*
301 * Given ncp and varid, return ptr to array of attributes
302 *  else NULL on error
303 */
304static NC_attrarray *
305NC_attrarray0( NC *ncp, int varid)
306{
307	NC_attrarray *ap;
308
309	if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
310	{
311		ap = &ncp->attrs;
312	}
313	else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
314	{
315		NC_var **vpp;
316		vpp = (NC_var **)ncp->vars.value;
317		vpp += varid;
318		ap = &(*vpp)->attrs;
319	} else {
320		ap = NULL;
321	}
322	return(ap);
323}
324
325
326/*
327 * Step thru NC_ATTRIBUTE array, seeking match on name.
328 *  return match or NULL if Not Found or out of memory.
329 */
330NC_attr **
331NC_findattr(const NC_attrarray *ncap, const char *uname)
332{
333	NC_attr **attrpp;
334	size_t attrid;
335	size_t slen;
336	char *name;
337
338	assert(ncap != NULL);
339
340	if(ncap->nelems == 0)
341		return NULL;
342
343	attrpp = (NC_attr **) ncap->value;
344
345	/* normalized version of uname */
346	name = (char *)utf8proc_NFC((const unsigned char *)uname);
347	if(name == NULL)
348	    return NULL; /* TODO: need better way to indicate no memory */
349	slen = strlen(name);
350
351	for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
352	{
353		if(strlen((*attrpp)->name->cp) == slen &&
354			strncmp((*attrpp)->name->cp, name, slen) == 0)
355		{
356		        free(name);
357			return(attrpp); /* Normal return */
358		}
359	}
360	free(name);
361	return(NULL);
362}
363
364
365/*
366 * Look up by ncid, varid and name, return NULL if not found
367 */
368static int
369NC_lookupattr(int ncid,
370	int varid,
371	const char *name, /* attribute name */
372	NC_attr **attrpp) /* modified on return */
373{
374	int status;
375	NC *ncp;
376	NC_attrarray *ncap;
377	NC_attr **tmp;
378
379	status = NC_check_id(ncid, &ncp);
380	if(status != NC_NOERR)
381		return status;
382
383	ncap = NC_attrarray0(ncp, varid);
384	if(ncap == NULL)
385		return NC_ENOTVAR;
386
387	tmp = NC_findattr(ncap, name);
388	if(tmp == NULL)
389		return NC_ENOTATT;
390
391	if(attrpp != NULL)
392		*attrpp = *tmp;
393
394	return ENOERR;
395}
396
397/* Public */
398
399int
400NC3_inq_attname(int ncid, int varid, int attnum, char *name)
401{
402	int status;
403	NC *ncp;
404	NC_attrarray *ncap;
405	NC_attr *attrp;
406
407	status = NC_check_id(ncid, &ncp);
408	if(status != NC_NOERR)
409		return status;
410
411	ncap = NC_attrarray0(ncp, varid);
412	if(ncap == NULL)
413		return NC_ENOTVAR;
414
415	attrp = elem_NC_attrarray(ncap, (size_t)attnum);
416	if(attrp == NULL)
417		return NC_ENOTATT;
418
419	(void) strncpy(name, attrp->name->cp, attrp->name->nchars);
420	name[attrp->name->nchars] = 0;
421
422	return NC_NOERR;
423}
424
425
426int
427NC3_inq_attid(int ncid, int varid, const char *name, int *attnump)
428{
429	int status;
430	NC *ncp;
431	NC_attrarray *ncap;
432	NC_attr **attrpp;
433
434	status = NC_check_id(ncid, &ncp);
435	if(status != NC_NOERR)
436		return status;
437
438	ncap = NC_attrarray0(ncp, varid);
439	if(ncap == NULL)
440		return NC_ENOTVAR;
441
442
443	attrpp = NC_findattr(ncap, name);
444	if(attrpp == NULL)
445		return NC_ENOTATT;
446
447	if(attnump != NULL)
448		*attnump = (int)(attrpp - ncap->value);
449
450	return NC_NOERR;
451}
452
453int
454NC3_inq_att(int ncid,
455	int varid,
456	const char *name, /* input, attribute name */
457	nc_type *datatypep,
458	size_t *lenp)
459{
460	int status;
461	NC_attr *attrp;
462
463	status = NC_lookupattr(ncid, varid, name, &attrp);
464	if(status != NC_NOERR)
465		return status;
466
467	if(datatypep != NULL)
468		*datatypep = attrp->type;
469	if(lenp != NULL)
470		*lenp = attrp->nelems;
471
472	return NC_NOERR;
473}
474
475
476int
477NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
478{
479	int status;
480	NC *ncp;
481	NC_attrarray *ncap;
482	NC_attr **tmp;
483	NC_attr *attrp;
484	NC_string *newStr, *old;
485	char *newname;  /* normalized version */
486
487			/* sortof inline clone of NC_lookupattr() */
488	status = NC_check_id(ncid, &ncp);
489	if(status != NC_NOERR)
490		return status;
491
492	if(NC_readonly(ncp))
493		return NC_EPERM;
494
495	ncap = NC_attrarray0(ncp, varid);
496	if(ncap == NULL)
497		return NC_ENOTVAR;
498
499	status = NC_check_name(unewname);
500	if(status != NC_NOERR)
501		return status;
502
503	tmp = NC_findattr(ncap, name);
504	if(tmp == NULL)
505		return NC_ENOTATT;
506	attrp = *tmp;
507			/* end inline clone NC_lookupattr() */
508
509	if(NC_findattr(ncap, unewname) != NULL)
510	{
511		/* name in use */
512		return NC_ENAMEINUSE;
513	}
514
515	old = attrp->name;
516	newname = (char *)utf8proc_NFC((const unsigned char *)unewname);
517	if(newname == NULL)
518	    return NC_EBADNAME;
519	if(NC_indef(ncp))
520	{
521		newStr = new_NC_string(strlen(newname), newname);
522		free(newname);
523		if( newStr == NULL)
524			return NC_ENOMEM;
525		attrp->name = newStr;
526		free_NC_string(old);
527		return NC_NOERR;
528	}
529	/* else */
530	status = set_NC_string(old, newname);
531	free(newname);
532	if( status != NC_NOERR)
533		return status;
534
535	set_NC_hdirty(ncp);
536
537	if(NC_doHsync(ncp))
538	{
539		status = NC_sync(ncp);
540		if(status != NC_NOERR)
541			return status;
542	}
543
544	return NC_NOERR;
545}
546
547int
548NC3_del_att(int ncid, int varid, const char *uname)
549{
550	int status;
551	NC *ncp;
552	NC_attrarray *ncap;
553	NC_attr **attrpp;
554	NC_attr *old = NULL;
555	int attrid;
556	size_t slen;
557
558	status = NC_check_id(ncid, &ncp);
559	if(status != NC_NOERR)
560		return status;
561
562	if(!NC_indef(ncp))
563		return NC_ENOTINDEFINE;
564
565	ncap = NC_attrarray0(ncp, varid);
566	if(ncap == NULL)
567		return NC_ENOTVAR;
568
569	{
570	char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
571	if(name == NULL)
572	    return NC_ENOMEM;
573
574			/* sortof inline NC_findattr() */
575	slen = strlen(name);
576
577	attrpp = (NC_attr **) ncap->value;
578	for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
579	    {
580		if( slen == (*attrpp)->name->nchars &&
581			strncmp(name, (*attrpp)->name->cp, slen) == 0)
582		{
583			old = *attrpp;
584			break;
585		}
586	    }
587	free(name);
588	}
589	if( (size_t) attrid == ncap->nelems )
590		return NC_ENOTATT;
591			/* end inline NC_findattr() */
592
593	/* shuffle down */
594	for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
595	{
596		*attrpp = *(attrpp + 1);
597		attrpp++;
598	}
599	*attrpp = NULL;
600	/* decrement count */
601	ncap->nelems--;
602
603	free_NC_attr(old);
604
605	return NC_NOERR;
606}
607
608dnl
609dnl XNCX_PAD_PUTN(Type)
610dnl
611define(`XNCX_PAD_PUTN',dnl
612`dnl
613static int
614ncx_pad_putn_I$1(void **xpp, size_t nelems, const $1 *tp, nc_type type)
615{
616	switch(type) {
617	case NC_CHAR:
618		return NC_ECHAR;
619	case NC_BYTE:
620		return ncx_pad_putn_schar_$1(xpp, nelems, tp);
621	case NC_SHORT:
622		return ncx_pad_putn_short_$1(xpp, nelems, tp);
623	case NC_INT:
624		return ncx_putn_int_$1(xpp, nelems, tp);
625	case NC_FLOAT:
626		return ncx_putn_float_$1(xpp, nelems, tp);
627	case NC_DOUBLE:
628		return ncx_putn_double_$1(xpp, nelems, tp);
629	default:
630                assert("ncx_pad_putn_I$1 invalid type" == 0);
631	}
632	return NC_EBADTYPE;
633}
634')dnl
635dnl
636dnl XNCX_PAD_GETN(Type)
637dnl
638define(`XNCX_PAD_GETN',dnl
639`dnl
640static int
641ncx_pad_getn_I$1(const void **xpp, size_t nelems, $1 *tp, nc_type type)
642{
643	switch(type) {
644	case NC_CHAR:
645		return NC_ECHAR;
646	case NC_BYTE:
647		return ncx_pad_getn_schar_$1(xpp, nelems, tp);
648	case NC_SHORT:
649		return ncx_pad_getn_short_$1(xpp, nelems, tp);
650	case NC_INT:
651		return ncx_getn_int_$1(xpp, nelems, tp);
652	case NC_FLOAT:
653		return ncx_getn_float_$1(xpp, nelems, tp);
654	case NC_DOUBLE:
655		return ncx_getn_double_$1(xpp, nelems, tp);
656	default:
657	        assert("ncx_pad_getn_I$1 invalid type" == 0);
658	}
659	return NC_EBADTYPE;
660}
661')dnl
662dnl Implement
663
664XNCX_PAD_PUTN(uchar)
665XNCX_PAD_GETN(uchar)
666
667XNCX_PAD_PUTN(schar)
668XNCX_PAD_GETN(schar)
669
670XNCX_PAD_PUTN(short)
671XNCX_PAD_GETN(short)
672
673XNCX_PAD_PUTN(int)
674XNCX_PAD_GETN(int)
675
676XNCX_PAD_PUTN(float)
677XNCX_PAD_GETN(float)
678
679XNCX_PAD_PUTN(double)
680XNCX_PAD_GETN(double)
681
682#ifdef IGNORE
683XNCX_PAD_PUTN(long)
684XNCX_PAD_GETN(long)
685#endif
686
687XNCX_PAD_PUTN(longlong)
688XNCX_PAD_GETN(longlong)
689
690
691/* Common dispatcher for put cases */
692static int
693dispatchput(void **xpp, size_t nelems, const void* tp,
694	    nc_type atype, nc_type memtype)
695{
696    switch (memtype) {
697    case NC_CHAR:
698        return ncx_pad_putn_text(xpp,nelems, (char *)tp);
699    case NC_BYTE:
700        return ncx_pad_putn_Ischar(xpp, nelems, (schar*)tp, atype);
701    case NC_SHORT:
702        return ncx_pad_putn_Ishort(xpp, nelems, (short*)tp, atype);
703    case NC_INT:
704          return ncx_pad_putn_Iint(xpp, nelems, (int*)tp, atype);
705    case NC_FLOAT:
706        return ncx_pad_putn_Ifloat(xpp, nelems, (float*)tp, atype);
707    case NC_DOUBLE:
708        return ncx_pad_putn_Idouble(xpp, nelems, (double*)tp, atype);
709    case NC_UBYTE: /*Synthetic*/
710        return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tp, atype);
711    case NC_INT64:
712          return ncx_pad_putn_Ilonglong(xpp, nelems, (longlong*)tp, atype);
713    case NC_NAT:
714        return NC_EBADTYPE;
715    default:
716        break;
717    }
718    return NC_EBADTYPE;
719}
720
721int
722NC3_put_att(
723	int ncid,
724	int varid,
725	const char *name,
726	nc_type type,
727	size_t nelems,
728	const void *value,
729	nc_type memtype)
730{
731    int status;
732    NC *ncp;
733    NC_attrarray *ncap;
734    NC_attr **attrpp;
735    NC_attr *old = NULL;
736    NC_attr *attrp;
737
738    status = NC_check_id(ncid, &ncp);
739    if(status != NC_NOERR)
740	return status;
741
742    if(NC_readonly(ncp))
743	return NC_EPERM;
744
745    ncap = NC_attrarray0(ncp, varid);
746    if(ncap == NULL)
747	return NC_ENOTVAR;
748
749    status = nc_cktype(type);
750    if(status != NC_NOERR)
751	return status;
752
753    if(memtype == NC_NAT) memtype = type;
754
755    if(memtype != NC_CHAR && type == NC_CHAR)
756	return NC_ECHAR;
757    if(memtype == NC_CHAR && type != NC_CHAR)
758	return NC_ECHAR;
759
760    /* cast needed for braindead systems with signed size_t */
761    if((unsigned long) nelems > X_INT_MAX) /* backward compat */
762	return NC_EINVAL; /* Invalid nelems */
763
764    if(nelems != 0 && value == NULL)
765	return NC_EINVAL; /* Null arg */
766
767    attrpp = NC_findattr(ncap, name);
768
769    /* 4 cases: exists X indef */
770
771    if(attrpp != NULL) { /* name in use */
772        if(!NC_indef(ncp)) {
773	    const size_t xsz = ncx_len_NC_attrV(type, nelems);
774            attrp = *attrpp; /* convenience */
775
776	    if(xsz > attrp->xsz) return NC_ENOTINDEFINE;
777	    /* else, we can reuse existing without redef */
778
779	    attrp->xsz = xsz;
780            attrp->type = type;
781            attrp->nelems = nelems;
782
783            if(nelems != 0) {
784                void *xp = attrp->xvalue;
785                status = dispatchput(&xp, nelems, (const void*)value, type, memtype);
786            }
787
788            set_NC_hdirty(ncp);
789
790            if(NC_doHsync(ncp)) {
791	        const int lstatus = NC_sync(ncp);
792                /*
793                 * N.B.: potentially overrides NC_ERANGE
794                 * set by ncx_pad_putn_I$1
795                 */
796                if(lstatus != ENOERR) return lstatus;
797            }
798
799            return status;
800        }
801        /* else, redefine using existing array slot */
802        old = *attrpp;
803    } else {
804        if(!NC_indef(ncp)) return NC_ENOTINDEFINE;
805
806        if(ncap->nelems >= NC_MAX_ATTRS) return NC_EMAXATTS;
807    }
808
809    status = NC_check_name(name);
810    if(status != NC_NOERR) return status;
811
812    attrp = new_NC_attr(name, type, nelems);
813    if(attrp == NULL) return NC_ENOMEM;
814
815    if(nelems != 0) {
816        void *xp = attrp->xvalue;
817        status = dispatchput(&xp, nelems, (const void*)value, type, memtype);
818    }
819
820    if(attrpp != NULL) {
821        assert(old != NULL);
822        *attrpp = attrp;
823        free_NC_attr(old);
824    } else {
825        const int lstatus = incr_NC_attrarray(ncap, attrp);
826        /*
827         * N.B.: potentially overrides NC_ERANGE
828         * set by ncx_pad_putn_I$1
829         */
830        if(lstatus != NC_NOERR) {
831           free_NC_attr(attrp);
832           return lstatus;
833        }
834    }
835    return status;
836}
837
838int
839NC3_get_att(
840	int ncid,
841	int varid,
842	const char *name,
843	void *value,
844	nc_type memtype)
845{
846    int status;
847    NC_attr *attrp;
848    const void *xp;
849
850    status = NC_lookupattr(ncid, varid, name, &attrp);
851    if(status != NC_NOERR) return status;
852
853    if(attrp->nelems == 0) return NC_NOERR;
854
855    if(memtype == NC_NAT) memtype = attrp->type;
856
857    if(memtype != NC_CHAR && attrp->type == NC_CHAR)
858	return NC_ECHAR;
859    if(memtype == NC_CHAR && attrp->type != NC_CHAR)
860	return NC_ECHAR;
861
862    xp = attrp->xvalue;
863    switch (memtype) {
864    case NC_CHAR:
865        return ncx_pad_getn_text(&xp, attrp->nelems , (char *)value);
866    case NC_BYTE:
867        return ncx_pad_getn_Ischar(&xp,attrp->nelems,(schar*)value,attrp->type);
868    case NC_SHORT:
869        return ncx_pad_getn_Ishort(&xp,attrp->nelems,(short*)value,attrp->type);
870    case NC_INT:
871          return ncx_pad_getn_Iint(&xp,attrp->nelems,(int*)value,attrp->type);
872    case NC_FLOAT:
873        return ncx_pad_getn_Ifloat(&xp,attrp->nelems,(float*)value,attrp->type);
874    case NC_DOUBLE:
875        return ncx_pad_getn_Idouble(&xp,attrp->nelems,(double*)value,attrp->type);
876    case NC_INT64:
877          return ncx_pad_getn_Ilonglong(&xp,attrp->nelems,(longlong*)value,attrp->type);
878    case NC_UBYTE: /* Synthetic */
879        return ncx_pad_getn_Iuchar(&xp, attrp->nelems , (uchar *)value, attrp->type);
880    case NC_NAT:
881        return NC_EBADTYPE;
882    default:
883        break;
884    }
885    status =  NC_EBADTYPE;
886    return status;
887}
888
889