home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / hdf / unix / hdf3_2r2 / src / dfsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-30  |  125.2 KB  |  3,724 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.9 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/src/RCS/dfsd.c,v 1.9 1992/10/30 18:36:52 koziol beta koziol $
  30.  
  31. $Log: dfsd.c,v $
  32.  * Revision 1.9  1992/10/30  18:36:52  koziol
  33.  * Fixed casts in a bunch of functions to make the SGI ANSI compiler happy
  34.  *
  35.  * Revision 1.8  1992/10/27  22:18:31  koziol
  36.  * changed DFSDpre32() call to return true or false instead of storing results
  37.  * in parameter
  38.  *
  39.  * Revision 1.7  1992/10/23  00:14:11  koziol
  40.  * Changed all DFIstr*() and DFImem*() calls to HDstr*() and HDmem*() calls
  41.  * #ifdef'd out the macros Jason defined for Hopen, Hclose, etc. for Vsets
  42.  * Replaced Vset VFREESPACE and VGETSPACE calls with actual calls to HDfreespace
  43.  * and HDgetspace
  44.  * Added a MS-Windows lower lower for file I/O (which may not be completely working
  45.  *
  46.  * Revision 1.5  1992/10/13  18:46:55  koziol
  47.  * Fixed calls to HDmemcpy() to not bother to check the return value
  48.  *
  49.  * Revision 1.4  1992/10/12  18:11:51  koziol
  50.  * Updated for v3.2r2 release
  51.  *
  52.  * Revision 1.3  1992/09/18  15:03:29  koziol
  53.  * Removed Chris' printf's for calibration stuff
  54.  *
  55.  * Revision 1.2  1992/08/27  22:18:42  chouck
  56.  * Added support for calibration tag reading and writing
  57.  *
  58.  * Revision 1.1  1992/08/25  21:40:44  koziol
  59.  * Initial revision
  60.  *
  61. */
  62. /*-----------------------------------------------------------------------------
  63.  File:  dfsd.c
  64.  
  65.  Purpose:
  66.     Routines for input and output of numeric data group
  67.  
  68.  Invokes:
  69.     df.c dfgroup.c dfkit.c dfi.h df.h dfsd.h
  70.  
  71.  Public functions:
  72.     DFSDgetdims - get rank and dim sizes
  73.     DFSDgetdatastrs - get label, unit, format and coord system of data
  74.     DFSDgetdimstrs - get label, unit and format for a dimension
  75.     DFSDgetdatalen - 
  76.     DFSDgetdimlen -
  77.     DFSDgetdimscale - get scale for a dimension
  78.     DFSDgetrange - get max and min of data
  79.     DFSDgetdata - get data values
  80.     DFSDgetNT - get file number type for reading
  81.     DFSDpre32 - is the current SDS written with HDF versions previous to 3.2?
  82.     DFSDsetlengths - set lengths of label, unit, format strings on gets
  83.     DFSDsetdims - set rank and dim sizes
  84.     DFSDsetdatastrs - set data label, unit, format and coord system
  85.     DFSDsetdimstrs - set dim labels, units and formats
  86.     DFSDsetdimscale - set scale for a dimension
  87.     DFSDsetrange - set max and min of data
  88.     DFSDsetorder - set array order to C or FORTRAN order
  89.     DFSDsetNT - set number type to be written out
  90.     DFSDputdata - output data, data info, and display info
  91.     DFSDrestart - forget info about last file accessed - restart from beginning
  92.     DFSDnumber - return number of SDGs in file
  93.     DFSDclear - forget all info set
  94.     DFSDlastref - get reference number of last SDG read or written
  95.     DFSDgetslice - get part of the data, specified as a slice
  96.     DFSDstartslice - set up to write SD
  97.     DFSDputslice - write specified number of data items to file
  98.     DFSDendslice - end of series of writes, write out SDG
  99.  
  100. Lower level functions:
  101.     DFSDgetsdg - read SDG into struct
  102.     DFSDputsdg - write SDG to file
  103.  
  104. Private functions:
  105.     DFSDIopen - open or reopen file
  106.     DFSDIsdginfo - find next sdg in file
  107.     DFSDIisndg - was currently read sdg written by HDF3.2
  108.     DFSDIrefresh -- get info of next sdg if necessary
  109.     DFSDIgetrrank - get rank of the currently read sdg
  110.     DFSDIgetwrank - get rank of the sdg to be written
  111.     DFSDIclear - clear sdg data structure of all info
  112.     DFSDIgetdata - read data from file
  113.     DFSDIputdata - write data to file
  114.     DFSDIgetslice - get slice
  115.     DFSDIputslice - put slice
  116.     DFSDIendslice -
  117.     DFSDIsetnsdg_t - set up nsdg table
  118.     DFSDInextnsdg - get next nsdg from nsdg table
  119.     DFSDIgetndg - read NDG into struct
  120.     DFSDIputndg - write NDG to file
  121.  
  122. Fortran stub functions:
  123.     dsisdas - set data label, unit, format and coord system
  124.     dsisdis - set dim labels, units and formats
  125.  
  126.  Remarks: 
  127.     These functions will be copied into dfsd.c after debugging.
  128.     This version assumes that all the values are floating point.
  129.  *---------------------------------------------------------------------------*/
  130.  
  131. #include "hdf.h"
  132. #include "herr.h"
  133. #include "dfsd.h"
  134. #include "hfile.h"
  135. #include "dfconvrt.h"
  136.  
  137. /* MMM: make this definition correct and move to hfile.h, or wherever. */
  138. #define DF_NOFILE 0
  139.  
  140. #define LABEL   0
  141. #define UNIT    1
  142. #define FORMAT  2
  143. #define COORDSYS 3
  144.  
  145. #define NFGSDG_TYPE_SDG    0    /* a pure SDG  */
  146. #define NFGSDG_TYPE_NFG    1    /* a pure NDG  */
  147. #define NFGSDG_TYPE_SDGNDG 2    /* an SDG in NDG */
  148.  
  149. /* Init NSDG table header      */
  150. static DFnsdg_t_hdr *nsdghdr = NULL;
  151.  
  152. /* initialize aid to -1 and numbertype to DFNT_NONE.   S. Xu    */
  153. static DFSsdg Readsdg =     /* struct for reading */
  154. { {(uint16)0, (uint16)0}, (intn)0, NULL, NULL, { NULL, NULL, NULL },
  155.       { NULL, NULL, NULL }, NULL, {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0},
  156.       (int32)DFNT_NONE, DFNTF_NONE, (int32)-1, (int32)0,
  157.       (float64) 1.0, (float64) 0.0, (float64) 0.0, (float64) 0.0,
  158.       (int32) -1 
  159. };
  160.  
  161. static DFSsdg Writesdg =    /* struct for writing */
  162. { {(uint16)0, (uint16)0}, (intn)0, NULL, NULL, { NULL, NULL, NULL },
  163.       { NULL, NULL, NULL }, NULL, {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0},
  164.       (int32)DFNT_NONE, DFNTF_NONE, (int32)-1, (int32)0,
  165.       (float64) 1.0, (float64) 0.0, (float64) 0.0, (float64) 0.0,
  166.       (int32) -1 
  167. };
  168.  
  169. static  uint16  Writeref=0;    /* ref of next SDG/NDG to write to file */
  170. static int Newdata=(-1);    /* Values in Readsdg fresh? */
  171.                 /* -1 : no descriptor read */
  172.                 /* 1 : descriptor read */
  173. static int Nextsdg = 1;        /* Signal if DFSDgetdata should get the */
  174.                 /* next SDG/NDG */
  175. static int32 Sfile_id=DF_NOFILE;  /* pointer to file for slice writes */
  176. static int32  *Sddims;        /*dims written so far in slice write */
  177.  
  178. static struct {            /* Indicators of status (s) of info:    */
  179.     int dims;            /* s = -1: there is no info in this category */
  180.     int nt;             /* s = 0: info was set, but not yet written */
  181.     int coordsys;       /* s > 0: info was set and written with ref no.s*/
  182.     int luf[3];
  183.     int scales;
  184.     int maxmin;
  185.     int transpose;    /* It should be taken out!!!        !!!  */
  186.     int cal;
  187. } Ref = {  -1, -1, -1, { -1, -1, -1 }, -1, -1 , -1, -1};
  188.     
  189. static int Maxstrlen[4] = { DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN };
  190. static int Ismaxmin      = 0;    /* is there a max/min value on read?  */
  191. static int FileTranspose = 0;    /* is the data in column major order? */
  192. static int Fortorder     = 0;    /* should data be written col major?  */
  193. static int IsCal         = 0;   /* has calibration info been set?     */
  194.  
  195. /* In ver. 3.2 numbertype and file number format (subclass) are included  */
  196. /* in DFSsdg, and  fileNTsize is local to functions .         */ 
  197. /* static int fileNT=DFNTF_IEEE,     default: all IEEE       */
  198. /*           fileNTsize=4,             */
  199. /*           outNT=DFNTF_IEEE,         default output: IEEE */
  200. /*           outNTsize=4,              */
  201. /*           userNT=DFNTF_IEEE ;     default */
  202. static uint16 Readref = 0;
  203.  
  204. static char Lastfile[DF_MAXFNLEN] = "";    /* last file opened */
  205. static uint16 Lastref = 0;
  206. static DFdi lastnsdg;        /* last read nsdg in nsdg_t */
  207.  
  208. /*-----------------------------------------------------------------------------
  209.  * Name:    DFSDgetdims
  210.  * Purpose: Get dimensions of data in next SDG
  211.  * Inputs:  filename: name of HDF file to use
  212.  *          prank: pointer to integer for returning rank (no of dimensions)
  213.  *          sizes: array of integers for returning size of each dimension
  214.  *          maxrank: size of array for returning dimensions
  215.  * Returns: 0 on success, FAIL on failure with ERROR set
  216.  * Outputs: rank in prank, size of each dimension in sizes
  217.  *          If rank > maxrank, rank is set, and -1 is returned
  218.  * Users:   HDF users, utilities, other routines
  219.  * Invokes: DFSDIopen, HERROR, Hclose, DFSDIsdginfo
  220.  * Method:  Opens file, calls DFSDIsdginfo to get SDG, copies rank etc, closes
  221.  *          file, returns
  222.  * Remarks: Always sequences to next SDG in file
  223.  *          User specifies maxrank, and allocates sizes as an array of integers
  224.  *          with dimension maxrank
  225.  *---------------------------------------------------------------------------*/
  226.  
  227. #ifdef PROTOTYPE
  228. int DFSDgetdims(char *filename, intn *prank, int32 sizes[], intn maxrank)
  229. #else
  230. int DFSDgetdims(filename, prank, sizes, maxrank)
  231. char *filename;
  232. intn *prank;
  233. int32 sizes[];
  234. intn maxrank;
  235. #endif /* PROTOTYPE */
  236. {
  237.     int i;
  238.     int32 file_id;
  239.     char *FUNC="DFSDgetdims";
  240.  
  241.     HEclear();
  242.  
  243.     if (!prank) {                        /* check if ptr is valid */
  244.         HERROR(DFE_BADPTR); return(FAIL);
  245.     }
  246.  
  247.     file_id = DFSDIopen(filename, DFACC_READ); /* open/reopen file */
  248.     if (file_id == FAIL) 
  249.         return FAIL;
  250.     if (DFSDIsdginfo(file_id)<0) {      /* reads next SDG from file */
  251.         Hclose(file_id); return FAIL;    /* on error, close file and return */
  252.     }
  253.  
  254.     *prank = Readsdg.rank;    /* copy rank, dimensions */
  255.     if (maxrank<*prank) {    /* if not all dimensions copied */
  256.         HERROR(DFE_NOTENOUGH); return FAIL;
  257.     }
  258.     for (i=0; i<*prank; i++)
  259.         sizes[i] = Readsdg.dimsizes[i];
  260.     Nextsdg = 0;
  261.     return(Hclose(file_id));
  262. }
  263.  
  264. /*-----------------------------------------------------------------------------
  265.  * Name:    DFSDgetdatastrs
  266.  * Purpose: Get information about data: label, units, format
  267.  * Inputs:  label: string to return label in, length Maxstrlen[LABEL]
  268.  *          unit: string to return unit in, length Maxstrlen[UNIT]
  269.  *          format: string to return format in, length Maxstrlen[FORMAT]
  270.  *          coordsys: string to return coord system, length Maxstrlen[COORDSYS]
  271.  * Returns: 0 on success, FAIL on failure with ERROR set
  272.  * Outputs: label, unit, format, coord system in the appropriate arguments
  273.  * Users:   HDF users, utilities, other routines
  274.  * Invokes: none
  275.  * Method:  get values from struct Readsdg
  276.  * Remarks: none
  277.  *---------------------------------------------------------------------------*/
  278.  
  279. #ifdef PROTOTYPE
  280. int DFSDgetdatastrs(char *label, char *unit, char *format, char *coordsys)
  281. #else
  282. int DFSDgetdatastrs(label, unit, format, coordsys)
  283. char *label, *unit, *format, *coordsys;
  284. #endif /* PROTOTYPE */
  285. {
  286.     int32 luf;
  287.     char *lufp;
  288.     char *FUNC="DFSDgetdatastrs";
  289.  
  290.     HEclear();
  291.     
  292.     if (Newdata<0) {
  293.         HERROR(DFE_BADCALL); return FAIL;
  294.     }
  295.  
  296. /* NOTE: Once DFSDsetdatastrs is changed to always write all three (label,
  297.          unit and format) whenever it is called, this routine should be
  298.          changed so that it returns all three, if any exist.  This means
  299.          that it also should be changed to return -1 if none exist.
  300.          (Currently it returns FAIL only if the SDS doesn't exist.)
  301. */
  302.  
  303.     /* copy label, unit, format */
  304.     for (luf=LABEL; luf<=FORMAT; luf++) {
  305.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  306.         if (lufp)
  307.             if (Readsdg.dataluf[luf])
  308.                 HIstrncpy(lufp, Readsdg.dataluf[luf], Maxstrlen[luf]);
  309.     }
  310.     /* copy coordsys */
  311.     if (coordsys)
  312.         if (Readsdg.coordsys)
  313.             HIstrncpy(coordsys, Readsdg.coordsys, Maxstrlen[COORDSYS]);
  314.         else coordsys[0] = '\0';
  315.     return(0);
  316. }
  317.  
  318. /*-----------------------------------------------------------------------------
  319.  * Name:    DFSDgetdimstrs
  320.  * Purpose: Get information about a dimension: label, units, format
  321.  * Inputs:  dim: no of dimension to get information about
  322.  *          label: string to return label in, max length Maxstrlen[LABEL]
  323.  *          unit: string to return unit in, max length Maxstrlen[UNIT]
  324.  *          format: string to return format in, max length Maxstrlen[FORMAT]
  325.  * Returns: 0 on success, FAIL on failure with ERROR set
  326.  * Outputs: label, unit, format in the appropriate arguments
  327.  *          NULL string if no value for the arguments
  328.  * Users:   HDF users, utilities, other routines
  329.  * Invokes: none
  330.  * Method:  get values from struct Readsdg
  331.  * Remarks: none
  332.  *---------------------------------------------------------------------------*/
  333.  
  334. #ifdef PROTOTYPE
  335. int DFSDgetdimstrs(int dim, char *label, char *unit, char *format)
  336. #else
  337. int DFSDgetdimstrs(dim, label, unit, format)
  338. int dim;
  339. char *label, *unit, *format;
  340. #endif /* PROTOTYPE */
  341. {
  342.     int luf, rdim;
  343.     char *lufp;
  344.     char *FUNC="DFSDgetdimstrs";
  345.  
  346.     HEclear();
  347.     
  348.     if (Newdata<0) {
  349.         HERROR(DFE_BADCALL); return FAIL;
  350.     }
  351.  
  352. /* NOTE: Once DFSDsetdimstrs is changed to always write all three (label,
  353.          unit and format) whenever it is called, this routine should be
  354.          changed so that it returns all three, if any exist.  This means
  355.          that it also should be changed to return -1 if none exist. 
  356.          (Currently it returns FAIL only if the SDS doesn't exist.)
  357. */
  358.  
  359.     rdim = dim-1;        /* translate dim to zero origin */
  360.     if ((rdim>=Readsdg.rank) || (rdim<0)) {
  361.         HERROR(DFE_BADDIM); return FAIL;
  362.     }
  363.  
  364.     /* copy labels etc */
  365.     for (luf=LABEL; luf<=FORMAT; luf++) {
  366.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  367.         if (lufp) {
  368.             if (!Readsdg.dimluf) { /* no labels etc */
  369.                 *lufp = '\0';
  370.                 continue;
  371.             }
  372.             if (Readsdg.dimluf[luf])
  373.                 HIstrncpy(lufp, Readsdg.dimluf[luf][rdim], Maxstrlen[luf]);
  374.         }
  375.     }
  376.     return(0);
  377. }
  378.                 
  379. /*-----------------------------------------------------------------------------
  380.  * Name:    DFSDgetdatalen()
  381.  * Purpose: Get actual length of label, unit, format, coordsys strings
  382.  *          Called from FORTRAN
  383.  * Inputs:  llabel, lunit, lformat, lcoordsys - for returning lengths
  384.  * Globals: Readsdg
  385.  * Returns: 0 on success, FAIL on error with error set
  386.  * Users:   HDF users, utilities, other routines
  387.  * Invokes: none
  388.  * Method:  get lengths from Readsdg
  389.  *---------------------------------------------------------------------------*/
  390.  
  391. #ifdef PROTOTYPE
  392. int DFSDgetdatalen(int *llabel, int *lunit, int *lformat, int *lcoordsys)
  393. #else
  394. int DFSDgetdatalen(llabel, lunit, lformat, lcoordsys)
  395. int *llabel, *lunit, *lformat, *lcoordsys;
  396. #endif /* PROTOTYPE */
  397. {
  398.     char *FUNC="DFSDgetdatalen";
  399.  
  400.     HEclear();
  401.  
  402.     if (Newdata<0) { 
  403.         HERROR(DFE_BADCALL); return FAIL; 
  404.     }
  405.  
  406.     *llabel =  Readsdg.dataluf[LABEL] ? HDstrlen(Readsdg.dataluf[LABEL]) : 0;
  407.     *lunit =  Readsdg.dataluf[UNIT] ? HDstrlen(Readsdg.dataluf[UNIT]) : 0;
  408.     *lformat =  Readsdg.dataluf[FORMAT] ? HDstrlen(Readsdg.dataluf[FORMAT]) : 0;
  409.     *lcoordsys =  Readsdg.coordsys ? HDstrlen(Readsdg.coordsys) : 0;
  410.     return(0);
  411. }
  412.     
  413.  
  414. /*-----------------------------------------------------------------------------
  415.  * Name:    DFSDgetdimlen()
  416.  * Purpose: Get actual length of label, unit, format strings
  417.  *          Called from FORTRAN
  418.  * Inputs:  dim. llabel, lunit, lformat - for returning lengths
  419.  * Globals: Readsdg
  420.  * Returns: 0 on success, FAIL on error with error set
  421.  * Users:   HDF users, utilities, other routines
  422.  * Invokes: none
  423.  * Method:  get lengths from Readsdg
  424.  *---------------------------------------------------------------------------*/
  425.  
  426. #ifdef PROTOTYPE
  427. int DFSDgetdimlen(int dim, int *llabel, int *lunit, int *lformat)
  428. #else
  429. int DFSDgetdimlen(dim, llabel, lunit, lformat)
  430. int dim;
  431. int *llabel, *lunit, *lformat;
  432. #endif /* PROTOTYPE */
  433. {
  434.     char *FUNC="DFSDgetdimlen";
  435.  
  436.     HEclear();
  437.  
  438.     if (Newdata<0) { 
  439.         HERROR(DFE_BADCALL); return FAIL; 
  440.     }
  441.  
  442.     if (dim>Readsdg.rank) { 
  443.         HERROR(DFE_BADDIM); return FAIL; 
  444.     }
  445.  
  446.     *llabel =  Readsdg.dimluf[LABEL][dim-1] ?
  447.         HDstrlen(Readsdg.dimluf[LABEL][dim-1]) : 0;
  448.     *lunit =  Readsdg.dimluf[UNIT][dim-1] ?
  449.         HDstrlen(Readsdg.dimluf[UNIT][dim-1]) : 0;
  450.     *lformat =  Readsdg.dimluf[FORMAT][dim-1] ?
  451.         HDstrlen(Readsdg.dimluf[FORMAT][dim-1]) : 0;
  452.     return(0);
  453. }
  454.  
  455. /*-----------------------------------------------------------------------------
  456.  * Name:    DFSDgetdimscale
  457.  * Purpose: Get dimension scale
  458.  * Inputs:  dim: no of dimension to get scale for
  459.  *          size: size of scale array
  460.  *          scale: array to return scale in
  461.  * Returns: 0 on success, FAIL on failure with error set
  462.  * Outputs: scale if present, else -1
  463.  * Users:   HDF users, utilities, other routines
  464.  * Invokes: none
  465.  * Method:  get values from struct Readsdg
  466.  * Remarks: none
  467.  *---------------------------------------------------------------------------*/
  468.  
  469. #ifdef PROTOTYPE
  470. intn DFSDgetdimscale(int dim, int32 maxsize,void *scale)
  471. #else
  472. intn DFSDgetdimscale(dim, maxsize, scale)
  473. int dim;
  474. int32 maxsize;
  475. void *scale;
  476. #endif /* PROTOTYPE */
  477. {
  478.     int32 dimsize;
  479.     int32 numtype, localNTsize;
  480.     int rdim;
  481.     uint8 *p1, *p2;
  482.     char *FUNC="DFSDgetdimscale";
  483.  
  484.     HEclear();
  485.     
  486.     if (Newdata<0) {
  487.         HERROR(DFE_BADCALL); return FAIL;
  488.     }
  489.     rdim = dim-1;        /* translate dim to zero origin */
  490.     if ((rdim>=Readsdg.rank) || (rdim<0)) {
  491.         HERROR(DFE_BADDIM); return FAIL;
  492.     }
  493.     if (maxsize < Readsdg.dimsizes[rdim]) {
  494.         HERROR(DFE_NOSPACE); return FAIL;
  495.     }
  496.     if (!scale) {
  497.         HERROR(DFE_BADPTR); return FAIL;
  498.     }
  499.     if (!Readsdg.dimscales || !Readsdg.dimscales[rdim]) { /* no scale */
  500.         HERROR(DFE_NOVALS); return FAIL;
  501.     }
  502.  
  503.     /* get number type and copy data from Readsdg to scale */
  504.     if (Readsdg.numbertype == DFNT_NONE)
  505.         Readsdg.numbertype = DFNT_FLOAT32;
  506.     numtype = Readsdg.numbertype;
  507.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  508.     dimsize = localNTsize*Readsdg.dimsizes[rdim]; /* in bytes  */
  509.  
  510.     p1 = (uint8 *)scale;
  511.     p2 = (uint8 *)(Readsdg.dimscales[rdim]);
  512.     HDmemcpy(p1, p2, dimsize);
  513.  
  514.     return(0);
  515. }
  516.  
  517. /*-----------------------------------------------------------------------------
  518.  * Name:    DFSDgetrange()
  519.  * Purpose: Get maximum and minimum data values
  520.  * Inputs:  pmax: pointer to int8 to return maximum value in
  521.  *          pmin: pointer to int8 to return minimum value in
  522.  * Globals: Ismaxmin
  523.  * Returns: 0 on success, -1 if no maxmin values or if error, with error set
  524.  * Users:   HDF users, utilities, other routines
  525.  * Invokes: none
  526.  * Method:  Retrieves values from Readsdg
  527.  * Remarks: none
  528.  *---------------------------------------------------------------------------*/
  529.  
  530. #ifdef PROTOTYPE
  531. int DFSDgetrange(void *pmax, void *pmin)
  532. #else
  533. int DFSDgetrange(pmax, pmin)
  534. void *pmax, *pmin;
  535. #endif /* PROTOTYPE */
  536. {
  537.     int32 numtype, localNTsize;
  538.     uint8 *p1, *p2;
  539.     char *FUNC="DFSDgetrange";
  540.  
  541.     HEclear();
  542.     
  543.     if (Newdata<0) {
  544.         HERROR(DFE_BADCALL); return FAIL;
  545.     }
  546.     /* get number type and copy data  */
  547.     if (Readsdg.numbertype == DFNT_NONE)
  548.         Readsdg.numbertype = DFNT_FLOAT32;
  549.     numtype = Readsdg.numbertype;
  550.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  551.  
  552.     if (Ismaxmin) {
  553.         p1 = (uint8 *)pmax;
  554.         p2 = (uint8 *)&(Readsdg.max_min[0]);
  555.         HDmemcpy(p1, p2, localNTsize);
  556.         p1 = (uint8 *)pmin;
  557.         p2 = &(Readsdg.max_min[localNTsize]);
  558.         HDmemcpy(p1, p2, localNTsize);
  559.         return(0);
  560.     } else {
  561.         HERROR(DFE_NOVALS); return FAIL;
  562.     }
  563. }
  564.  
  565. /*-----------------------------------------------------------------------------
  566.  * Name:    DFSDgetdata
  567.  * Purpose: Get data from SDG.  Will sequence to next SDG if DFSDgetdims not
  568.  *          called.
  569.  * Inputs:  filename: name of HDF file to use
  570.  *          rank: no of dimensions of array "data"
  571.  *          maxsizes: actual dimensions of array "data"
  572.  *          data: data for returning scientific data
  573.  * Returns: 0 on success, FAIL on failure with error set
  574.  * Outputs: actual scientific data in array
  575.  * Users:   HDF users, utilities, other routines
  576.  * Invokes: DFSDIgetdata
  577.  * Method:  call DFSDIgetdata
  578.  * Remarks: maxsizes may be larger than actual size.  In that event, the actual
  579.  *          data may not be contiguous in the array "data"
  580.  *          User sets maxsizes before call.
  581.  *          It is not necessary to call DFSDgetdata first if the dimensions
  582.  *          are correct
  583.  *---------------------------------------------------------------------------*/
  584.  
  585. #ifdef PROTOTYPE
  586. int DFSDgetdata(char *filename, intn rank, int32 maxsizes[], void *data)
  587. #else
  588. int DFSDgetdata(filename, rank, maxsizes, data)
  589. char *filename;
  590. intn rank;
  591. int32 maxsizes[];
  592. void *data;
  593. #endif /* PROTOTYPE */
  594. {
  595.     return(DFSDIgetdata(filename, rank, maxsizes, data, 0));    /* 0 == C */
  596. }
  597.                 
  598.  
  599. /*-----------------------------------------------------------------------------
  600.  * Name:    DFSDsetlengths()
  601.  * Purpose: Set maximum length for label, unit, format, coordsys strings
  602.  * Inputs:  maxlen_label, maxlen_format, maxlen_unit, maxlen_coordsys:
  603.  *              maximum length of each string.
  604.  * Globals: Maxstrlen
  605.  * Returns: 0 on success, FAIL on error with error set
  606.  * Users:   HDF users, utilities, other routines
  607.  * Invokes: none
  608.  * Method:  Stores values in global Maxstrlen
  609.  * Remarks: The get routines assume the array passed in by user is of this len
  610.  *          If this routine is not called, the lengths default to DFS_MAXLEN
  611.  *          The length includes the string terminator NULL byte
  612.  *---------------------------------------------------------------------------*/
  613.  
  614. #ifdef PROTOTYPE
  615. int DFSDsetlengths(int maxlen_label, int maxlen_unit, int maxlen_format,
  616.            int maxlen_coordsys)
  617. #else
  618. int DFSDsetlengths(maxlen_label, maxlen_unit, maxlen_format, maxlen_coordsys)
  619. int maxlen_label, maxlen_unit, maxlen_format, maxlen_coordsys;
  620. #endif /* PROTOTYPE */
  621. {
  622.  
  623.     if (maxlen_label>0) Maxstrlen[LABEL] = maxlen_label;
  624.     if (maxlen_unit>0) Maxstrlen[UNIT] = maxlen_unit;
  625.     if (maxlen_format>0) Maxstrlen[FORMAT] = maxlen_format;
  626.     if (maxlen_coordsys>0) Maxstrlen[COORDSYS] = maxlen_coordsys;
  627.     return(0);
  628. }
  629.     
  630.  
  631. /*-----------------------------------------------------------------------------
  632.  * Name:    DFSDsetdims()
  633.  * Purpose: Set rank and sizes for subsequent SDGs
  634.  * Inputs:  rank: rank of array that holds the raw data
  635.  *          dimsizes: sizes of all of the dimensions
  636.  * Globals: Writesdg, Ref
  637.  * Returns: 0 on success, FAIL on error with error set
  638.  * Users:   HDF users, utilities, other routines
  639.  * Invokes: DFSDclear
  640.  * Method:  Stores values in global structure Writesdg
  641.  * Remarks: If dimensions change, all previous "set"s are cleared
  642.  *          This routine must be called before DFSDsetdimstrs and
  643.  *          DFSDsetdimscales.  It need not be called if these routines are
  644.  *          not called, and the correct dimensions are supplied to DFSDputdata
  645.  *          or DFSDadddata
  646.  *---------------------------------------------------------------------------*/
  647.  
  648. #ifdef PROTOTYPE
  649. int DFSDsetdims(intn rank, int32 dimsizes[])
  650. #else
  651. int DFSDsetdims(rank, dimsizes)
  652. intn rank;
  653. int32  dimsizes[];
  654. #endif /* PROTOTYPE */
  655. {
  656.     int i;
  657.     char *FUNC="DFSDsetdims";
  658.  
  659.     HEclear();
  660.  
  661.     if (Sfile_id!=DF_NOFILE) { 
  662.         HERROR(DFE_BADCALL); return FAIL;
  663.     }
  664.  
  665.     if (Writesdg.rank == rank)    /* check if dimensions same */
  666.         if (Writesdg.dimsizes) {
  667.             for (i=0; i<rank; i++)
  668.                 if (Writesdg.dimsizes[i] != dimsizes[i]) break;
  669.             if (i == rank) return(0); /* Dimensions same as before */
  670.         }   
  671.     
  672.     /* forget all attributes set previously */
  673.     if (DFSDIclear((DFSsdg *)&Writesdg)<0) return FAIL;
  674.  
  675.     /* allocate dimensions */
  676.     Writesdg.dimsizes = (int32 *) HDgetspace((uint32)(rank*sizeof(int32)));
  677.     if (Writesdg.dimsizes==NULL) return FAIL;
  678.  
  679.     /* copy dimensions */
  680.     Writesdg.rank = rank;
  681.     for (i=0; i<rank; i++)
  682.         Writesdg.dimsizes[i] = dimsizes[i];
  683.  
  684.     /* Note dimensions modified */
  685.     Ref.dims = 0;
  686.     return(0);
  687. }
  688. /*-----------------------------------------------------------------------------
  689.  * Name:    DFSDsetdatastrs()
  690.  * Purpose: Set label, unit and format for displaying subsequent SDGs
  691.  * Inputs:  label: label to be used to describe data
  692.  *          unit: unit corresponding to data values
  693.  *          format: format to be used in displaying data values
  694.  *          coordsys: type of coordinate system
  695.  * Globals: Writesdg, Ref
  696.  * Returns: 0 on success, FAIL on failure with error set
  697.  * Users:   HDF users, utilities, other routines
  698.  * Invokes: DFSDIsetdatastrs
  699.  * Method:  
  700.  * Remarks: 
  701.  *---------------------------------------------------------------------------*/
  702.  
  703. #ifdef PROTOTYPE
  704. int DFSDsetdatastrs(char *label, char *unit, char *format, char *coordsys)
  705. #else
  706. int DFSDsetdatastrs(label, unit, format, coordsys)
  707. char *label, *unit, *format, *coordsys;
  708. #endif /* PROTOTYPE */
  709. {
  710.  
  711.     return DFSDIsetdatastrs(label, unit, format, coordsys);
  712.  
  713. }
  714.  
  715. /*-----------------------------------------------------------------------------
  716.  * Name:    DFSDIsetdatastrs()
  717.  * Purpose: Set label, unit and format for displaying subsequent SDGs
  718.  * Inputs:  label: label to be used to describe data
  719.  *          unit: unit corresponding to data values
  720.  *          format: format to be used in displaying data values
  721.  *          coordsys: type of coordinate system
  722.  * Globals: Writesdg, Ref
  723.  * Returns: 0 on success, FAIL on failure with error set
  724.  * Users:   HDF users, utilities, other routines
  725.  * Invokes: none
  726.  * Method:  Stores values in global structure Writesdg
  727.  * Remarks: should we validate coordsys? proposed strings: "cartesian",
  728.  *          "polar" (="spherical") and "cylindrical".  Do "spherical" and
  729.  *          "cylindrical" make sense for 2D?
  730.  *---------------------------------------------------------------------------*/
  731.  
  732. #ifdef PROTOTYPE
  733. int DFSDIsetdatastrs(char *label, char *unit, char *format, char *coordsys)
  734. #else
  735. int DFSDIsetdatastrs(label, unit, format, coordsys)
  736. char *label, *unit, *format, *coordsys;
  737. #endif /* PROTOTYPE */
  738. {
  739.     int luf;            /* takes values LABEL, UNIT, FORMAT */
  740.                 /* in succession */
  741.     char *lufp;            /* points to label, unit, format */
  742.                 /* in succession */
  743.  
  744. /* NOTE: The following code should be changed to write all three, even if
  745.          one or more is an empty string.  Then, when DFSDgetdatastrs is called
  746.          values will be returned for all three also, even though some might
  747.          be empty strings.
  748. */
  749.  
  750.     for (luf=LABEL; luf<=FORMAT; luf++) {
  751.     /* set lufp to point to label etc. as apppropriate */
  752.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  753.  
  754.     /* free space if allocated */
  755.         Writesdg.dataluf[luf] = HDfreespace(Writesdg.dataluf[luf]);
  756.  
  757.     /* copy string */
  758.         if (lufp) {
  759.             Writesdg.dataluf[luf] = HDgetspace((uint32) HDstrlen(lufp)+1);
  760.             if (Writesdg.dataluf[luf]==NULL) return FAIL;
  761.             HDstrcpy(Writesdg.dataluf[luf], lufp);
  762.         }
  763.     }
  764.  
  765.     Writesdg.coordsys = HDfreespace(Writesdg.coordsys);
  766.  
  767.     if (coordsys) {
  768.         Writesdg.coordsys = HDgetspace((uint32) HDstrlen(coordsys)+1);
  769.         if (Writesdg.coordsys==NULL) return FAIL;
  770.         HDstrcpy(Writesdg.coordsys, coordsys);
  771.     }
  772.  
  773.     /* indicate that label, unit, format and coordsys info modified */
  774.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = Ref.coordsys = 0;
  775.  
  776.     return(0);
  777. }
  778.  
  779. /*-----------------------------------------------------------------------------
  780.  * Name:    DFSDsetdimstrs()
  781.  * Purpose: For the given dimension, set label, unit, format
  782.  *          This routine needs to be called once for each dimension whose 
  783.  *          values the user wants to set.
  784.  * Inputs:  dim: the dimension that this info applies to
  785.  *          label: label to be used to describe this dimension
  786.  *          unit: units for dimension
  787.  *          format: format to be used in displaying
  788.  * Globals: 
  789.  * Returns: 0 on success, FAIL on failure with error set
  790.  * Users:   HDF users, utilities, other routines
  791.  * Invokes: DFSDIsetdimstrs
  792.  * Method:  
  793.  *---------------------------------------------------------------------------*/
  794. #ifdef PROTOTYPE
  795. int DFSDsetdimstrs(int dim, char *label, char *unit, char *format)
  796. #else
  797. int DFSDsetdimstrs(dim, label, unit, format)
  798. int dim;
  799. char *label, *unit, *format;
  800. #endif /* PROTOTYPE */
  801. {
  802.  
  803.     return DFSDIsetdimstrs(dim, label, unit, format);
  804.  
  805. } /* DFSDsetdimstrs */
  806.  
  807.  
  808. /*-----------------------------------------------------------------------------
  809.  * Name:    DFSDIsetdimstrs()
  810.  * Purpose: For the given dimension, set label, unit, format
  811.  *          This routine needs to be called once for each dimension whose 
  812.  *          values the user wants to set.
  813.  * Inputs:  dim: the dimension that this info applies to
  814.  *          label: label to be used to describe this dimension
  815.  *          unit: units for dimension
  816.  *          format: format to be used in displaying
  817.  * Globals: Writesdg, Ref
  818.  * Returns: 0 on success, FAIL on failure with error set
  819.  * Users:   HDF users, utilities, other routines
  820.  * Invokes: none
  821.  * Method:  Stores values in global structure Writesdg
  822.  *---------------------------------------------------------------------------*/
  823.  
  824. #ifdef PROTOTYPE
  825. int DFSDIsetdimstrs(int dim, char *label, char *unit, char *format)
  826. #else
  827. int DFSDIsetdimstrs(dim, label, unit, format)
  828. int dim;
  829. char *label, *unit, *format;
  830. #endif /* PROTOTYPE */
  831. {
  832.  
  833.     int i, rdim, luflen;
  834.     int luf;            /* takes values LABEL, UNIT, FORMAT */
  835.                 /* in succession */
  836.     char *lufp;            /* points to label, unit, format */
  837.                 /* in succession */
  838.     char *FUNC="DFSDsetdimstrs";
  839.     HEclear();
  840.  
  841.     /* translate from 1 to 0 origin */
  842.     rdim = dim - 1;
  843.  
  844.     if ((rdim>=Writesdg.rank) || (rdim<0)) {
  845.         HERROR(DFE_BADDIM); return FAIL;
  846.     }
  847.  
  848.     for (luf = LABEL; luf <= FORMAT; luf++) {
  849.     /* set lufp to point to label etc. as apppropriate */
  850.         lufp   = (luf==LABEL) ? label : (luf==UNIT) ? unit  : format;
  851.         luflen = HDstrlen(lufp);
  852.  
  853.     /* allocate space if necessary */
  854.         if (!Writesdg.dimluf[luf]) {
  855.             Writesdg.dimluf[luf] =
  856.                 (char **) HDgetspace((uint32) Writesdg.rank * sizeof(char *));
  857.             if (Writesdg.dimluf[luf]==NULL) return FAIL;
  858.             for (i = 0; i < Writesdg.rank; i++) /* set allocated pointers to NULL*/
  859.                 Writesdg.dimluf[luf][i] = NULL;
  860.         }
  861.  
  862.     /* free string space if allocated */
  863.         Writesdg.dimluf[luf][rdim] = HDfreespace(Writesdg.dimluf[luf][rdim]);
  864.  
  865. /* NOTE: The following code should be changed to write all three, even if
  866.          one or more is an empty string.  Then, when DFSDgetdimstrs is called
  867.          values will be returned for all three also, even though some might
  868.          be empty strings.
  869. */
  870.  
  871.     /* copy string */
  872.         if (lufp) {
  873.             Writesdg.dimluf[luf][rdim] = HDgetspace((uint32) luflen + 1);
  874.             if (Writesdg.dimluf[luf][rdim]==NULL) return FAIL;
  875.             HIstrncpy(Writesdg.dimluf[luf][rdim], lufp, luflen + 1);
  876.         }
  877.     }
  878.     /* Indicate that this info has not been written to file */
  879.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = 0;
  880.  
  881.     return(0);
  882. } /* DFSDIsetdimstrs */
  883.  
  884. /*-----------------------------------------------------------------------------
  885.  * Name:    DFSDsetdimscale()
  886.  * Purpose: For the given dimension, set scale values
  887.  *          This routine needs to be called once for each dimension whose 
  888.  *          values the user wants to set.
  889.  * Inputs:  dim: the dimension that this info applies to
  890.  *          dimsize: number of points in the scale
  891.  *          scale: array of numbers that will make up the scale
  892.  * Globals: Writesdg, Ref
  893.  * Returns: 0 on success, FAIL on failure with error set
  894.  * Users:   HDF users, utilities, other routines
  895.  * Invokes: none
  896.  * Method:  Stores values in global structure Writesdg
  897.  *---------------------------------------------------------------------------*/
  898.  
  899. #ifdef PROTOTYPE
  900. int DFSDsetdimscale(int dim, int32 dimsize, void *scale)
  901. #else
  902. int DFSDsetdimscale(dim, dimsize, scale)
  903. int dim;
  904. int32   dimsize;
  905. void *scale;
  906. #endif /* PROTOTYPE */
  907. {
  908.  
  909.     int32 i;
  910.     int rdim;
  911.     int32 numtype, bytesize;
  912.     int32 localNTsize;
  913.     uint8 *p1, *p2;
  914.     char *FUNC="DFSDsetdimscale";
  915.  
  916.     HEclear();
  917.     rdim = dim-1;        /* translate from 1 to 0 origin */
  918.  
  919.     if (!Writesdg.dimsizes) {
  920.         HERROR(DFE_BADCALL); return FAIL;
  921.     }
  922.     if (Writesdg.numbertype == DFNT_NONE)
  923.     if (DFSDsetNT( DFNT_FLOAT32) <0) return FAIL;
  924.     numtype = Writesdg.numbertype;
  925.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  926.  
  927.     if ((rdim>=Writesdg.rank) || (rdim<0) /* check dimensions */
  928.     || (dimsize!=Writesdg.dimsizes[rdim])) {
  929.         HERROR(DFE_BADDIM); return FAIL;
  930.     }
  931.  
  932.     if (!scale) {        /* No scale for this dimension */
  933.         if (Writesdg.dimscales)
  934.             Writesdg.dimscales[rdim] =
  935.         (uint8 *) HDfreespace((char*) Writesdg.dimscales[rdim]);
  936.         Ref.scales = 0;
  937.         return(0);
  938.     }
  939.     /* get number type and size of this type in this machine  */
  940.     if (Writesdg.numbertype == DFNT_NONE)
  941.     if (DFSDsetNT( DFNT_FLOAT32) <0) return FAIL;
  942.     numtype = Writesdg.numbertype;
  943.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  944.     bytesize = dimsize * localNTsize;
  945.         
  946.     /* allocate space for dimscales if necessary */
  947.     if (!Writesdg.dimscales) {
  948.         Writesdg.dimscales =
  949.         (uint8 **) HDgetspace((uint32)Writesdg.rank * sizeof(int8 *));
  950.         if (Writesdg.dimscales==NULL) return FAIL;
  951.         for (i=0; i<Writesdg.rank; i++) /* set allocated pointers to NULL */
  952.             Writesdg.dimscales[i] = NULL;
  953.     }
  954.  
  955.     if (!Writesdg.dimscales[rdim]) {
  956.     /* allocate dimension scale space if necessary */
  957.         Writesdg.dimscales[rdim] =
  958.         (uint8 *) HDgetspace((uint32) bytesize);
  959.         if (Writesdg.dimscales[rdim]==NULL) return FAIL;
  960.     }
  961.  
  962.              /* copy scale */
  963.     p1 = (uint8 *)scale;
  964.     p2 = (uint8 *)Writesdg.dimscales[rdim];
  965.     HDmemcpy(p2, p1, bytesize);
  966.  
  967.     /* Indicate scales modified */
  968.     Ref.scales = 0;
  969.  
  970.     return(0);
  971. }
  972.  
  973. /*-----------------------------------------------------------------------------
  974.  * Name:    DFSDsetrange()
  975.  * Purpose: Set maximum and minimum data values
  976.  * Inputs:  maxi: maximum value
  977.  *          mini: minimum value
  978.  * Globals: Ref
  979.  * Returns: 0 on success, -1 if no maxmin values or if error, with error set
  980.  * Users:   HDF users, utilities, other routines
  981.  * Invokes: none
  982.  * Method:  Modify Writesdg, set Ref
  983.  * Remarks: Automatically cleared after call to DFSDputdata or DFSDadddata
  984.  *---------------------------------------------------------------------------*/
  985.  
  986. #ifdef PROTOTYPE
  987. int DFSDsetrange(void *maxi, void *mini)
  988. #else
  989. int DFSDsetrange(maxi, mini)
  990. void *maxi, *mini;
  991. #endif /* PROTOTYPE */
  992. {
  993.     int32 numtype, localNTsize;
  994.     int i;
  995.     uint8 *p1, *p2;
  996.  
  997.     HEclear();
  998.     p1 = &(Writesdg.max_min[0]);
  999.     for (i=0; i<16; i++)
  1000.         *p1++ = 0;       /* clear max_min   */
  1001.  
  1002.     /* get number type and copy the values to Writesdg   */
  1003.     if (Writesdg.numbertype == DFNT_NONE)
  1004.         DFSDsetNT(DFNT_FLOAT32);
  1005.  
  1006.     numtype = Writesdg.numbertype;
  1007.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  1008.     p1 = (uint8 *)maxi;
  1009.     p2 = (uint8 *)mini;
  1010.     
  1011.     HDmemcpy((uint8 *) &(Writesdg.max_min[0]), p1, localNTsize);
  1012.     HDmemcpy((uint8 *)&(Writesdg.max_min[localNTsize]), p2, localNTsize);
  1013.  
  1014.     Ref.maxmin = 0;
  1015.  
  1016.     return(0);
  1017. }
  1018.  
  1019.  
  1020. /*-----------------------------------------------------------------------------
  1021.  * Name:    DFSDputdata
  1022.  * Purpose: Calls DFSDIputdata to write data and SDG to file
  1023.  * Inputs:  filename: name of HDF file to use
  1024.  *          rank: rank of data array
  1025.  *          dimsizes: sizes of the dimensions of data array
  1026.  *          data: array that holds data
  1027.  * Globals: Writeref
  1028.  * Returns: 0 on success, FAIL on failure with error set
  1029.  * Users:   HDF users, utilities, other routines
  1030.  * Invokes: DFSDIputdata
  1031.  * Method:  Invoke DFSDIputdata
  1032.  *---------------------------------------------------------------------------*/
  1033.  
  1034. #ifdef PROTOTYPE
  1035. int DFSDputdata(char *filename, intn rank, int32 dimsizes[], void *data)
  1036. #else
  1037. int DFSDputdata(filename, rank, dimsizes, data)
  1038. char *filename;
  1039. intn rank;
  1040. int32 dimsizes[];
  1041. void *data;
  1042. #endif /* PROTOTYPE */
  1043. {
  1044.  
  1045.     /* 0, 0 specify create mode, C style array (row major) */
  1046.     return(DFSDIputdata(filename, rank, dimsizes, data, 0, 0));
  1047. }
  1048.  
  1049. /*-----------------------------------------------------------------------------
  1050.  * Name:    DFSDadddata
  1051.  * Purpose: Calls DFSDIputdata to append data and SDG to file
  1052.  * Inputs:  filename: name of HDF file to use
  1053.  *          rank: rank of data array
  1054.  *          dimsizes: sizes of the dimensions of data array
  1055.  *          data: array that holds data
  1056.  * Globals: Writeref
  1057.  * Returns: 0 on success, FAIL on failure with error set
  1058.  * Users:   HDF users, utilities, other routines
  1059.  * Invokes: DFSDIputdata
  1060.  * Method:  Invoke DFSDIputdata
  1061.  *---------------------------------------------------------------------------*/
  1062.  
  1063. #ifdef PROTOTYPE
  1064. int DFSDadddata(char *filename, intn rank, int32 dimsizes[], void *data)
  1065. #else
  1066. int DFSDadddata(filename, rank, dimsizes, data)
  1067. char *filename;
  1068. intn rank;
  1069. int32 dimsizes[];
  1070. void *data;
  1071. #endif /* PROTOTYPE */
  1072. {
  1073.  
  1074.     /* 1, 0 specifies append mode, C style array (row major) */
  1075.     return(DFSDIputdata(filename, rank, dimsizes, data, 1, 0));
  1076. }
  1077.  
  1078.  
  1079. /*-----------------------------------------------------------------------------
  1080.  * Name:    DFSDrestart
  1081.  * Purpose: Do not remember info about file - get again from first data set
  1082.  * Inputs:  none
  1083.  * Returns: 0 on success
  1084.  * Users:   HDF programmers
  1085.  * Remarks: Just reset Lastfile to NULL
  1086.  *          Subsequent gets will starts from first image
  1087.  *          Next put will write all "set" info to file
  1088.  *---------------------------------------------------------------------------*/
  1089.  
  1090. #ifdef PROTOTYPE
  1091. int DFSDrestart(void)
  1092. #else
  1093. int DFSDrestart()
  1094. #endif /* PROTOTYPE */
  1095. {
  1096.     Lastfile[0] = '\0';
  1097.     Readref = 0;
  1098.     return(0);
  1099. }
  1100.     
  1101.  
  1102. /*-----------------------------------------------------------------------------
  1103.  * Name:    DFSDnumber
  1104.  * Purpose: Return number of NSDGs in file
  1105.  * Inputs:  filename - name of HDF file
  1106.  * Globals: none
  1107.  * Returns: number of NSDGs on success, FAIL on error with error set
  1108.  * Users:   HDF users, utilities, other routines
  1109.  * Invokes: DFSDIopen, Hclose
  1110.  * Method:  open file (creating nsdgs table), then read nsdghdr->size
  1111.  * Remarks: none
  1112.  *---------------------------------------------------------------------------*/
  1113.  
  1114. #ifdef PROTOTYPE
  1115. int32 DFSDnumber(char *filename)
  1116. #else
  1117. int32 DFSDnumber(filename)
  1118. char *filename;
  1119. #endif /* PROTOTYPE */
  1120. {
  1121.     int32 file_id;
  1122.     int32 nsdgs=0;
  1123.     char *FUNC="DFSDnumber";
  1124.  
  1125.     HEclear();
  1126.  
  1127.     /* should use reopen if same file as last time - more efficient */
  1128.     file_id = DFSDIopen(filename, DFACC_READ);
  1129.     if (file_id == FAIL) {
  1130.         HERROR(DFE_BADOPEN);
  1131.         return FAIL;
  1132.     }
  1133.  
  1134.     nsdgs = nsdghdr->size;
  1135.     if (Hclose(file_id) == FAIL) return FAIL;
  1136.     return(nsdgs);
  1137. }
  1138.  
  1139.  
  1140. /*-----------------------------------------------------------------------------
  1141.  * Name:    DFSDclear
  1142.  * Purpose: Clear all "set" values
  1143.  * Inputs:  none
  1144.  * Globals: Writesdg, Ref
  1145.  * Returns: 0 on success, FAIL on error with error set
  1146.  * Users:   HDF users, utilities, other routines
  1147.  * Invokes: DFSDIclear
  1148.  * Method:  Invoke DFSDIclear
  1149.  * Remarks: none
  1150.  *---------------------------------------------------------------------------*/
  1151.  
  1152. #ifdef PROTOTYPE
  1153. int DFSDclear(void)
  1154. #else
  1155. int DFSDclear()
  1156. #endif /* PROTOTYPE */
  1157. {
  1158.     lastnsdg.tag=DFTAG_NULL;
  1159.     lastnsdg.ref=0;
  1160.     if (DFSDIclearNT(&Writesdg) < 0) return(-1);
  1161.     return(DFSDIclear(&Writesdg));
  1162. }
  1163.  
  1164.  
  1165. /*-----------------------------------------------------------------------------
  1166.  * Name:    DFSDlastref
  1167.  * Purpose: Return last ref written or read
  1168.  * Inputs:  none
  1169.  * Globals: Lastref
  1170.  * Returns: ref on success, FAIL on error with error set
  1171.  * Users:   HDF users, utilities, other routines
  1172.  * Invokes: none
  1173.  * Method:  return Lastref
  1174.  * Remarks: none
  1175.  *---------------------------------------------------------------------------*/
  1176.  
  1177. #ifdef PROTOTYPE
  1178. int DFSDlastref(void)
  1179. #else
  1180. int DFSDlastref()
  1181. #endif /* PROTOTYPE */
  1182. {
  1183.     return((int) Lastref);
  1184. }
  1185.  
  1186. /*-----------------------------------------------------------------------------
  1187.  * Name:    DFSDreadref
  1188.  * Purpose: Set ref of SDS to get next
  1189.  * Inputs:  filename: file to which this applies
  1190.  *          ref: reference number of next get
  1191.  * Returns: 0 on success, FAIL on failure
  1192.  * Users:   HDF programmers, other routines and utilities
  1193.  * Invokes: DFSDIopen, DFIfind
  1194.  * Remarks: checks if image with this ref exists
  1195.  *---------------------------------------------------------------------------*/
  1196.  
  1197. #ifdef PROTOTYPE
  1198. int DFSDreadref(char *filename, uint16 ref)
  1199. #else
  1200. int DFSDreadref(filename, ref)
  1201.     char *filename;
  1202.     uint16 ref;
  1203. #endif /* PROTOTYPE */
  1204. {
  1205.     int32 file_id, aid;
  1206.     char *FUNC="DFSDreadref";
  1207.  
  1208.     HEclear();
  1209.     file_id = DFSDIopen(filename, DFACC_READ);
  1210.     if (file_id == DF_NOFILE) return FAIL; 
  1211.  
  1212.     if((aid = Hstartread(file_id, DFTAG_SDG, ref)) == FAIL
  1213.        && (aid = Hstartread(file_id, DFTAG_NDG, ref)) == FAIL)      {
  1214.         HERROR(DFE_NOMATCH);
  1215.         return(HDerr(file_id));
  1216.     }
  1217.  
  1218.     Hendaccess(aid);
  1219.     Readref = ref;
  1220.     Newdata = -1;
  1221.     return Hclose(file_id);
  1222. }
  1223.  
  1224. /*-----------------------------------------------------------------------------
  1225.  * Name:    DFSDgetslice
  1226.  * Purpose: Get slice of data from SDG.  Will sequence to next SDG if
  1227.  *          DFSDgetdims, DFSDgetdata or DFSDgetslice not called earlier.
  1228.  * Inputs:  filename: name of HDF file to use
  1229.  *          winst: array of size = rank of data, containing start of slice
  1230.  *          windims: array of size rank, containing end of slice
  1231.  *          data: array for returning slice
  1232.  *          dims: dimensions of array data
  1233.  * Returns: 0 on success, FAIL on failure with error set
  1234.  * Outputs: slice of data in data
  1235.  * Users:   DFSDIgetdata
  1236.  * Invokes: DFSDIgetslice
  1237.  * Method:  call DFSDIgetslice
  1238.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  1239.  *          data may not be contiguous in the array "data".
  1240.  *          User sets dims before call.
  1241.  *---------------------------------------------------------------------------*/
  1242.  
  1243. #ifdef PROTOTYPE
  1244. int DFSDgetslice(char *filename, int32 winst[], int32 windims[], void *data,
  1245.          int32 dims[])
  1246. #else
  1247. int DFSDgetslice(filename, winst, windims, data, dims)
  1248. char *filename;
  1249. int32 winst[], windims[];
  1250. int32 dims[];
  1251. void *data;
  1252. #endif /* PROTOTYPE */
  1253. {
  1254.     return(DFSDIgetslice(filename, winst, windims, data, dims, 0));
  1255. }
  1256.  
  1257. /*-----------------------------------------------------------------------------
  1258.  * Name:    DFSDstartslice
  1259.  * Purpose: Set up to write slice of data to SDG.
  1260.  * Inputs:  filename: name of HDF file to write to
  1261.  * Returns: 0 on success, FAIL on failure with error set
  1262.  * Users:   DFSDIputdata
  1263.  * Invokes: DFSDIopen, DFnewref, DFaccess
  1264.  * Method:  call DFSDIputslice
  1265.  * Remarks: DFSDsetdims must have been called first
  1266.  *          No call which needs a file open may be made after this
  1267.  *          till DFSDendslice is called
  1268.  *---------------------------------------------------------------------------*/
  1269.  
  1270. #ifdef PROTOTYPE
  1271. int DFSDstartslice(char *filename)
  1272. #else
  1273. int DFSDstartslice(filename)
  1274. char *filename;
  1275. #endif /* PROTOTYPE */
  1276. {
  1277.     int32 i, size;
  1278.     char *FUNC="DFSDstartslice";
  1279.  
  1280.     HEclear();
  1281.  
  1282.     if (!Writesdg.rank) {    /* dimensions not set */
  1283.         HERROR(DFE_BADDIM); return FAIL;
  1284.     }
  1285.  
  1286.     Sfile_id = DFSDIopen(filename, DFACC_WRITE);
  1287.     if (Sfile_id == DF_NOFILE) return FAIL;
  1288.  
  1289.     if (!Writeref) Writeref = Hnewref(Sfile_id);
  1290.     if (!Writeref) return FAIL;
  1291.  
  1292.     Writesdg.data.tag = DFTAG_SD;
  1293.     Writesdg.data.ref = Writeref;
  1294.     
  1295.     if (Writesdg.numbertype == DFNT_NONE) /* if NT not set,default to float32 */
  1296.         DFSDsetNT(DFNT_FLOAT32);
  1297.  
  1298.         /* set up to write data */
  1299.     size = DFKNTsize(Writesdg.numbertype);
  1300.     for (i=0; i<Writesdg.rank; i++)
  1301.         size *= Writesdg.dimsizes[i];
  1302.  
  1303.     Writesdg.aid = Hstartwrite(Sfile_id, DFTAG_SD, Writeref, size);
  1304.     if (Writesdg.aid == FAIL) {
  1305.         Hclose(Sfile_id); return FAIL;
  1306.     }
  1307.  
  1308.     /* allocate array for keeping track of dims written */
  1309.     Sddims = (int32 *) HDgetspace((uint32) Writesdg.rank * sizeof(int32));
  1310.     if (Sddims==NULL) {
  1311.         Hclose(Sfile_id); return FAIL;
  1312.     }
  1313.     
  1314.     for (i=0; i<Writesdg.rank; i++)
  1315.         Sddims[i] = 0;        /* nothing written so far */
  1316.  
  1317.     return(0);
  1318. }
  1319.  
  1320.  
  1321. /*-----------------------------------------------------------------------------
  1322.  * Name:    DFSDputslice
  1323.  * Purpose: Put slice of data to SDG.
  1324.  * Inputs:  winend: array of size rank, containing end of slice
  1325.  *          data: array containing slice
  1326.  *          dims: dimensions of array data
  1327.  * Returns: 0 on success, FAIL on failure with error set
  1328.  * Users:   DFSDIputdata
  1329.  * Invokes: DFSDIputslice
  1330.  * Method:  call DFSDIputslice
  1331.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  1332.  *          data may not be contiguous in the array "data".
  1333.  *          DFSDstartslice must have been called first
  1334.  *---------------------------------------------------------------------------*/
  1335.  
  1336. #ifdef PROTOTYPE
  1337. int DFSDputslice(int32 winend[], void *data, int32 dims[])
  1338. #else
  1339. int DFSDputslice(winend, data, dims)
  1340. int32 winend[];
  1341. void *data;
  1342. int32 dims[];
  1343. #endif /* PROTOTYPE */
  1344. {
  1345.  
  1346.     return(DFSDIputslice(winend, data, dims, 0));
  1347. }
  1348.  
  1349.  
  1350. /*-----------------------------------------------------------------------------
  1351.  * Name:    DFSDendslice
  1352.  * Purpose: Write of data to SDG completed, write SDG and close file
  1353.  * Inputs:  none
  1354.  * Returns: 0 on success, FAIL on failure with error set
  1355.  * Users:   DFSDIputdata
  1356.  * Invokes: DFSDIendslice 
  1357.  * Method:  call DFSDIendslice
  1358.  *---------------------------------------------------------------------------*/
  1359.  
  1360. #ifdef PROTOTYPE
  1361. int DFSDendslice(void)
  1362. #else
  1363. int DFSDendslice()
  1364. #endif /* PROTOTYPE */
  1365. {
  1366.     return(DFSDIendslice(0));
  1367. }
  1368.  
  1369.  
  1370. /*---------------------------------------------------------------------
  1371. * Name:     DFSDsetNT
  1372. * Purpose:    Set number type for writing out to the hdf file
  1373. * Inputs:    numbertype
  1374. * Return:     0 on success, FAIL on failure with error set
  1375. * Outputs:    none
  1376. * Method:     Set Writesdg.numbertype to numbertype 
  1377.         Calls DFKsetNT, which keeps current NT and also initializes
  1378.         conversion routines. 
  1379. * Remarks:
  1380. *--------------------------------------------------------------------- */
  1381.  
  1382. #if defined PROTOTYPE
  1383. int DFSDsetNT(int32 numbertype)
  1384. #else
  1385. int DFSDsetNT(numbertype)
  1386. int32 numbertype;
  1387. #endif /* PROTOTYPE */
  1388. {
  1389.     uint8 outNT;
  1390.     char *FUNC="DFSDsetNT";
  1391.  
  1392.     HEclear();
  1393.  
  1394.     outNT = (int8)(DFKisnativeNT(numbertype)? DFKgetPNSC(numbertype, DF_MT) :
  1395.                 DFNTF_HDFDEFAULT);
  1396.     if ((numbertype == Writesdg.numbertype) &&
  1397.             (outNT == Writesdg.filenumsubclass))
  1398.         return(0);
  1399.  
  1400.     /* Forget previous numbertype  */
  1401.     if (DFSDIclearNT((DFSsdg *)&Writesdg) < 0) return FAIL;
  1402.     Writesdg.numbertype = numbertype;
  1403.     Writesdg.filenumsubclass = outNT;
  1404.     Ref.nt = 0;
  1405.     Ref.dims = (Ref.dims >= 0? 0: Ref.dims);
  1406.     return(DFKsetNT(numbertype));
  1407. }
  1408.  
  1409. /*-------------------------------------------------------------------
  1410. * Name:     DFSDIclearNT
  1411. * Purpose:    Reset all "set" values related to number types
  1412. * Inputs;    sdg: pointer to sdg struct to clear
  1413. * Globals:    Ref
  1414. * Returns:    0 on success, FAIL on error with error set
  1415. * Users:    DFSDsetNT, HDF users
  1416. * Invokes:    none
  1417. * Remarks:
  1418. *--------------------------------------------------------------------*/
  1419.  
  1420. #if defined PROTOTYPE
  1421. int DFSDIclearNT(DFSsdg *sdg)
  1422. #else
  1423. int DFSDIclearNT(sdg)
  1424. DFSsdg *sdg;
  1425. #endif
  1426.  
  1427. {
  1428.     char *FUNC="DFSDIclearNT";
  1429.     int i;
  1430.  
  1431.     HEclear();
  1432.     sdg->numbertype = DFNT_NONE;
  1433.     sdg->filenumsubclass = DFNTF_NONE;
  1434.  
  1435.     /* free scale pointers. Note: scale pointer array is not freed   */
  1436.     /* sdg->dimscales will be freed only when rank is changed        */
  1437.     if (sdg->dimscales)
  1438.         for (i=0; i<sdg->rank; i++)
  1439.             sdg->dimscales[i] = (uint8 *)
  1440.                 HDfreespace((char *) sdg->dimscales[i]);
  1441.  
  1442.     Ref.nt = -1;
  1443.     Ref.maxmin = -1;    /* maxmin and scales should be changed to */
  1444.     Ref.scales = -1;    /* new number type              */
  1445.     return(0);
  1446. }
  1447.  
  1448. /*--------------------------------------------------------------------
  1449.  
  1450. * Name:    DFSDgetNT
  1451. * Purpose:    Get number type to be read from the hdf file
  1452. * Inputs:     pnumbertype: pointer to int32 to return number type in
  1453. * Return:    0 on success, FAIL on error with DFerror set 
  1454. * Method:    return numbertype in sdg struct
  1455. * Remark:
  1456. *------------------------------------------------------------------- */
  1457.  
  1458. #if defined PROTOTYPE
  1459. int DFSDgetNT(int32 *pnumbertype)
  1460. #else
  1461. int DFSDgetNT(pnumbertype)
  1462. int32 *pnumbertype;
  1463. #endif
  1464. {
  1465.     char *FUNC="DFSDgetNT";
  1466.  
  1467.     HEclear();
  1468.     *(pnumbertype) = Readsdg.numbertype;
  1469.     if (*(pnumbertype) == DFNT_NONE)     {
  1470.         HERROR(DFE_BADNUMTYPE); return FAIL;
  1471.     }
  1472.     return(0);
  1473. }
  1474.     
  1475. /*--------------------------------------------------------------------
  1476. *
  1477. * Name:            DFSDpre32
  1478. * Purpose:    Is the current SDS written by HDF previous to 3.2r1
  1479. * Inputs:     None
  1480. * return:   TRUE (!0) if the SDS was written by 3.1,
  1481. *               FALSE (0) otherwise.
  1482. * Method:   invokes DFSDIisndg, testing isndg in sdg struct
  1483. * Remark:
  1484. *------------------------------------------------------------------- */
  1485.  
  1486. #if defined PROTOTYPE
  1487. intn DFSDpre32(void)
  1488. #else
  1489. intn DFSDpre32()
  1490. #endif
  1491. {
  1492.     intn isndg;
  1493.     char *FUNC="DFSDpre32";
  1494.     
  1495.     DFSDIisndg(&isndg);
  1496.     if (isndg == 1)
  1497.         return (FALSE);
  1498.     else return (TRUE);
  1499. }
  1500.     
  1501. /******************************************************************************/
  1502. /*--------------------- Lower level routines --------------------------------*/
  1503. /******************************************************************************/
  1504.  
  1505. /* Functions for NDG and SDG stuff              */
  1506.  
  1507. /*--------------------------------------------------------------------------
  1508.  * Name:    DFSDIsetnsdg_t
  1509.  * Purpose: Set up the NDG/SDG table. Each node has two
  1510.             fields: the 1st field is NDG or SDG, the 2nd
  1511.             field has value only when it is a special
  1512.             NDG, i.e. the data set is float32 and not
  1513.              compressed.
  1514.  * Inputs:  file_id: pointer to HDF file containing SDG
  1515.  * Returns: 0 on success, FAIL on failure with error set
  1516.  * Users:   DFSDIopen for READ
  1517.  *--------------------------------------------------------------------------*/
  1518. #if defined PROTOTYPE
  1519. int DFSDIsetnsdg_t(int32 file_id, DFnsdg_t_hdr *nsdghdr)
  1520. #else
  1521. int DFSDIsetnsdg_t(file_id,nsdghdr)
  1522. int32 file_id;
  1523. DFnsdg_t_hdr *nsdghdr;
  1524. #endif
  1525. {
  1526.     uint32 sz_DFnsdgle = (uint32)sizeof(struct DFnsdgle);
  1527.     int32 aid,         /* access id */
  1528.           ndgs, sdgs;    /* number of ndg's and sdg's */
  1529.     uint16 intag, inref;
  1530.     bool moretags, found;
  1531.     DFnsdgle *ntb, *stb, *new, *nf, *nr, *sf, *sr;
  1532.     DFdi di, lnkdd[2];
  1533.     uint8 *bufp;
  1534.     char *FUNC="DFSDsetnsdg_t";
  1535.   
  1536.     if (!HDvalidfid(file_id)) {
  1537.         HERROR(DFE_BADCALL); return FAIL;
  1538.     }
  1539.  
  1540. /* MMM:  Talk to Shiming and make sure the change made to the way ndgs
  1541.          and sdgs are handled is ok.
  1542. */
  1543.     ndgs = Hnumber(file_id, DFTAG_NDG);
  1544.     sdgs = Hnumber(file_id, DFTAG_SDG);
  1545.     if ( (ndgs==FAIL) || (sdgs==FAIL) )
  1546.         return FAIL;
  1547.     
  1548.     if ( (ndgs+sdgs) == 0 ) {       /* no sdgs or ndgs in file */
  1549.         nsdghdr->size = 0;
  1550.         nsdghdr->nsdg_t = NULL;
  1551.         return(0);
  1552.     }
  1553.     if ( (ntb = (DFnsdgle *)HDgetspace(sz_DFnsdgle) ) == NULL)   {
  1554.         HERROR(DFE_NOSPACE); return FAIL;
  1555.     }        
  1556.     /* the first node in each table is a dummy node  */
  1557.     ntb->nsdg.tag = DFTAG_NULL;    /* set up and init an ndg table  */
  1558.     ntb->nsdg.ref = 0;
  1559.     ntb->sdg.tag = DFTAG_NULL;
  1560.     ntb->sdg.ref = 0;
  1561.     ntb->next = NULL;
  1562.     if ((stb = (DFnsdgle *)HDgetspace(sz_DFnsdgle)) == NULL)   {
  1563.         HERROR(DFE_NOSPACE); return FAIL;
  1564.     }
  1565.     stb->nsdg.tag = DFTAG_NULL;    /* set up and init an sdg table  */
  1566.     stb->nsdg.ref = 0;
  1567.     stb->sdg.tag = DFTAG_NULL; /* this field should be named as */
  1568.     stb->sdg.ref = 0;          /* stb->ndg.tag, the ndg to which this */
  1569.     stb->next = NULL;        /* sdg belongs.         */
  1570.  
  1571.     aid = Hstartread(file_id, DFTAG_WILDCARD, DFREF_WILDCARD);
  1572.     moretags = (aid != FAIL);
  1573.     while (moretags)    {     /* read dd's and put each dd in ntb or stb */
  1574.         HQuerytagref(aid, &intag, &inref);
  1575.         /* put NDG or SDG on ntb or stb    */
  1576.     if (intag == DFTAG_NDG)    {
  1577.         nr = ntb;
  1578.         nf = ntb;
  1579.         while ((inref>nf->nsdg.ref) && (nf->next!=NULL))   {
  1580.                 nr = nf;
  1581.                 nf = nf->next;
  1582.         }
  1583.             /* MMM:  Tlk to Shiming and make sure the way this part was rearranged is ok.
  1584.              */
  1585.  
  1586.             /* check for duplicate nsdg */
  1587.         if (inref == nf->nsdg.ref)      
  1588.                 HRETURN_ERROR(DFE_BADNDG, FAIL);
  1589.             
  1590.             /* add a node to the table */
  1591.             if ((new = (DFnsdgle *)HDgetspace(sz_DFnsdgle)) == NULL)
  1592.                 HRETURN_ERROR(DFE_NOSPACE, FAIL);
  1593.             
  1594.             new->nsdg.tag = DFTAG_NDG;
  1595.             new->nsdg.ref = inref;
  1596.             new->sdg.tag = DFTAG_NULL;
  1597.             new->sdg.ref = 0;
  1598.             
  1599.             if (inref < nf->nsdg.ref) {  /* does it go before current node? */
  1600.                 new->next = nf;
  1601.                 nr->next = new;
  1602.             } else {                     /* or at the end? */
  1603.                 new->next = nf->next;
  1604.                 nf->next = new;
  1605.             }
  1606.             
  1607.         /* Does this NDG have an SDG?     */
  1608.         if (DFdiread(file_id, DFTAG_NDG, inref) < 0)
  1609.                 return FAIL;
  1610.  
  1611.         found = 0;
  1612.         di.tag = DFTAG_NULL;
  1613.         di.ref = 0;
  1614.         while ((found == 0) && (DFdiget(&di.tag, &di.ref) == 0))  {
  1615.          if (di.tag == DFTAG_SDLNK)
  1616.                     found = 1;
  1617.         }
  1618.         if (found)    {    /* read in the tag/refs in the link element */
  1619.                 if ((int32)FAIL == Hgetelement(file_id, di.tag, di.ref, DFtbuf) )
  1620.                     return FAIL;
  1621.                 bufp = DFtbuf;
  1622.                 UINT16DECODE(bufp, lnkdd[0].tag);
  1623.                 UINT16DECODE(bufp, lnkdd[0].ref);
  1624.                 UINT16DECODE(bufp, lnkdd[1].tag);
  1625.                 UINT16DECODE(bufp, lnkdd[1].ref);
  1626.                 new->sdg.tag = lnkdd[1].tag;
  1627.                 new->sdg.ref = lnkdd[1].ref;
  1628.         }
  1629.     }    /* end of NDG    */
  1630.     if (intag == DFTAG_SDG)    {
  1631.         sr = stb;
  1632.         sf = stb;
  1633.         while ((inref>sf->nsdg.ref) && (sf->next!=NULL))   {
  1634.                 sr = sf;
  1635.                 sf = sf->next;
  1636.         }
  1637.         if (inref == sf->nsdg.ref)
  1638.                 HRETURN_ERROR(DFE_BADNDG, FAIL);
  1639.  
  1640.             /* insert a new node */
  1641.         if ((new = (DFnsdgle *)HDgetspace(sz_DFnsdgle)) == NULL)
  1642.             HRETURN_ERROR(DFE_NOSPACE, FAIL);
  1643.  
  1644.         new->nsdg.tag = DFTAG_SDG;
  1645.         new->nsdg.ref = inref;
  1646.             new->sdg.tag = DFTAG_NULL;
  1647.         new->sdg.ref = 0;
  1648.             
  1649.         if (inref < sf->nsdg.ref)  {  /* does it go before current node? */
  1650.                 new->next = sf;
  1651.                 sr->next = new;
  1652.         } else {                      /* or at the end? */
  1653.                 new->next = sf->next;
  1654.                 sf->next = new;
  1655.         }
  1656.         /* Does it belong to  an NDG?    */
  1657.         if (DFdiread(file_id, DFTAG_SDG, inref) < 0) return FAIL;
  1658.         found = 0;
  1659.             di.tag = DFTAG_NULL;
  1660.         di.ref = 0;            
  1661.             while ((found == 0) && (DFdiget(&di.tag, &di.ref) == 0)) {
  1662.                 if (di.tag == DFTAG_SDLNK)
  1663.                     found = 1;
  1664.             }
  1665.         if (found)    {   /* read in the tag/refs in the link element */
  1666.                 if ((int32)FAIL == Hgetelement(file_id,  di.tag, di.ref, DFtbuf))
  1667.                     return FAIL;
  1668.                 bufp = DFtbuf;
  1669.                 UINT16DECODE(bufp, lnkdd[0].tag);
  1670.                 UINT16DECODE(bufp, lnkdd[0].ref);
  1671.                 UINT16DECODE(bufp, lnkdd[1].tag);
  1672.                 UINT16DECODE(bufp, lnkdd[1].ref);
  1673.                 new->sdg.tag = lnkdd[0].tag;
  1674.                 new->sdg.ref = lnkdd[0].ref;
  1675.         }
  1676.     }    /* end of SDG    */
  1677.  
  1678.     /*   get next dd   */
  1679.         moretags = ( SUCCEED == 
  1680.                   Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT) );
  1681.     }    /* gone through the dd blocks   */
  1682.     Hendaccess(aid);
  1683.  
  1684.     /* merge stb and ntb        */
  1685.         /* remove SDGNDG from stb       */
  1686.     nf = ntb->next;
  1687.     while (nf != NULL)    {
  1688.         inref = nf->sdg.ref;
  1689.         if (inref != 0) {   /* it has an SDG   */
  1690.             sr = stb;
  1691.             sf = stb;
  1692.             while ((sf->nsdg.ref < inref) && (sf->next != NULL))  {
  1693.                 sr = sf;
  1694.                 sf = sf->next;
  1695.             }
  1696.             if (sf->nsdg.ref == inref)      {
  1697.                 if (sf->sdg.ref != nf->nsdg.ref) {
  1698.                     HRETURN_ERROR(DFE_BADNDG, FAIL);
  1699.                 } else {
  1700.                     sr->next = sf->next;
  1701.                     if ((sf = (DFnsdgle *)HDfreespace((char *) sf)) != NULL)
  1702.                         return FAIL;
  1703.                     sdgs--;
  1704.                 }
  1705.             }
  1706.         }
  1707.         nf = nf->next;
  1708.     }
  1709.  
  1710.     /* check all SDGNDGs were removed   */
  1711.     sf = stb->next;
  1712.     while (sf != NULL)    {
  1713.         if (sf->sdg.ref != 0)
  1714.             HRETURN_ERROR(DFE_BADSDG, FAIL);
  1715.         sf = sf->next;
  1716.     }
  1717.  
  1718.     /* merge the two tables into one */
  1719.     nf = ntb;            /* looking for the end of ntb   */
  1720.     while (nf->next != NULL) 
  1721.         nf = nf->next;
  1722.     nf->next = stb->next;    /* the first node in stb is a dummy */
  1723.     nsdghdr->size = ndgs + sdgs;
  1724.     nsdghdr->nsdg_t = ntb->next;
  1725.     
  1726.     /* Release the first nodes in stb and ntb  */
  1727.     HDfreespace((char *)stb);
  1728.     HDfreespace((char *)ntb);
  1729.     return(0);
  1730. }   /* end of DFSDsdtnsdg_t   */
  1731.  
  1732.  
  1733. /*-----------------------------------------------------------------------
  1734. * Name    DFSDInextnsdg
  1735. * Purpose: Returns next ndg or sdg in the file
  1736. * Inputs:  nsdghdr: point to the nsdg table 
  1737. *       nsdg: the structure holds the di of next sdg or ndg
  1738. * Returns: 0 on succeeds, FAIL on failure
  1739. * -------------------------------------------------------------------*/
  1740. #if defined PROTOTYPE
  1741. int DFSDInextnsdg(DFnsdg_t_hdr *nsdghdr, DFdi *nsdg)
  1742. #else
  1743. int DFSDInextnsdg(nsdghdr,nsdg)
  1744. DFnsdg_t_hdr *nsdghdr;
  1745. DFdi *nsdg;
  1746. #endif /* PROTOTYPE*/
  1747.  
  1748. {
  1749.     uint32 num;
  1750.     intn found=FALSE;
  1751.     DFnsdgle *ptr;
  1752.     char *FUNC="DFSDInextnsdg";
  1753.     
  1754.     nsdg->tag= DFTAG_NULL;
  1755.     nsdg->ref=0;
  1756.     ptr = nsdghdr->nsdg_t;
  1757.     num = nsdghdr->size;
  1758.  
  1759.     if ((ptr == NULL) || (num == 0)) return(0);
  1760.  
  1761.     if ((lastnsdg.tag == DFTAG_NULL) && (lastnsdg.ref == 0)) {
  1762.         found = TRUE;
  1763.     } else {
  1764.         while ((num>0) && (ptr != NULL) && !found) {
  1765.             if ((ptr->nsdg.tag == lastnsdg.tag) && 
  1766.                 (ptr->nsdg.ref == lastnsdg.ref))  {
  1767.                 if ((ptr = ptr->next) != NULL)    found = TRUE;
  1768.             } else {
  1769.                 ptr = ptr->next;
  1770.                 num--;
  1771.             }
  1772.         } /* while  */
  1773.         if(((num == 0) && (ptr != NULL)) || 
  1774.            ((num != 0) && (ptr == NULL)) ||
  1775.            !found)  {
  1776.             HERROR(DFE_BADTABLE); return FAIL;
  1777.         }
  1778.     }    /* else   */
  1779.     if (found)    {
  1780.         nsdg->tag=ptr->nsdg.tag;
  1781.         nsdg->ref=ptr->nsdg.ref;
  1782.     }
  1783.     return(0);
  1784. }   /* end of DFSDInextnsdg   */
  1785.  
  1786. /*-----------------------------------------------------------------------------
  1787.  * Name:    DFSDIgetndg
  1788.  * Purpose: Reads in NDG
  1789.  * Inputs:  file_id: pointer to HDF file containing NDG
  1790.  *          ref: ref of NDG to read
  1791.  *          sdg: pointer to DFSsdg struct to read NDG into
  1792.  * Returns: 0 on success, FAIL on failure with error set
  1793.  * Users:   HDF programmers, DFSDIsdginfo
  1794.  * Invokes: DFgetelement, DFdiread, DFdiget, DFaccess, DFread
  1795.         DFSDgetsdg
  1796.  * Method:  Reads in NDG using DFdiread.  Gets each tag/ref using DFdiget.
  1797.  *          Reads in dimensions using DFgetelement.
  1798.  *         Call DFSDgetsdg to read in the rest info.
  1799.  *          Mallocs space for these, freeing
  1800.  *          previously allocated space.
  1801.  * Remarks: This accepts non-float32 data
  1802.  *---------------------------------------------------------------------------*/
  1803.  
  1804. #ifdef PROTOTYPE
  1805. int DFSDIgetndg(int32 file_id, uint16 tag, uint16 ref, DFSsdg *sdg)
  1806. #else
  1807. int DFSDIgetndg(file_id, tag, ref, sdg)
  1808. int32 file_id;
  1809. uint16 tag;
  1810. uint16 ref;
  1811. DFSsdg *sdg;
  1812. #endif /* PROTOTYPE */
  1813. {
  1814.     int32 i;
  1815.     int luf;
  1816.     int32 length;
  1817.     DFdi elmt, nt;
  1818.     uint8 ntstring[4];
  1819.     int32 numtype,    /* current number type */
  1820.           fileNTsize,    /* size of this NT as it is in the file */
  1821.       localNTsize,    /* size of this NT as it is in this machine */
  1822.           ret,
  1823.           aid;
  1824.     int8  fileNT,    /* file number subclass */
  1825.       platnumsubclass;   /* platform number subclass */
  1826.     uint8 *isscales,
  1827.           *buf, 
  1828.           *p;           /* temporary pointer for moving things to buffer */
  1829.     char *FUNC="DFSDIgetndg";
  1830.  
  1831.     HEclear();
  1832.  
  1833.     if (!HDvalidfid(file_id)) {  
  1834.         HERROR(DFE_BADCALL); return FAIL; 
  1835.     }
  1836.     if (!ref)  { 
  1837.         HERROR(DFE_BADREF); return FAIL; 
  1838.     }
  1839.     if (DFdiread(file_id, tag, ref)<0) /* read NDG into memory */
  1840.         return FAIL;
  1841.  
  1842.     DFSDIclear(sdg);
  1843.     if(tag == DFTAG_NDG) DFSDIclearNT(sdg);
  1844.     Ismaxmin = 0;
  1845.     IsCal = FALSE;
  1846.  
  1847.     /*
  1848.      * Loop through all members of the group 
  1849.      */
  1850.     while (!DFdiget(&elmt.tag, &elmt.ref)) {
  1851.         luf = -1;                      /* flag value for label/unit/ */
  1852.         switch (elmt.tag) {                  /* format gets process tag/ref */
  1853.  
  1854.         case DFTAG_SD:    /* data tag/ref */
  1855.             sdg->data.tag = elmt.tag; /* put tag/ref in struct */
  1856.             sdg->data.ref = elmt.ref;
  1857.             break;
  1858.             
  1859.         case DFTAG_SDD:    /* dimension */
  1860.             aid = Hstartread(file_id, elmt.tag, elmt.ref);
  1861.             if (aid == FAIL)
  1862.                 return FAIL;
  1863.             
  1864.             /* read rank */
  1865.             if (Hread(aid, (int32) 2, DFtbuf) == FAIL) return FAIL;
  1866.             p = DFtbuf;
  1867.             INT16DECODE(p, sdg->rank);
  1868.             
  1869.             /* get space for dimensions */
  1870.             sdg->dimsizes = (int32 *) HDgetspace((uint32) sdg->rank *
  1871.                                                  sizeof(int32));
  1872.             if (sdg->dimsizes == NULL) return FAIL;
  1873.  
  1874.             /* read dimension record */
  1875.             if (Hread(aid, (int32) 4 * sdg->rank,DFtbuf) == FAIL) return FAIL;
  1876.             p = DFtbuf;
  1877.             for (i=0; i<sdg->rank; i++)
  1878.                 INT32DECODE(p, sdg->dimsizes[i]);
  1879.             
  1880.             /* read tag/ref of NT */
  1881.             if (Hread(aid,(int32) 4,  DFtbuf) == FAIL) return FAIL;
  1882.             p = DFtbuf;
  1883.             UINT16DECODE(p, nt.tag);
  1884.             UINT16DECODE(p, nt.ref);
  1885.             
  1886.             /* read actual NT */
  1887.             if (Hgetelement(file_id, nt.tag, nt.ref, ntstring) == FAIL)
  1888.                 return FAIL;
  1889.             
  1890.             /* check for any valid NT */
  1891.             if (ntstring[1] == DFNT_NONE) 
  1892.                 HRETURN_ERROR(DFE_BADCALL, FAIL);
  1893.             
  1894.             /* if looking for an SDG type must be FLOAT32 */
  1895.             if (tag == DFTAG_SDG && ntstring[1] != DFNT_FLOAT32)
  1896.                 HRETURN_ERROR(DFE_BADCALL, FAIL);
  1897.                 
  1898.             /* set NT info */
  1899.             numtype = ntstring[1];
  1900.             fileNT = ntstring[3];
  1901.             platnumsubclass = DFKgetPNSC(numtype, DF_MT);
  1902.             if ((fileNT != DFNTF_HDFDEFAULT) &&
  1903.                 (fileNT != platnumsubclass))    {
  1904.                 HERROR(DFE_BADCALL); return FAIL;
  1905.             }
  1906.             if (fileNT != DFNTF_HDFDEFAULT) /* if native */
  1907.                 numtype = numtype | DFNT_NATIVE;
  1908.             sdg->filenumsubclass = ntstring[3];
  1909.             sdg->numbertype = numtype;
  1910.             
  1911.             /* set size of NT    */
  1912.             fileNTsize = DFKNTsize(numtype);
  1913.             localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  1914.  
  1915.             /* read and check all scale NTs */
  1916.             for (i=0; i < sdg->rank; i++) {
  1917.                 if (Hread(aid, (int32) 4, DFtbuf) == FAIL) return FAIL;
  1918.                 p = DFtbuf;
  1919.                 UINT16DECODE(p, nt.tag);
  1920.                 UINT16DECODE(p, nt.ref);
  1921.                     
  1922.                 /* read NT itself */
  1923.                 if (Hgetelement(file_id, nt.tag,nt.ref, ntstring) == FAIL)
  1924.                         return FAIL;
  1925.  
  1926.                 /* check for any valid NT */
  1927.                 if (ntstring[1] == DFNT_NONE) 
  1928.                     HRETURN_ERROR(DFE_BADCALL, FAIL);
  1929.             
  1930.                 /* if looking for an SDG type must be FLOAT32 */
  1931.                 if (tag == DFTAG_SDG && ntstring[1] != DFNT_FLOAT32)
  1932.                     HRETURN_ERROR(DFE_BADCALL, FAIL);
  1933.  
  1934.             }
  1935.             Hendaccess(aid);
  1936.             break;
  1937.             
  1938.         case DFTAG_SDLNK:     /* SDG NDG link */
  1939.             break;      /* do nothing in 3.2  */
  1940.             
  1941.         case DFTAG_SDL:     /* labels */
  1942.             if (luf==(-1)) luf = LABEL;
  1943.             
  1944.         case DFTAG_SDU:     /* units */
  1945.             if (luf==(-1)) luf = UNIT;
  1946.             
  1947.         case DFTAG_SDF:     /* formats */
  1948.             if (luf==(-1)) luf = FORMAT;
  1949.             
  1950.             if (!sdg->dimsizes) 
  1951.                 HRETURN_ERROR(DFE_CORRUPT, FAIL);
  1952.             
  1953.             /* get needed size of buffer, allocate */
  1954.             length =  Hlength(file_id, elmt.tag, elmt.ref);
  1955.             if (length == FAIL) return FAIL;
  1956.             buf = HDgetspace((uint32) length);
  1957.             if (buf == NULL) return FAIL;
  1958.             
  1959.             /* read in luf */
  1960.             if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL) {
  1961.                 buf = HDfreespace(buf);
  1962.                 return FAIL;
  1963.             }
  1964.             p = buf;
  1965.  
  1966.             /* allocate data luf space */
  1967.             sdg->dataluf[luf] = HDgetspace((uint32) HDstrlen((char*)p)+1);
  1968.  
  1969.             if (sdg->dataluf[luf]==NULL) {
  1970.                 buf = HDfreespace(buf);
  1971.                 return FAIL;
  1972.             }
  1973.  
  1974.             /* extract data luf */
  1975.             HDstrcpy(sdg->dataluf[luf], (char*)p);
  1976.             p += HDstrlen(sdg->dataluf[luf])+1;
  1977.  
  1978.             /* get space for dimluf array */
  1979.             sdg->dimluf[luf] =
  1980.                 (char **) HDgetspace((uint32) sdg->rank * sizeof(char *));
  1981.             if (sdg->dimluf[luf]==NULL) {
  1982.                 buf = HDfreespace(buf);
  1983.                 return FAIL;
  1984.             }
  1985.  
  1986.             /* extract dimension lufs */
  1987.             for (i = 0; i < sdg->rank; i++) {
  1988.                 sdg->dimluf[luf][i] = 
  1989.                     HDgetspace((uint32) HDstrlen((char*)p) + 1);
  1990.                 if (sdg->dimluf[luf][i]==NULL) {
  1991.                     buf = HDfreespace(buf);
  1992.                     return FAIL;
  1993.                 }
  1994.                 HDstrcpy(sdg->dimluf[luf][i], (char*)p);
  1995.                 p += HDstrlen(sdg->dimluf[luf][i])+1;
  1996.             }
  1997.             buf = HDfreespace(buf);
  1998.             break;
  1999.  
  2000.         case DFTAG_SDS:     /* scales */
  2001.             if (!sdg->dimsizes) 
  2002.                     HRETURN_ERROR(DFE_CORRUPT, FAIL);
  2003.  
  2004.             /* set up to read scale */
  2005.             aid = Hstartread(file_id, elmt.tag, elmt.ref);
  2006.             if (aid == FAIL) return FAIL;
  2007.  
  2008.             /* read isscales */
  2009.             isscales = HDgetspace((uint32) sdg->rank);
  2010.             if (isscales == NULL) return FAIL;
  2011.             if (Hread(aid, (int32) sdg->rank, isscales) == FAIL) 
  2012.                 return FAIL;
  2013.  
  2014.             /* allocate scale pointers */
  2015.             sdg->dimscales = 
  2016.                 (uint8 **) HDgetspace((uint32) sdg->rank * sizeof(int8 *));
  2017.             if (sdg->dimscales == NULL) {
  2018.                 HDfreespace(isscales);
  2019.                 return FAIL;
  2020.             }
  2021.  
  2022.             /* read scales */
  2023.             for (i = 0; i < sdg->rank; i++) {
  2024.                 sdg->dimscales[i] = NULL;       /* default */
  2025.                 if (!isscales[i]) continue;
  2026.  
  2027.                 /* space for scale */
  2028.                 sdg->dimscales[i] = (uint8 *)
  2029.                     HDgetspace((uint32) sdg->dimsizes[i] * localNTsize);
  2030.                 if (sdg->dimscales[i]==NULL) {
  2031.                     HDfreespace(isscales);
  2032.                     return FAIL;
  2033.                 }
  2034.  
  2035.                 if (platnumsubclass == fileNT) { /* no conversion needed */
  2036.                     ret = Hread(aid, (int32)sdg->dimsizes[i]*fileNTsize, 
  2037.                                 (uint8 *) sdg->dimscales[i]);
  2038.                     if (ret == FAIL) { 
  2039.                         HDfreespace(isscales);
  2040.                         return FAIL;
  2041.                     }
  2042.                 } else {                      /* conversion necessary */
  2043.  
  2044.                     /* allocate conversion buffer */
  2045.                     buf = HDgetspace((uint32)sdg->dimsizes[i] * fileNTsize);
  2046.                     if (buf == NULL) {
  2047.                         HDfreespace(isscales);
  2048.                         return FAIL;
  2049.                     }
  2050.  
  2051.                     /* read scale from file */
  2052.                     ret = Hread(aid,
  2053.                                 (int32) (sdg->dimsizes[i]*fileNTsize), buf);
  2054.                     if (ret == FAIL) {
  2055.                         buf = HDfreespace(buf);
  2056.                         HDfreespace(isscales);
  2057.                         return FAIL;
  2058.                     }
  2059.                             
  2060.                     p = buf;
  2061.  
  2062.                     /* convert, all at once */
  2063.                     DFKconvert(p, sdg->dimscales[i], numtype,
  2064.                                sdg->dimsizes[i], DFACC_READ, 0, 0);
  2065.  
  2066.                     HDfreespace(buf);
  2067.                 }
  2068.             }
  2069.             HDfreespace(isscales);
  2070.             Hendaccess(aid);
  2071.             break;
  2072.  
  2073.         case DFTAG_SDC:    /* coordsys */
  2074.             /* find and allocate necessary space */
  2075.             length =  Hlength(file_id, elmt.tag, elmt.ref);
  2076.             if (length == FAIL) return FAIL;
  2077.             
  2078.             sdg->coordsys = HDgetspace((uint32) length);
  2079.             if (sdg->coordsys==NULL) return FAIL;
  2080.             
  2081.             /* read coordsys */
  2082.             if (Hgetelement(file_id, elmt.tag, elmt.ref, 
  2083.                              (uint8 *) sdg->coordsys) == FAIL)
  2084.                 return FAIL;
  2085.             break;
  2086.             
  2087.         case DFTAG_SDM:    /* max/min */
  2088.             if (fileNT == platnumsubclass) {       /* no conversion */
  2089.                 if (Hgetelement(file_id, elmt.tag, elmt.ref,
  2090.                                 (uint8 *) &(sdg->max_min[0])) == FAIL)
  2091.                     return FAIL;
  2092.             }
  2093.             else {
  2094.                 /* conversion needed */
  2095.  
  2096.                 /* allocate buffer */
  2097.                 buf = HDgetspace((uint32) 2 * fileNTsize);
  2098.                 if (buf == NULL) return FAIL;
  2099.  
  2100.                 /* read and convert max/min */
  2101.                 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
  2102.                     return FAIL;
  2103.  
  2104.                 DFKconvert(buf, &(sdg->max_min[0]), numtype, 2,
  2105.                            DFACC_READ, 0, 0);
  2106.  
  2107.                 HDfreespace(buf);
  2108.             }
  2109.             Ismaxmin = 1;
  2110.             break;
  2111.  
  2112.         case DFTAG_CAL:
  2113.  
  2114.             if (fileNT == platnumsubclass) {       /* no conversion */
  2115.  
  2116.                 /* get size of element */
  2117.                 intn eltSize = Hlength(file_id, elmt.tag, elmt.ref);
  2118.                 if(eltSize == FAIL) return FAIL; 
  2119.                 
  2120.                 if(eltSize == 36) {
  2121.                     /* element is new, double based type */
  2122.                     if (Hgetelement(file_id, elmt.tag, elmt.ref,
  2123.                                     (unsigned char*) &sdg->cal)<0)
  2124.                         return(-1);
  2125.                 } else {
  2126.  
  2127.                     /* element is old float based type */
  2128.                     char *buf2;
  2129.  
  2130.                     /* allocate input buffer */
  2131.                     buf2 = HDgetspace((uint32) 4 * sizeof(float32));
  2132.                     if(buf == NULL) return FAIL;
  2133.  
  2134.                     /* move 'em over */
  2135.                     sdg->ioff     = (float64) buf2[0];
  2136.                     sdg->ioff_err = (float64) buf2[1];
  2137.                     sdg->cal      = (float64) buf2[2];
  2138.                     sdg->cal_err  = (float64) buf2[3];
  2139.                     sdg->cal_type = DFNT_INT16;
  2140.  
  2141.                     HDfreespace(buf2);
  2142.                 }
  2143.             }
  2144.             else {
  2145.  
  2146.                 intn eltSize;
  2147.  
  2148.                 /* get size of element */
  2149.                 eltSize = Hlength(file_id, elmt.tag, elmt.ref);
  2150.                 if(eltSize == FAIL) return FAIL;
  2151.  
  2152.  
  2153.  
  2154.                 /* allocate buffer */
  2155.                 buf = HDgetspace((uint32) eltSize);
  2156.                 if (buf == NULL) return FAIL;
  2157.                 
  2158.                 /* read and convert calibration */
  2159.                 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
  2160.                     return FAIL;
  2161.  
  2162.                 if(eltSize == 36) {
  2163.  
  2164.                     /* element is new, double based type */
  2165.  
  2166.                     /* read in the 64bit float factors */
  2167.                     DFKconvert(buf, 
  2168.                                (unsigned char *) &sdg->cal, 
  2169.                                DFNT_FLOAT64, 4, DFACC_READ, 0, 0);
  2170.  
  2171.  
  2172.                     
  2173.                     /* read in the 32bit integer number type */
  2174.                     DFKconvert(buf + 32,
  2175.                                (unsigned char *) &sdg->cal_type, 
  2176.                                DFNT_INT32, 1, DFACC_READ, 0, 0);
  2177.  
  2178.                 } else {
  2179.  
  2180.                     /* element is old float based type */
  2181.                     uint8 *buf2;
  2182.  
  2183.                     /* allocate translation buffer */
  2184.                     buf2 = HDgetspace((uint32) 4 * sizeof(float32));
  2185.                     if(buf == NULL) return FAIL;
  2186.  
  2187.                     /* convert calibration factors */
  2188.                     DFKconvert(buf, buf2, DFNT_FLOAT32, 4,
  2189.                                DFACC_READ, 0, 0);
  2190.  
  2191.                     /* move 'em over */
  2192.                     sdg->ioff     = (float64) buf2[0];
  2193.                     sdg->ioff_err = (float64) buf2[1];
  2194.                     sdg->cal      = (float64) buf2[2];
  2195.                     sdg->cal_err  = (float64) buf2[3];
  2196.                     sdg->cal_type = DFNT_INT16;
  2197.  
  2198.                     HDfreespace(buf2);
  2199.  
  2200.                 }
  2201.  
  2202.                 HDfreespace(buf);
  2203.                 
  2204.             }
  2205.             
  2206.             IsCal = TRUE;
  2207.  
  2208.             break;
  2209.                     
  2210.         case DFTAG_SDT:
  2211.             FileTranspose = 1;
  2212.             break;
  2213.         default:
  2214.             if((elmt.tag <= DFTAG_BREQ) && (elmt.tag >= DFTAG_EREQ))
  2215.                 HRETURN_ERROR(DFE_BADNDG, FAIL);
  2216.             break;
  2217.         }
  2218.     }
  2219.     return(0);
  2220. }
  2221.  
  2222.  
  2223.  /*---------------------------------------------------------------------------*
  2224.  * Name:    DFSDIputndg
  2225.  * Purpose: Write NDG out to HDF file
  2226.  * Inputs:  file_id: HDF file pointer
  2227.  *          ref: ref to put NDG with
  2228.  *          sdg: struct containing NDG info to put
  2229.  * Returns: 0 on success, FAIL on failure with error set
  2230.  * Users:   HDF programmers, utilities, DFSDputdata, other routines
  2231.  * Invokes: DFIcheck, DFdistart, DFdiadd, DFdiend, DFputelement, DFaccess,
  2232.  *          DFwrite
  2233.  * Remarks: Writes out NTs
  2234.  *---------------------------------------------------------------------------*/
  2235.  
  2236. #ifdef PROTOTYPE
  2237. int DFSDIputndg(int32 file_id, uint16 ref, DFSsdg *sdg)
  2238. #else
  2239. int DFSDIputndg(file_id, ref, sdg)
  2240. int32 file_id;
  2241. uint16 ref;
  2242. DFSsdg *sdg;
  2243. #endif /* PROTOTYPE */
  2244. {
  2245.     int32 i;
  2246.     int j, luf, issdg = 0;    /* issdg=1 if it is NDG SDG  */
  2247.     uint16 luftag;
  2248.     uint8 *buf, *Isscales=NULL, *bufp;
  2249.     uint8 ntstring[4],
  2250.      platnumsubclass, 
  2251.      outNT;            /* file number type subclass    */
  2252.     DFdi nt ;    
  2253.     int32 numtype,    /* current number type    */
  2254.           localNTsize,  /* size of this NT on as it is on this machine */
  2255.           fileNTsize,    /* size of this NT as it will be in the file */
  2256.           scaleNTsize,    /* size of scale NT as it will be in the file */
  2257.           ret, aid;
  2258.     intn len;
  2259.     char *FUNC="DFSDIputndg";
  2260.      
  2261.     HEclear();
  2262.  
  2263.     if (!HDvalidfid(file_id)) HRETURN_ERROR(DFE_BADCALL, FAIL);
  2264.     if (!ref)                 HRETURN_ERROR(DFE_BADREF, FAIL);
  2265.  
  2266.     /* set number type and subclass    */
  2267.     if (sdg->numbertype == DFNT_NONE)
  2268.         DFSDsetNT(DFNT_FLOAT32);     /* default is float32  */
  2269.     numtype = sdg->numbertype;
  2270.     fileNTsize = DFKNTsize(numtype);
  2271.     scaleNTsize = fileNTsize;        /* for now, assume same. MAY CHANGE */
  2272.     outNT = sdg->filenumsubclass;
  2273.     localNTsize = DFKNTsize(numtype | DFNT_NATIVE);
  2274.     platnumsubclass = DFKgetPNSC(numtype, DF_MT);
  2275.     
  2276.     /* prepare to start writing ndg   */
  2277.     if (DFdisetup(10) < 0) return FAIL;
  2278.     
  2279.     /* put ND and ref       */
  2280.     if (DFdiput(sdg->data.tag, sdg->data.ref) < 0) return FAIL;
  2281.     
  2282.     if (Ref.nt<=0) {   /* will not execute if has been written in putsdg  */ 
  2283.         /* construct and write out NT */
  2284.         ntstring[0] = DFNT_VERSION;             /* version */
  2285.         ntstring[1] = (uint8)(numtype & 0xff);  /* type */
  2286.         ntstring[2] = (uint8)(fileNTsize*8);  /* width of number type in bits */
  2287.         ntstring[3] = outNT;          /* class: IEEE or machine class */
  2288.         if (Hputelement(file_id, DFTAG_NT, ref, ntstring, (int32) 4) == FAIL)
  2289.             return FAIL;
  2290.         Ref.nt = ref;
  2291.     }
  2292.     
  2293.     /* write out NDD (dimension record) */
  2294.     if (Ref.dims<=0) {   /* new NDD; write rank, dims, data NT and scale NTs */
  2295.         
  2296.         /* put rank & dimensions in buffer */
  2297.         bufp = DFtbuf;     
  2298.         UINT16ENCODE(bufp, sdg->rank);
  2299.         for (i=0; i<sdg->rank; i++)
  2300.             INT32ENCODE(bufp, sdg->dimsizes[i]);
  2301.         
  2302.         /* put data NT and scale NTs  in buffer */
  2303.         nt.tag = DFTAG_NT;
  2304.         nt.ref = Ref.nt;           /* same NT for scales too */
  2305.         
  2306.         /* "<=" used to put 1 data NT + rank scale NTs in buffer */
  2307.         for (i=0; i<=sdg->rank; i++) {  /* scale NTs written even if no scale!*/
  2308.             UINT16ENCODE(bufp, nt.tag);
  2309.             UINT16ENCODE(bufp, nt.ref);
  2310.         }   
  2311.         /* write out NDD record */
  2312.         ret = Hputelement(file_id,DFTAG_SDD, ref,DFtbuf,(int32) (bufp-DFtbuf));
  2313.         if (ret == FAIL)
  2314.             return FAIL;
  2315.         Ref.dims = ref;
  2316.     }
  2317.     /* write dimension record tag/ref */
  2318.     if (DFdiput(DFTAG_SDD,(uint16) Ref.dims) < 0) return FAIL;
  2319.     
  2320.     /* write out label/unit/format */
  2321.     for (luf=LABEL; luf<=FORMAT; luf++) {
  2322.         luftag = (luf==LABEL) ? DFTAG_SDL : (luf==UNIT) ? DFTAG_SDU : DFTAG_SDF;
  2323.         bufp = DFtbuf;
  2324.         /* this block of code checks if luf is NULL, else writes it */
  2325.         if (!Ref.luf[luf]) {            /* if luf was set */
  2326.             Ref.luf[luf] = -1;          /* assume it is NULL */
  2327.             
  2328.             /* if dataluf non-NULL, set up to write */
  2329.             if (sdg->dataluf[luf] && sdg->dataluf[luf][0]) { 
  2330.                 len = HDstrlen(sdg->dataluf[luf])+1;
  2331.                 HIstrncpy( (char *)bufp, sdg->dataluf[luf], len);
  2332.                 bufp += len;
  2333.             } else {                       /* dataluf NULL */
  2334.                 HIstrncpy( (char *)bufp, "", (int32) 1 );
  2335.                 bufp ++;
  2336.             }
  2337.  
  2338.             /* for each dimluf, if non-NULL, set up to write */
  2339.             if (sdg->dimluf[luf]) {
  2340.                 for (i=0; i<sdg->rank; i++) {
  2341.                     if ( sdg->dimluf[luf][i] &&     
  2342.                          sdg->dimluf[luf][i][0] ) {   /* dimluf not NULL */
  2343.                             len = HDstrlen(sdg->dimluf[luf][i])+1;
  2344.                             HIstrncpy( (char *)bufp, sdg->dimluf[luf][i], len);
  2345.                             bufp += len;
  2346.                     } else {                        /* dimluf NULL */
  2347.                         HIstrncpy( (char *)bufp, "", (int32) 1 );
  2348.                         bufp ++;
  2349.                     }
  2350.                 }    /* i loop     */
  2351.             }    /* dimluf is non-NULL */
  2352.             Ref.luf[luf] = ref; /* remember ref */
  2353.             ret = Hputelement(file_id, luftag, (uint16)Ref.luf[luf],
  2354.                               DFtbuf, (int32) (bufp-DFtbuf));
  2355.             if (ret == FAIL) return FAIL;
  2356.         }  /* luf was set */
  2357.         
  2358.     /* write luf tag/ref */
  2359.         if (Ref.luf[luf]>0)
  2360.             if (DFdiput(luftag, (uint16)Ref.luf[luf]) < 0)
  2361.                 return FAIL;
  2362.     }    /* luf loop    */
  2363.     
  2364.     /* check if there is a scale and write it out */
  2365.     if (!Ref.scales) {        /* if scale set */
  2366.         Isscales = HDgetspace((uint32) sdg->rank);
  2367.         if (Isscales==NULL) return FAIL;
  2368.         Ref.scales = (-1);                  /* assume there is no scale */
  2369.         
  2370.         /* set up Isscales array */
  2371.         for (i=0; i<sdg->rank; i++) {
  2372.             if (sdg->dimscales && sdg->dimscales[i]) {  /* a scale exists */
  2373.                 Isscales[i] = 1;
  2374.                 Ref.scales = 0;             /* flag: write out scales */
  2375.             }
  2376.             else Isscales[i] = 0;
  2377.         }
  2378.     }
  2379.  
  2380.     if (!Ref.scales) {      /* write out scales */
  2381.         /* compute space needed for scales */
  2382.         len = 0;
  2383.         for (i=0; i<sdg->rank; i++)  
  2384.             if (Isscales[i] == 1)
  2385.                 len += sdg->dimsizes[i]*scaleNTsize;
  2386.         len += sdg->rank;
  2387.         
  2388.         aid = Hstartwrite(file_id, DFTAG_SDS, ref, len);
  2389.         if (aid == FAIL ) {
  2390.             HDfreespace(Isscales); 
  2391.             return FAIL;
  2392.         }
  2393.                             /* write Isscales */
  2394.         if (Hwrite(aid, (int32) sdg->rank, Isscales) == FAIL) {
  2395.             HDfreespace(Isscales); 
  2396.             return FAIL;
  2397.         }
  2398.                             /* Write scales */
  2399.         for (j=0; j<sdg->rank; j++) {
  2400.             if (!Isscales[j]) continue;
  2401.             if (platnumsubclass ==outNT) {       /* no conversion needed */
  2402.                 if (Hwrite(aid, (int32) (fileNTsize * sdg->dimsizes[j]),
  2403.                                    (uint8 *) sdg->dimscales[j]) == FAIL) {
  2404.                     HDfreespace(Isscales);
  2405.                     return FAIL;
  2406.                 }
  2407.             }
  2408.             else {              /* convert and write */
  2409.                         /* allocate buffer */
  2410.                 buf = HDgetspace((uint32) (fileNTsize * sdg->dimsizes[j]));
  2411.                 if (buf==NULL) {
  2412.                     HDfreespace(Isscales); 
  2413.                     return FAIL;
  2414.                 }
  2415.                         /* convert, all at once */
  2416.                 DFKconvert(sdg->dimscales[j], buf, numtype,
  2417.                            sdg->dimsizes[j], DFACC_WRITE, 0, 0);
  2418.                 /* write it all out */
  2419.                 if (Hwrite(aid, (int32) (fileNTsize * sdg->dimsizes[j]), buf)
  2420.                              == FAIL) {
  2421.                     HDfreespace(Isscales);
  2422.                     HDfreespace(buf);
  2423.                     return FAIL;
  2424.                 }
  2425.                 buf = HDfreespace(buf);
  2426.             }
  2427.         }
  2428.         Ref.scales = ref;
  2429.         Hendaccess(aid);
  2430.     }
  2431.     Isscales = HDfreespace(Isscales);
  2432.     if (Ref.scales>0)
  2433.         if (DFdiput(DFTAG_SDS, (uint16) Ref.scales) < 0)
  2434.             return FAIL;
  2435.  
  2436.     /* write coordsys */
  2437.     if (!sdg->coordsys || !sdg->coordsys[0]) Ref.coordsys = (-1);
  2438.     if (!Ref.coordsys) {
  2439.         ret = Hputelement(file_id, DFTAG_SDC, ref, (uint8 *)sdg->coordsys,
  2440.                                 (int32) (HDstrlen(sdg->coordsys)+1));
  2441.         if (ret == FAIL) return FAIL;
  2442.         Ref.coordsys = ref;
  2443.     }
  2444.     if (Ref.coordsys>0) if (DFdiput(DFTAG_SDC, (uint16) Ref.coordsys) < 0)
  2445.     return FAIL;
  2446.     
  2447.     /* write max/min */
  2448.     if (!Ref.maxmin) {
  2449.         if (platnumsubclass == outNT) {     /* no conversion */
  2450.             ret = Hputelement(file_id, DFTAG_SDM, ref, 
  2451.                               (uint8 *) &(sdg->max_min[0]), 
  2452.                               (int32) (2 * fileNTsize));
  2453.             if (ret == FAIL) return FAIL;
  2454.             Ref.maxmin = ref;
  2455.         }
  2456.         else {
  2457.         /* allocate buffer */
  2458.             buf = HDgetspace((uint32) 2*fileNTsize); /* max/min is 8 bytes */
  2459.             if (buf==NULL) return FAIL;
  2460.             
  2461.         /* convert */
  2462.             DFKconvert((uint8*) &(sdg->max_min[0]), buf, numtype, 2, DFACC_WRITE, 0, 0);
  2463.  
  2464.         /* write */
  2465.             ret = Hputelement(file_id, DFTAG_SDM, ref, buf,
  2466.                               (int32) (2*fileNTsize));
  2467.             if (ret == FAIL) { 
  2468.                 buf = HDfreespace(buf); return FAIL;
  2469.             }
  2470.             Ref.maxmin = ref;
  2471.             buf = HDfreespace(buf);
  2472.         }
  2473.     }
  2474.     if (Ref.maxmin>0)
  2475.         if (DFdiput(DFTAG_SDM, (uint16) Ref.maxmin) < 0)
  2476.             return FAIL;
  2477.     Ref.maxmin = (-1);        /* max/min should be reset for each data set */
  2478.     
  2479.     /* Write calibration. */
  2480.     if (!Ref.cal) {
  2481.         
  2482.         
  2483.         if (platnumsubclass == outNT) {     /* no conversion */
  2484.             if (Hputelement(file_id, DFTAG_CAL, ref, 
  2485.                             (unsigned char *) &sdg->cal,
  2486.                             (int32) 36)<0) 
  2487.                 return(-1);
  2488.             Ref.cal = ref;
  2489.         }
  2490.         else {
  2491.             /* allocate buffer */
  2492.             uint8 *buf;
  2493.             
  2494.             /* allocate translation buffer */
  2495.             buf = (uint8 *) HDgetspace((uint32) 
  2496.                                        4 * sizeof(float64) +
  2497.                                        1 * sizeof(int32));
  2498.             if(buf == NULL) return FAIL;
  2499.             
  2500.             /* convert doubles */            
  2501.             DFKconvert((uint8*) &sdg->cal, buf, 
  2502.                        DFNT_FLOAT64, 4, DFACC_WRITE, 0, 0);
  2503.             
  2504.             /* convert int */
  2505.             DFKconvert((uint8*) &sdg->cal_type, buf + 32, 
  2506.                        DFNT_INT32, 1, DFACC_WRITE, 0, 0);
  2507.             
  2508.             /* write it into the file */
  2509.             if (Hputelement(file_id, DFTAG_CAL, ref, 
  2510.                             (unsigned char *) buf,
  2511.                             (int32) 36) < 0) 
  2512.                 return(-1);
  2513.             Ref.cal = ref;
  2514.             HDfreespace(buf);
  2515.             
  2516.         }
  2517.     }
  2518.  
  2519.     
  2520.     if (Ref.cal>0)
  2521.         if (DFdiput(DFTAG_CAL, (uint16) Ref.cal) < 0)
  2522.             return(-1);
  2523.     Ref.cal = (-1);        /* Calibration should be reset for each data set */
  2524.     
  2525.     
  2526.     if (!Ref.transpose) {        /* if transposed, add transpose tag */
  2527.         if (Hdupdd(file_id, DFTAG_SDT, ref, DFTAG_SDD, ref) == FAIL)
  2528.             return FAIL;
  2529.         Ref.transpose = ref;
  2530.     }
  2531.     if (Ref.transpose>0)
  2532.         if (DFdiput(DFTAG_SDT, (uint16) Ref.transpose) < 0)
  2533.             return FAIL;
  2534.  
  2535.     if (numtype == DFNT_FLOAT32) {  /* if float32, add a DFTAG_SDLNK   */
  2536.         DFdi lnkdd[2];
  2537.  
  2538.         issdg = 1;
  2539.         lnkdd[0].tag=DFTAG_NDG;
  2540.         lnkdd[0].ref = ref;
  2541.         lnkdd[1].tag=DFTAG_SDG;
  2542.         lnkdd[1].ref = ref;
  2543.         bufp = DFtbuf;
  2544.         for (i=0; i<2; i++)    {
  2545.             UINT16ENCODE(bufp, lnkdd[i].tag);
  2546.             UINT16ENCODE(bufp, lnkdd[i].ref);
  2547.         }
  2548.         ret = Hputelement(file_id, DFTAG_SDLNK, ref,
  2549.                                     DFtbuf,(int32) (bufp-DFtbuf));
  2550.         if (ret == FAIL) return FAIL;
  2551.  
  2552.     /* write DFTAG_SDLNK  */
  2553.         if (DFdiput(DFTAG_SDLNK, ref) < 0) return FAIL;
  2554.     }
  2555.     
  2556.     /* write out NDG */
  2557.     if (DFdiwrite(file_id, DFTAG_NDG, ref) < 0) return FAIL;
  2558.     /* write an SDG point to the dataset if it is an NDG SDG  */
  2559.     if (issdg)    {
  2560.         if (Hdupdd(file_id, DFTAG_SDG, ref, DFTAG_NDG, ref) < 0) {
  2561.             Hclose(file_id); return FAIL;
  2562.         }
  2563.     }
  2564.     return(0);
  2565. }
  2566.  
  2567. /*-----------------------------------------------------------------------------
  2568.  * Name:    DFSDIendslice
  2569.  * Purpose: Write of data to SDG completed, write SDG and close file
  2570.  * Inputs:  isfortran: true if called from Fortran
  2571.  * Returns: 0 on success, FAIL on failure with error set
  2572.  * Users:   DFSDIputdata
  2573.  * Invokes: DFSDputsdg, Hclose, HERROR
  2574.  * Method:  call DFSDputsdg, close Sfile_id
  2575.  * Remarks: checks that slice writes were completed.
  2576.  *---------------------------------------------------------------------------*/
  2577.  
  2578. #ifdef PROTOTYPE
  2579. int DFSDIendslice(int isfortran)
  2580. #else
  2581. int DFSDIendslice(isfortran)
  2582.     int isfortran;
  2583. #endif /* PROTOTYPE */
  2584. {
  2585.     int i, ret;
  2586.     char *FUNC="DFSDIendslice";
  2587.  
  2588.     HEclear();
  2589.  
  2590.     if (Sfile_id == DF_NOFILE) {
  2591.         HERROR(DFE_BADCALL); return FAIL;
  2592.     }
  2593.  
  2594.     /* check if slice writes complete */
  2595.     for (i=0; i<Writesdg.rank; i++) {
  2596.         if (!Fortorder && (i==0) && (Sddims[i]==Writesdg.dimsizes[i]))continue;
  2597.         if ((isfortran||Fortorder) && (i==Writesdg.rank-1) &&
  2598.         (Sddims[i] == Writesdg.dimsizes[i])) continue;
  2599.         if((isfortran||Fortorder || i>0) && (!Fortorder || i<Writesdg.rank-1)
  2600.        && (Sddims[i] == 0)) continue;
  2601.         HERROR(DFE_BADCALL);
  2602.         return(FAIL);
  2603.     }
  2604.  
  2605.  
  2606.     if (DFSDIputndg(Sfile_id, Writeref, &Writesdg)<0)  {
  2607.         Hclose(Sfile_id); return FAIL;
  2608.     }
  2609.     /* old nsdg table should be reset next time  */
  2610.     if (nsdghdr != NULL)    {
  2611.     if (nsdghdr->nsdg_t != NULL)     {
  2612.         DFnsdgle *rear, *front;
  2613.  
  2614.         rear = nsdghdr->nsdg_t;
  2615.         front = rear->next;
  2616.         while (rear != NULL)    {
  2617.            if ((rear=(DFnsdgle *)HDfreespace((void *) rear)) != NULL)
  2618.                   return FAIL;
  2619.             rear = front;
  2620.            if (rear != NULL) front = rear->next;
  2621.         }
  2622.         nsdghdr->size=0;
  2623.         nsdghdr->nsdg_t = NULL;
  2624.         lastnsdg.tag = DFTAG_NULL;
  2625.         lastnsdg.ref = 0;
  2626.         }
  2627.         if ((nsdghdr=(DFnsdg_t_hdr *)HDfreespace((void *)nsdghdr)) != NULL)
  2628.         return FAIL;
  2629.     }
  2630.     
  2631.     Lastref = Writeref;        /* remember ref written */
  2632.     Writeref=0;            /* don't know ref to write next */
  2633.  
  2634.     Hendaccess(Writesdg.aid);
  2635.     ret = Hclose(Sfile_id);
  2636.     Sfile_id = 0;       /* partial write complete */
  2637.     Sddims = (int32 *) HDfreespace((char*) Sddims);
  2638.  
  2639.     return(ret);
  2640. }
  2641.  
  2642.  
  2643. /******************************************************************************/
  2644. /*----------------------- Internal routines ---------------------------------*/
  2645. /******************************************************************************/
  2646.  
  2647. /*-----------------------------------------------------------------------------
  2648.  * Name:    DFSDIopen
  2649.  * Purpose: open or reopen a file
  2650.  * Inputs:  filename: name of file to open
  2651.  *          access : access mode
  2652.  * Returns: file id on success, -1 (FAIL) on failure with error set
  2653.  * Users:   HDF systems programmers, many SD routines
  2654.  * Invokes: DFopen
  2655.  * Remarks: This is a hook for someday providing more efficient ways to
  2656.  *          reopen a file, to avoid re-reading all the headers
  2657.  *---------------------------------------------------------------------------*/
  2658.  
  2659. #ifdef PROTOTYPE
  2660. int32 DFSDIopen(char *filename, int access)
  2661. #else
  2662. int32 DFSDIopen(filename, access)
  2663. char *filename;
  2664. int access;
  2665. #endif /* PROTOTYPE */
  2666. {
  2667.  
  2668.     int32 file_id;
  2669.     char *FUNC="DFSDIopen";
  2670.  
  2671.     if (Sfile_id!=DF_NOFILE) {     /* in the middle of a partial write */
  2672.         HERROR(DFE_ALROPEN); return(FAIL);
  2673.     }
  2674.  
  2675.         /* use reopen if same file as last time - more efficient */
  2676.     if ((HDstrcmp(Lastfile,filename)) || (access==DFACC_CREATE)) {
  2677.         /* open a new file, delete nsdg table and reset lastnsdg  */
  2678.         if (nsdghdr != NULL)     {
  2679.             if (nsdghdr->nsdg_t != NULL)     {
  2680.                 DFnsdgle *rear, *front;
  2681.  
  2682.                 rear = nsdghdr->nsdg_t;
  2683.                 while (rear != NULL)    {
  2684.                     front = rear->next;
  2685.                     if ((rear=(DFnsdgle *)HDfreespace((void *) rear)) != NULL)
  2686.                         return FAIL;
  2687.                     rear = front;
  2688.                 }
  2689.                 nsdghdr->size=0;
  2690.                 nsdghdr->nsdg_t = NULL;
  2691.                 lastnsdg.tag = DFTAG_NULL;
  2692.                 lastnsdg.ref = 0;
  2693.             }
  2694.             if ((nsdghdr=(DFnsdg_t_hdr *)HDfreespace((void *)nsdghdr))
  2695.                     != NULL)
  2696.                 return FAIL;
  2697.  
  2698.         }
  2699.         /* treat create as different file */
  2700.         file_id = Hopen(filename, access, (int16) 0);
  2701.         if (file_id == FAIL) {
  2702.             return FAIL;
  2703.         }
  2704.         Newdata = (-1);         /* data in Readsdg is not fresh */ 
  2705.         Readsdg.data.ref = 0;   /* No SDG read yet */
  2706.  
  2707.         /* remember no info written to file */
  2708.         Ref.scales  = (Ref.scales  >= 0) ? 0 : Ref.scales;
  2709.         Ref.luf[LABEL]  = (Ref.luf[LABEL]  >= 0) ? 0 : Ref.luf[LABEL];
  2710.         Ref.luf[UNIT]   = (Ref.luf[UNIT]   >= 0) ? 0 : Ref.luf[UNIT];
  2711.         Ref.luf[FORMAT] = (Ref.luf[FORMAT] >= 0) ? 0 : Ref.luf[FORMAT];
  2712.         Ref.dims    = (Ref.dims    >= 0) ? 0 : Ref.dims;
  2713.         Ref.coordsys = (Ref.coordsys >= 0) ? 0 : Ref.coordsys;
  2714.         Ref.maxmin = (Ref.maxmin >= 0) ? 0 : Ref.maxmin;
  2715.         Ref.nt = (Ref.nt >= 0) ? 0 : Ref.nt;
  2716.         Ref.transpose = (Ref.transpose >= 0)? 0 : Ref.transpose;
  2717.     }
  2718.     else {
  2719.         file_id = Hopen(filename, access, (int16) 0);
  2720.         if (file_id == FAIL) 
  2721.             return FAIL;
  2722.     }
  2723.     /* if read, set up nsdg table */
  2724.     if (nsdghdr == NULL)     {
  2725.         nsdghdr = (DFnsdg_t_hdr *)HDgetspace((uint32)sizeof(DFnsdg_t_hdr));
  2726.         if (nsdghdr == NULL)        {
  2727.             HERROR(DFE_NOSPACE); return(FAIL);
  2728.         }
  2729.         nsdghdr->size = 0;
  2730.         nsdghdr->nsdg_t = NULL;
  2731.     }
  2732.     if ((nsdghdr->nsdg_t == NULL) && (access == DFACC_READ))  {
  2733.         if (DFSDIsetnsdg_t(file_id,nsdghdr ) < 0) return(FAIL);
  2734.         lastnsdg.tag = DFTAG_NULL;
  2735.         lastnsdg.ref = 0;
  2736.     }
  2737.     
  2738.     HIstrncpy(Lastfile, filename, DF_MAXFNLEN);
  2739.     /* remember filename, so reopen may be used next time if same file*/
  2740.  
  2741.     return(file_id);
  2742. }
  2743.  
  2744.  
  2745. /*-----------------------------------------------------------------------------
  2746.  * Name:    DFSDIsdginfo
  2747.  * Purpose: Locates next sdg in file
  2748.  * Inputs:  file_id: pointer to DF file
  2749.  * Returns: 0 on success, FAIL on failure with error set
  2750.  * Users:   HDF systems programmers, DFSDgetdims, DFSDgetdata
  2751.  * Invokes: DFIfind, DFSDIgetndg
  2752.  * Method:  Call DFIfind to find SDG, then DFSDIgetndg to read it in to Readsdg
  2753.  * Remarks: none
  2754.  *---------------------------------------------------------------------------*/
  2755.  
  2756. #ifdef PROTOTYPE
  2757. int DFSDIsdginfo(int32 file_id)
  2758. #else
  2759. int DFSDIsdginfo(file_id)
  2760. int32 file_id;
  2761. #endif /* PROTOTYPE */
  2762. {
  2763.     DFdi *ptr;
  2764.     char *FUNC="DFSDIsdginfo";
  2765.     int32 aid;
  2766.  
  2767.     HEclear();
  2768.  
  2769.     if (!HDvalidfid(file_id)) {
  2770.         HERROR(DFE_BADCALL); return FAIL;
  2771.     }
  2772.     ptr = (DFdi *)HDgetspace(sizeof(DFdi));
  2773.     if (Readref != 0)     {
  2774.         aid = Hstartread(file_id, DFTAG_NDG, Readref);
  2775.         if (aid  != FAIL)    {
  2776.             ptr->ref = Readref;
  2777.             ptr->tag = DFTAG_NDG;
  2778.             Hendaccess(aid);
  2779.         }
  2780.         else                {
  2781.             aid = Hstartread(file_id, DFTAG_SDG, Readref);
  2782.             if (aid != FAIL)    {
  2783.                 ptr->ref = Readref;
  2784.                 ptr->tag = DFTAG_SDG;
  2785.                 Hendaccess(aid);
  2786.             }
  2787.             else     return FAIL;
  2788.         }
  2789.     }
  2790.     else    {
  2791.         if (DFSDInextnsdg(nsdghdr, ptr) < 0) return FAIL;
  2792.         if ((ptr->tag != DFTAG_NDG) && (ptr->tag != DFTAG_SDG)) {
  2793.             HERROR(DFE_BADTAG); return FAIL;
  2794.         }
  2795.         if (ptr->ref <=0)       {
  2796.             HERROR(DFE_BADREF); return FAIL;
  2797.         }
  2798.         Readref = ptr->ref;
  2799.     }
  2800.  
  2801.     /* find next sd object */
  2802.     if (DFSDIgetndg(file_id, ptr->tag, ptr->ref, &Readsdg) <0)
  2803.         return FAIL;
  2804.  
  2805.     /* remember what type of thing we just read */
  2806.     if (ptr->tag == DFTAG_NDG)
  2807.         Readsdg.isndg = 1;
  2808.     else
  2809.         Readsdg.isndg = 0;
  2810.  
  2811.     Lastref = ptr->ref;           /* remember ref read */
  2812.     lastnsdg.tag = ptr->tag;
  2813.     lastnsdg.ref = ptr->ref;
  2814.  
  2815.     Newdata=1;      /* now Readsdg is fresh */
  2816.     Readref = 0;
  2817.     if ((ptr=(DFdi *)HDfreespace((char *)ptr)) != NULL)
  2818.         return FAIL;
  2819.  
  2820.     return(0);
  2821. }
  2822.  
  2823. /*-----------------------------------------------------------------------------
  2824.  * Name:    DFSDIrefresh
  2825.  * Purpose: get next sdg if Readsdg is not fresh
  2826.  * Inputs:  filename
  2827.  * Returns: 0 on success, FAIL on failure with error set
  2828.  * Users:   HDF systems programmers, functions in dfsdF.c
  2829.  * Invokes: DFSDIopen, DFSDIsdginfo
  2830.  * Method:  test Newdata and Nextsdg, call DFSDIsdginfo if necessary
  2831.  * Remarks: none
  2832.  *---------------------------------------------------------------------------*/
  2833.  
  2834. #ifdef PROTOTYPE
  2835. intn DFSDIrefresh(char *filename)
  2836. #else
  2837. intn DFSDIrefresh(filename)
  2838. char *filename;
  2839. #endif /* PROTOTYPE */
  2840. {
  2841.       int32 file_id;
  2842.       char *FUNC="DFSDgetdims";
  2843.  
  2844.       HEclear();
  2845.       if (Newdata != 1 || Nextsdg) { /* if Readsdg not fresh  */
  2846.           file_id = DFSDIopen(filename, DFACC_READ); /* open/reopen file */
  2847.           if (file_id == FAIL)
  2848.               return FAIL;
  2849.           if (DFSDIsdginfo(file_id)<0) {      /* reads next SDG from file */
  2850.               Hclose(file_id); return FAIL;   
  2851.         /* on error, close file and return */
  2852.           }
  2853.           if (Hclose(file_id)<0) return FAIL;
  2854.           Nextsdg = 0;
  2855.       }
  2856.      return(0);
  2857. }
  2858.  
  2859. /*-----------------------------------------------------------------------------
  2860.  * Name:    DFSDIisndg
  2861.  * Purpose: is the current read sds an sdg or nsdg/ndg
  2862.  * Inputs:  isndg: 0 -- pure sdg( written by 3.1); 1 -- nsdg/ndg 
  2863.  * Returns: 0 on success, FAIL on failure with error set
  2864.  * Users:   HDF systems programmers, functions in dfsdF.c
  2865.  * Invokes: none
  2866.  * Method:  Assigns Readsdg.isndg to isndg.
  2867.  * Remarks: none
  2868.  *---------------------------------------------------------------------------*/
  2869.  
  2870. #ifdef PROTOTYPE
  2871. int DFSDIisndg(intn *isndg)
  2872. #else
  2873. int DFSDIisndg(isndg)
  2874. intn *isndg;
  2875. #endif /* PROTOTYPE */
  2876. {
  2877.     *isndg = Readsdg.isndg;
  2878.     return(0);
  2879. }
  2880.  
  2881. /*-----------------------------------------------------------------------------
  2882.  * Name:    DFSDIgetrrank
  2883.  * Purpose: get rank of the current sdg, to transpose dims for Fortran
  2884.  * Inputs:  &rank: address to return the rank
  2885.  * Returns: 0 on success, FAIL on failure with error set
  2886.  * Users:   HDF systems programmers, functions in dfsdF.c
  2887.  * Invokes: none
  2888.  * Method:  Assigns Readsdg.rank to rank.
  2889.  * Remarks: none
  2890.  *---------------------------------------------------------------------------*/
  2891.  
  2892. #ifdef PROTOTYPE
  2893. int DFSDIgetrrank(intn *rank)
  2894. #else
  2895. int DFSDIgetrrank(rank)
  2896. intn *rank;
  2897. #endif /* PROTOTYPE */
  2898. {
  2899.     *rank = (intn)Readsdg.rank;
  2900.     return(0);
  2901. }
  2902.  
  2903. /*-----------------------------------------------------------------------------
  2904.  * Name:    DFSDIgetwrank
  2905.  * Purpose: get rank of the current sdg, to transpose dims for Fortran
  2906.  * Inputs:  &rank: address to return the rank
  2907.  * Returns: 0 on success, FAIL on failure with error set
  2908.  * Users:   HDF systems programmers, functions in dfsdF.c
  2909.  * Invokes: none
  2910.  * Method:  Assigns Readsdg.rank to rank.
  2911.  * Remarks: none
  2912.  *---------------------------------------------------------------------------*/
  2913.  
  2914. #ifdef PROTOTYPE
  2915. int DFSDIgetwrank(intn *rank)
  2916. #else
  2917. int DFSDIgetwrank(rank)
  2918. intn *rank;
  2919. #endif /* PROTOTYPE */
  2920. {
  2921.     *rank = (intn)Writesdg.rank;
  2922.     return(0);
  2923. }
  2924.  
  2925.  
  2926. /*-----------------------------------------------------------------------------
  2927.  * Name:    DFSDIclear
  2928.  * Purpose: Reset all "set" values, free allocated space
  2929.  * Inputs:  sdg: pointer to sdg struct to clear
  2930.  * Globals: Ref
  2931.  * Returns: 0 on success, FAIL on error with error set
  2932.  * Users:   HDF users, utilities, other routines
  2933.  * Invokes: none
  2934.  * Method:  Release space in sdg
  2935.  * Remarks: none
  2936.  *---------------------------------------------------------------------------*/
  2937.  
  2938. #ifdef PROTOTYPE
  2939. int DFSDIclear(DFSsdg *sdg)
  2940. #else
  2941. int DFSDIclear(sdg)
  2942. DFSsdg *sdg;
  2943. #endif /* PROTOTYPE */
  2944. {
  2945.     int luf, i;
  2946.     char *FUNC="DFSDIclear";
  2947.  
  2948.     HEclear();
  2949.  
  2950.     if (Sfile_id !=DF_NOFILE) {        /* cannot clear during slice writes */
  2951.         HERROR(DFE_BADCALL); return FAIL;
  2952.     }
  2953.     sdg->dimsizes = (int32 *) HDfreespace((char*) sdg->dimsizes);
  2954.  
  2955.     sdg->coordsys = HDfreespace(sdg->coordsys);
  2956.  
  2957.         /* free label/unit/format pointers */
  2958.     for (luf=LABEL; luf<=FORMAT; luf++) {
  2959.         if (sdg->dimluf[luf])       /* free strings */
  2960.             for (i=0; i<sdg->rank; i++)
  2961.                 sdg->dimluf[luf][i] = HDfreespace(sdg->dimluf[luf][i]);
  2962.  
  2963.     /* free string pointers */
  2964.         sdg->dimluf[luf] = (char **) HDfreespace((char*) sdg->dimluf[luf]);
  2965.  
  2966.     /* free data string */
  2967.         sdg->dataluf[luf] = HDfreespace(sdg->dataluf[luf]);
  2968.     }
  2969.  
  2970.     /* free scale pointers */
  2971.     if (sdg->dimscales)
  2972.         for (i=0; i<sdg->rank; i++)
  2973.             sdg->dimscales[i] = (uint8 *)
  2974.         HDfreespace((char*) sdg->dimscales[i]);
  2975.  
  2976.     /* free array of scale pointers */
  2977.     sdg->dimscales = (uint8 **) HDfreespace((int8 *)sdg->dimscales);
  2978.  
  2979.     sdg->rank = 0;
  2980.     /* number type is independant to dimsizes   4/7/92  sxu
  2981.     sdg->numbertype = DFNT_NONE;
  2982.     sdg->filenumsubclass = DFNTF_NONE;
  2983.     */
  2984.     sdg->aid = (int32)-1;
  2985.     sdg->compression = (int32)0;
  2986.     FileTranspose = 0;
  2987.  
  2988.     Ref.dims = -1;
  2989.     Ref.scales = Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = (-1);
  2990.     Ref.coordsys = Ref.maxmin = (-1);
  2991.     return(0);
  2992. }
  2993.  
  2994.  
  2995. /*-----------------------------------------------------------------------------
  2996.  * Name:    DFSDIgetdata
  2997.  * Purpose: Get data from SDG.  Will sequence to next SDG if DFSDgetdims not
  2998.  *          called.
  2999.  * Inputs:  filename: name of HDF file to use
  3000.  *          rank: no of dimensions of array "data"
  3001.  *          maxsizes: actual dimensions of array "data"
  3002.  *          data: data for returning scientific data
  3003.  *          isfortran : 0 if called from C, 1 when called from FORTRAN
  3004.  * Returns: 0 on success, FAIL on failure with error set
  3005.  * Outputs: actual scientific data in array
  3006.  * Users:   DFSDgetdata
  3007.  * Invokes: DFSDIgetslice, HDgetspace, HDfreespace, DFSDIopen, Hclose,
  3008.  *          HERROR, DFSDIsdginfo
  3009.  * Method:  Open file, call DFSDIsdginfo to read sdg if necessary, set up
  3010.  *          window start and end arrays, call DFSDIgetslice.
  3011.  * Remarks: maxsizes may be larger than actual size.  In that event, the actual
  3012.  *          data may not be contiguous in the array "data"
  3013.  *          User sets maxsizes before call.
  3014.  *---------------------------------------------------------------------------*/
  3015.  
  3016. #ifdef PROTOTYPE
  3017. int DFSDIgetdata(char *filename, intn rank, int32 maxsizes[], void *data,
  3018.          int isfortran)
  3019. #else
  3020. int DFSDIgetdata(filename, rank, maxsizes, data, isfortran)
  3021. char *filename;
  3022. intn rank;
  3023. int32 maxsizes[];
  3024. void *data;
  3025. int isfortran;
  3026. #endif /* PROTOTYPE */
  3027. {
  3028.     int32 *winst, *windims;
  3029.     int ret, i;
  3030.     int32 file_id;
  3031.     char *FUNC="DFSDIgetdata";
  3032.  
  3033.     HEclear();
  3034.  
  3035.     if (Newdata!=1 || Nextsdg) { /* if Readsdg not fresh */
  3036.         file_id = DFSDIopen(filename, DFACC_READ);
  3037.         if (file_id == DF_NOFILE) return FAIL;
  3038.         if (DFSDIsdginfo(file_id)<0)  {   /* reads next SDG from file */
  3039.             Hclose(file_id); return FAIL;
  3040.         }
  3041.         if (Hclose(file_id)==FAIL) return FAIL;
  3042.     }
  3043.  
  3044.     winst = (int32 *) HDgetspace((uint32) Readsdg.rank * sizeof(int32));
  3045.     if (winst==NULL) return FAIL;
  3046.     windims = (int32 *) HDgetspace((uint32) Readsdg.rank * sizeof(int32));
  3047.     if (windims==NULL) {
  3048.         HDfreespace((char*) winst);
  3049.         return FAIL;
  3050.     }
  3051.  
  3052.     for (i=0; i<rank; i++) {
  3053.         winst[i] = 1;
  3054.         windims[i] = Readsdg.dimsizes[i];
  3055.     }
  3056.  
  3057.     ret = DFSDIgetslice(filename, winst, windims, data, maxsizes, isfortran);
  3058.     HDfreespace((char*) winst);
  3059.     HDfreespace((char*) windims);
  3060.     Nextsdg = 1;
  3061.     return(ret);
  3062. }
  3063.  
  3064.  
  3065. /*-----------------------------------------------------------------------------
  3066.  * Name:    DFSDIputdata
  3067.  * Purpose: Writes entire SDG to file
  3068.  * Inputs:  filename: name of HDF file to use
  3069.  *          rank: rank of data array
  3070.  *          dimsizes: sizes of the dimensions of data array
  3071.  *          data: array that holds data
  3072.  *          accmode: 0 if write to new file, 1 if append to file
  3073.  *          isfortran: 0 if C, 1 if FORTRAN
  3074.  * Globals: Writeref
  3075.  * Returns: 0 on success, FAIL on failure with error set
  3076.  * Users:   HDF users, utilities, other routines
  3077.  * Invokes: DFSDIopen, Hclose, HDgetspace, HDfreespace, DFSDIputslice,
  3078.  *          DFSDstartslice, DFSDIendslice
  3079.  * Method:  Create file if necessary, allocate arrays, call slice routines
  3080.  *---------------------------------------------------------------------------*/
  3081.  
  3082. #ifdef PROTOTYPE
  3083. int DFSDIputdata(char *filename, intn rank, int32 *dimsizes, void *data,
  3084.          int accmode, int isfortran)
  3085. #else
  3086. int DFSDIputdata(filename, rank, dimsizes, data, accmode, isfortran)
  3087. char *filename;
  3088. intn  rank;
  3089. int32   *dimsizes;
  3090. void *data;
  3091. int accmode;
  3092. int isfortran;
  3093. #endif /* PROTOTYPE */
  3094. {
  3095.     int ret;
  3096.     int32 file_id;
  3097.     char *FUNC="DFSDIputdata";
  3098.  
  3099.     HEclear();
  3100.  
  3101.     if (!accmode) {                             /* new file */
  3102.         file_id = DFSDIopen(filename, DFACC_CREATE);
  3103.         if (file_id == DF_NOFILE) return FAIL;
  3104.         if (Hclose(file_id) == FAIL) return FAIL;
  3105.     }
  3106.  
  3107.     if (Ref.dims)       /* don't call setdims if already called */
  3108.         if (DFSDsetdims(rank, dimsizes)<0) return FAIL;
  3109.  
  3110.     if (DFSDstartslice(filename)<0) return FAIL;
  3111.  
  3112.     if ((ret=DFSDIputslice(Writesdg.dimsizes, data, dimsizes, isfortran)) <0)
  3113.         return ret;
  3114.  
  3115.     return DFSDIendslice(isfortran);
  3116. }
  3117.  
  3118. /*----------------------------------------------------------------------------
  3119.  * Name:    DFSDIgetslice
  3120.  * Purpose: Get slice of data from SDG.  Will sequence to next SDG if
  3121.  *          DFSDgetdims, DFSDgetdata or DFSDgetslice not called earlier.
  3122.  * Inputs:  filename: name of HDF file to use
  3123.  *          winst: array of size = rank of data, containing start of slice
  3124.  *          windims: array of size rank, containing size of slice
  3125.  *          data: array for returning slice
  3126.  *          dims: dimensions of array data
  3127.  *          isfortran : 0 if called from C, 1 when called from FORTRAN
  3128.  * Returns: 0 on success, FAIL on failure with error set
  3129.  * Outputs: slice of data in data
  3130.  * Users:   DFSDIgetdata
  3131.  * Invokes: DFSDIopen, Hclose, HERROR, DFSDIsdginfo, DFaccess, DFread
  3132.  * Method:  Open file, call DFSDIsdginfo to read sdg if necessary, read the
  3133.  *          data, convert types if necessary, place in data as appropriate
  3134.  *          data is assumed column major for FORTRAN, row major for C
  3135.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  3136.  *          data may not be contiguous in the array "data".
  3137.  *          User sets dims before call.
  3138.  *--------------------------------------------------------------------------*/
  3139.  
  3140. /*****************************************************************************/
  3141. /* DESIGN DECISIONS                                                          */
  3142. /*****************************************************************************/
  3143. /* 
  3144.    A. All stride/index/offset value will, when this is done -- refer to
  3145.       element counts rather than byte counts in the name of consistency.
  3146.  
  3147.    B. The conversion buffers/allcated areas... will all be char buffers --
  3148.       providing that the Cray-2 is cooperative.
  3149.                                          */    
  3150. /*****************************************************************************/
  3151.  
  3152. /*****************************************************************************/
  3153. /* CHANGE LOG                                                                */
  3154. /*****************************************************************************/
  3155. /*
  3156.   A.
  3157.                                          */
  3158. /*****************************************************************************/
  3159.  
  3160. #ifdef PROTOTYPE
  3161. int DFSDIgetslice(char *filename, int32 winst[], int32 windims[],
  3162.           void *data, int32 dims[], int isfortran)
  3163. #else
  3164. int DFSDIgetslice(filename, winst, windims, data, dims, isfortran)
  3165.     char    *filename;  /* HDF file containing the dataset */
  3166.     int32   winst[];    /* array containing the coordinates of the start */
  3167.                             /* of the slice in the HDF file */
  3168.     int32    windims[];    /* array containing the size of the slice */
  3169.     int32    dims[];        /* array containing the dimensions of data[] */
  3170.     void    *data;        /* array to hold the floating point data read*/
  3171.     int        isfortran;    /* true if called from Fortran */
  3172. #endif /* PROTOTYPE */
  3173.  
  3174. {
  3175.     intn
  3176.         rank;           /* number of dimensions in data[] */
  3177.     int32
  3178.         leastsig,       /* fastest varying subscript in the array */
  3179.         error,          /* flag if an error occurred, */
  3180.                             /* used by DFconvert macro */
  3181.         convert,        /* true if machine NT != NT to be read */
  3182.         transposed,     /* true if we must transpose the data before writing */
  3183.         done,           /* true if we are at the end of the slice */
  3184.         aid; 
  3185.     int32
  3186.         i, j,           /* temporary loop index */
  3187.         issdg,          /* 1 -- pure sdg. do what HDF3.1 does   */
  3188.         *wstart,        /* tmp array containing starting slice dims */
  3189.         *wdims,         /* tmp array containing the slice size */
  3190.         *adims,         /* tmp array containing the dimensions of data[] */
  3191.         *fdims,         /* tmp array containing the dimensions */
  3192.                             /* of the dataset in the file */
  3193.         numtype,    /* current number type  */
  3194.         fileNTsize, /* size of this NT in the file  */
  3195.         localNTsize,    /* size of this NT as it occurs in this machine */
  3196.         numelements,    /* number of floats to read at once */
  3197.         readsize,       /* number of bytes to read at once */
  3198.         datastride,         /* number of floats in one row of data[] */
  3199.         *offset,        /* array for accessing the next element in data[] */
  3200.         *foffset,       /* array for accessing the next element in the file */
  3201.         *dimsleft,      /* array for tracking the current position in data[] */
  3202.         isnative, 
  3203.         fileoffset,     /* offset into the current dataset in the file */
  3204.         machinetype;    /* assigned DF_MT.  used for debugging */
  3205.     uint8
  3206.         platnumsubclass, /* class of this NT for this platform */
  3207.          fileNT,     /* file number subclass    */
  3208.         *scatterbuf,    /* buffer to hold the current row contiguously */
  3209.         *sp,        /* ptr into scatterbuf         */
  3210.         *datap,         /* ptr into data[] at starting offset */
  3211.                             /* of current block */
  3212.         *dp,            /* ptr into data[] at an element of the current row */
  3213.         *buf;           /* buffer containing the converted current row */
  3214.     int32  file_id;     /* HDF file pointer */
  3215.     char *FUNC="DFSDIgetslice";
  3216.  
  3217.     HEclear();
  3218.  
  3219.     if (!data) {
  3220.         HERROR(DFE_BADPTR); return FAIL;
  3221.     }
  3222.  
  3223.     file_id = DFSDIopen(filename, DFACC_READ);
  3224.     if (file_id == DF_NOFILE) return FAIL;
  3225.  
  3226.     if (Newdata!=1) {        /* if Readsdg not fresh */
  3227.         if (DFSDIsdginfo(file_id)<0)  { /* reads next SDG from file */
  3228.             Hclose(file_id); return FAIL;
  3229.         }
  3230.     }
  3231.     rank = Readsdg.rank;
  3232.     numtype = Readsdg.numbertype;
  3233.     isnative = DFNT_NATIVE;
  3234.     machinetype = DF_MT;
  3235.     platnumsubclass = DFKgetPNSC(numtype, DF_MT);
  3236.     localNTsize = DFKNTsize(numtype | isnative);
  3237.     fileNTsize = DFKNTsize(numtype);
  3238.     fileNT = Readsdg.filenumsubclass;
  3239.     issdg = Readsdg.isndg? 0: 1;
  3240.  
  3241.     /* get dimensions of slice to extract, set nwindims. also err check */
  3242.     for (i=0; i < (int32)rank; i++) {
  3243.         /* check validity for the dimension ranges */
  3244.         if ((windims[i] < 1) || (winst[i] < 1)
  3245.             || (winst[i]+windims[i]-1 > Readsdg.dimsizes[i])) {
  3246.             HERROR(DFE_BADDIM);
  3247.             Hclose(file_id);
  3248.             return FAIL;
  3249.         }
  3250.         /* check if space allocated is sufficient */
  3251.         if (dims[i]<windims[i]) {
  3252.             HERROR(DFE_NOTENOUGH);
  3253.             Hclose(file_id);
  3254.             return FAIL;
  3255.         }
  3256.     }
  3257.     /* allocate buffers */
  3258.     wstart = (int32 *) HDgetspace((uint32) 4 * rank * sizeof(int32));
  3259.     if (wstart == NULL) {
  3260.         HERROR(DFE_NOSPACE);
  3261.         Hclose(file_id);
  3262.         return FAIL;
  3263.     }
  3264.     wdims = wstart + rank;
  3265.     adims = wdims + rank;
  3266.     fdims = adims + rank;
  3267.  
  3268.     /* copy arrays to private workspace (so that they are in row major order)*/
  3269.     for (i=0; i < (int32)rank; i++) {
  3270.         int32 ii = (issdg && isfortran)? rank-i-1 : i;
  3271.  
  3272.         adims[i] = dims[ii];
  3273.         ii = (issdg && FileTranspose)? rank-i-1 : i;
  3274.         wstart[i] = winst[ii]-1; /* translate to 0 origin */
  3275.         wdims[i] = windims[ii];
  3276.         fdims[i] = Readsdg.dimsizes[ii];
  3277.     }
  3278.  
  3279.     convert = (fileNT != platnumsubclass); /* is conversion necessary */
  3280.     transposed = issdg && (isfortran ^ FileTranspose); /* is transposition needed */
  3281.  
  3282.     /*
  3283.      * Note that if the data is transposed we must work on a row by row
  3284.      * basis and cannot collapse dimensions.
  3285.      */
  3286.     if (!transposed) {
  3287.         /* collapse dimensions if contiguous both in the file and in memory */
  3288.         for (i=(int32)rank-1; i>0; i--) { /* stop before most sig dim */
  3289.             if (adims[i] > wdims[i] /* not all of data[] will be filled */
  3290.                 || wstart[i] != 0 /* reading only part of the dataset */
  3291.                 || wdims[i] < fdims[i]) break;
  3292.             wstart[i-1] *= fdims[i];
  3293.             wdims[i-1] *= wdims[i];
  3294.             adims[i-1] *= adims[i];
  3295.             fdims[i-1] *= fdims[i];
  3296.             rank--;
  3297.         }
  3298.     }
  3299.     leastsig = (int32)rank-1;        /* which is least sig dim */
  3300.  
  3301.     /* position at start of data set */
  3302.     aid = Hstartread(file_id, Readsdg.data.tag, Readsdg.data.ref);
  3303.     if (aid == FAIL) {
  3304.         HDfreespace((char *)wstart);
  3305.         Hclose(file_id); return FAIL;
  3306.     }
  3307.  
  3308.     error = 0;
  3309.     if (rank==1 && !convert) {
  3310.         /* all data is contiguous with no conversions */
  3311.         readsize = adims[0] * fileNTsize;
  3312.         if ( (Hseek(aid, wstart[0]*fileNTsize, 0) == FAIL) ||
  3313.             (readsize != Hread(aid, readsize, (uint8 *)data)) ) error=1;
  3314.     } else {
  3315.     /*
  3316.      * The data must be further manipulated.
  3317.      * It may be transposed, may need conversion, may not be contiguous, or
  3318.      * any combination of these.
  3319.      */
  3320.         numelements  = wdims[leastsig];
  3321.         readsize = numelements * fileNTsize;
  3322.  
  3323.         /* allocate 1 row buffers */
  3324.         if (convert) {
  3325.             if ((buf = HDgetspace((uint32) readsize)) == NULL) {
  3326.                 HDfreespace((char *)wstart);
  3327.                 HERROR(DFE_NOSPACE);
  3328.                 Hendaccess(aid); Hclose(file_id);
  3329.                 return FAIL;
  3330.             }
  3331.         } else buf = NULL;
  3332.  
  3333.         if (transposed) {
  3334.             scatterbuf = (uint8 *)HDgetspace((uint32) numelements *
  3335.                             localNTsize);
  3336.             if (scatterbuf == NULL) {
  3337.                 HDfreespace((char *)wstart);
  3338.                 HDfreespace(buf);
  3339.                 HERROR(DFE_NOSPACE);
  3340.                 Hendaccess(aid); Hclose(file_id);
  3341.                 return FAIL;
  3342.             }
  3343.         } else scatterbuf = NULL;
  3344.  
  3345.         offset = (int32 *) HDgetspace((uint32)3 * rank * sizeof(int32));
  3346.         if (offset==NULL) {
  3347.             HDfreespace((char *)wstart);
  3348.             HDfreespace(buf);
  3349.             HDfreespace((char *)scatterbuf);
  3350.             HERROR(DFE_NOSPACE);
  3351.             Hendaccess(aid); Hclose(file_id);
  3352.             return FAIL;
  3353.         }
  3354.         foffset = offset + rank;
  3355.         dimsleft = foffset + rank;
  3356.  
  3357.         /* compute initial position in the data */
  3358.         for (i=leastsig; i>=0; i--)
  3359.             dimsleft[i] = wdims[i];
  3360.  
  3361.         /* compute offsets in the source array */
  3362.         if (transposed) {
  3363.             offset[0] = 1*localNTsize;
  3364.             for (i=0; i<leastsig; i++)
  3365.             offset[i+1] = offset[i] * adims[leastsig - i];
  3366.         } else {
  3367.             offset[leastsig] = 1*localNTsize;
  3368.             for (i = leastsig; i>0; i--)
  3369.             offset[i-1] = offset[i] * adims[i];
  3370.         }
  3371.         datastride = offset[leastsig];
  3372.  
  3373.         /* compute offsets in the file */
  3374.         for (i=leastsig, foffset[i]=1*fileNTsize; i>0; i--)
  3375.             foffset[i-1] = foffset[i] * fdims[i];
  3376.  
  3377.         /*
  3378.          * Compute starting position in file
  3379.          * All file reads are done relative to this starting offset.
  3380.          * Cumulative offset is from most sig to next to least sig dim.
  3381.          */
  3382.         for (i=0, fileoffset=0; i<leastsig; i++)
  3383.             fileoffset = (fileoffset+wstart[i]) * fdims[i+1];
  3384.         fileoffset += wstart[leastsig]; /* adjust for last dim */
  3385.         fileoffset *= fileNTsize; /* convert to bytes */
  3386.  
  3387.         datap = (uint8 *)data;
  3388.         done = 0;
  3389.  
  3390.         /* -- now read in the data */
  3391.         do {
  3392.             /* move to the next data element in the file */
  3393.             if (Hseek(aid, fileoffset, 0) == FAIL) {
  3394.                 error=1;
  3395.                 break;
  3396.             }
  3397.  
  3398.             /* read and convert one contiguous block of data */
  3399.             if (convert) {
  3400.                 if (readsize != Hread(aid, readsize, buf)) {
  3401.                     error=1;
  3402.                     break;
  3403.                 }
  3404.                 DFKconvert(buf, transposed ? (uint8 *)scatterbuf :
  3405.                     (uint8 *)datap, numtype, numelements, DFACC_READ, 0, 0);
  3406.             }
  3407.             else {
  3408.                 if (readsize != Hread(aid, readsize,
  3409.                         transposed ? scatterbuf : datap)) {
  3410.                     error=1;
  3411.                     break;
  3412.                 }
  3413.             }
  3414.             if (transposed) {
  3415.             /* scatter out the elements of one row */
  3416. #ifdef UNICOS
  3417. #pragma ivdep
  3418. #endif
  3419.                 for (dp=datap, sp = scatterbuf, i=0; i<numelements; i++) {
  3420.                     for (j=0; j<localNTsize; j++)
  3421.                         *(dp +j) = *(sp +j);
  3422.                     sp += localNTsize;
  3423.                     dp += datastride;
  3424.                 }
  3425.             }
  3426.  
  3427.             /*
  3428.              * Find starting place of the next row/block.
  3429.              * Note that all moves are relative:
  3430.              *   this preserves the starting offsets of each dimension
  3431.              */
  3432.             for (i=leastsig-1; i>=0; i--) {
  3433.                 if (--dimsleft[i] > 0) {
  3434.                     /* move to next element in the current dimension */
  3435.                     datap += offset[i];
  3436.                     fileoffset += foffset[i];
  3437.                     break;
  3438.                 } else {
  3439.                     dimsleft[i] = wdims[i];
  3440.                     /*
  3441.                      * Note that we are still positioned at the beginning of
  3442.                      * the last element in the current dimension
  3443.                      */
  3444.                     /* move back to the beginning of dimension i */
  3445.                     datap -= offset[i] * (wdims[i]-1);
  3446.                     /* move back to beginning read position of dimension i */
  3447.                     fileoffset -= foffset[i] * (wdims[i]-1);
  3448.                     if (i==0) done = 1;
  3449.                 }
  3450.             }
  3451.         } while (!done && leastsig > 0);
  3452.  
  3453.         HDfreespace(buf);
  3454.         HDfreespace((char *)scatterbuf);
  3455.         HDfreespace((char *)offset);
  3456.     }
  3457.  
  3458.     Hendaccess(aid);
  3459.     HDfreespace((char *)wstart);
  3460.     if (error)  {
  3461.         Hclose(file_id); return FAIL;
  3462.     }
  3463.     else return (Hclose(file_id));
  3464.  
  3465. }
  3466.  
  3467. /*----------------------------------------------------------------------------
  3468.  * Name:    DFSDIputslice
  3469.  * Purpose: Put slice of data to SDG.
  3470.  * Inputs:  windims: array of size rank, containing size of slice
  3471.  *          data: array containing slice
  3472.  *          dims: dimensions of array data
  3473.  *            isfortran: 0 for C, 1 for Fortran
  3474.  * Returns: 0 on success, FAIL on failure with error set
  3475.  * Users:   DFSDputslice
  3476.  * Invokes: DFwrite, HDgetspace, HDfreespace,DFKnumout(if conversion
  3477.         required)
  3478.  * Method:  check dimensions for contiguity, convert types if necessary
  3479.  *          write to file
  3480.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  3481.  *          data may not be contiguous in the array "data".
  3482.  *          DFSDstartslice must have been called first
  3483.  *          If DFKnumout is called, DFSDsetNT may need to have been
  3484.  *        called
  3485.  *        Note, writes must be contiguous - successive calls to putslice
  3486.  *          must write out array consecutively, according to the setting
  3487.  *          of the Fortorder variable - row major if 0, column major if 1
  3488.  *--------------------------------------------------------------------------*/
  3489.  
  3490. #ifdef PROTOTYPE
  3491. int DFSDIputslice(int32 windims[], void *data, int32 dims[], int isfortran)
  3492. #else
  3493. int DFSDIputslice(windims, data, dims, isfortran)
  3494.  
  3495.     int32    windims[];    /* array containing dimensions of the slice */
  3496.     int32    dims[];        /* array containing the dimensions of data[] */
  3497.     void    *data;        /* array of the floating point data to write */
  3498.     int        isfortran;    /* true if called from Fortran */
  3499. #endif /* PROTOTYPE */
  3500. {
  3501.     intn
  3502.         rank;          /* number of dimensions in data[] */
  3503.     int32
  3504.         leastsig,      /* fastest varying subscript in the array */
  3505.         convert,       /* true if machine NT = NT to be written */
  3506.         contiguous,    /* true if there are no gaps in the data to be written */
  3507.         numtype,       /* current number type */
  3508.         platnumsubclass, /* class of this NT for this platform */
  3509.         fileNTsize,    /* size of this NT as it will be in the file */
  3510.         isnative,
  3511.         localNTsize;   /* size of this NT as it occurs in theis machine */
  3512.     int32
  3513.         ret,           /* return code from DFwrite */
  3514.         i, j,          /* temporaries */
  3515.         numelements,   /* number of elements to write out per row */
  3516.         writesize,     /* number of bytes to write out per row */
  3517.         datastride;    /* number of bytes in one row of data[] */
  3518.     uint8
  3519.         *datap,        /* pointer into data[] at */
  3520.                           /* the start of the current row */
  3521.         *buf;          /* buffer containing converted current row */
  3522.     char *FUNC="DFSDIputslice";
  3523.  
  3524.     HEclear();
  3525.  
  3526.     if (!data) {
  3527.         HERROR(DFE_BADPTR); return FAIL;
  3528.     }
  3529.     if (Sfile_id == DF_NOFILE) {
  3530.         HERROR(DFE_BADCALL); return FAIL;
  3531.     }
  3532.  
  3533.     rank = Writesdg.rank;
  3534.  
  3535.     for (i=0; i < (int32)rank; i++) {
  3536.         /* check validity for the dimension ranges */
  3537.         if ((windims[i]<=0) || (windims[i]>Writesdg.dimsizes[i])) {
  3538.             HERROR(DFE_BADDIM); return FAIL;
  3539.         }
  3540.     /* check if space allocated is sufficient */
  3541.     if (dims[i] < windims[i]) {
  3542.         HERROR(DFE_NOTENOUGH); return FAIL;
  3543.     }
  3544.     }
  3545.  
  3546.     /* check to see if the slices fit together */
  3547.     /* Same for Fortran or C    */
  3548.     /* find the first significant dimension */
  3549.     for (i=0; windims[i] == 1 && i<(int32)rank-1; i++)
  3550.         /* empty */;
  3551.         /* check that all 'lesser' dims match */
  3552.     for (j=i+1; j<(int32)rank; j++)
  3553.         if (Writesdg.dimsizes[j] != windims[j]) {
  3554.             HERROR(DFE_BADDIM); return FAIL;
  3555.         }
  3556.         /* update Sddims to reflect new write */
  3557.     Sddims[i] += windims[i];
  3558.     for (;i>0 && Sddims[i] >= Writesdg.dimsizes[i]; i--) {
  3559.         Sddims[i-1] += Sddims[i] / Writesdg.dimsizes[i];
  3560.          /* promote the unit */
  3561.         Sddims[i] %= Writesdg.dimsizes[i];
  3562.     } 
  3563.  
  3564.     leastsig =  (int32)rank-1; /* which is least sig dim */
  3565.     numtype = Writesdg.numbertype;
  3566.     platnumsubclass = DFKgetPNSC(numtype, DF_MT);
  3567.         /* get class of this num type for this platform */
  3568.     fileNTsize = DFKNTsize(numtype);
  3569.     isnative = DFNT_NATIVE;
  3570.     localNTsize = DFKNTsize(numtype | isnative);
  3571.     convert = ( (platnumsubclass != DFNTF_HDFDEFAULT) && /* need conversion? */
  3572.         (!DFKisnativeNT(numtype)) );
  3573.  
  3574.     contiguous = 1;
  3575.     for (i=0; contiguous && i<(int32)rank; i++) {
  3576.     /* check if data at the end of the users array will be contiguous */
  3577.         if (dims[i] > Writesdg.dimsizes[i])
  3578.             contiguous = 0;
  3579.     /* Note: if a winstart[] array is ever added, will also need */
  3580.     /*    to check if data at start of users array will be */
  3581.     /*    contig            */
  3582.     }
  3583.  
  3584.     /*
  3585.      *  2 Factors that determine how we write (in order of importance)
  3586.      *  conversion and contiguous
  3587.      */
  3588.     datap = (uint8 *)data;
  3589.     if (!convert && contiguous) {
  3590.         /* compute total number of elements to write */
  3591.         for (i=0, numelements=1; i<(int32)rank; i++) 
  3592.             numelements *= windims[i];
  3593.         writesize = numelements * fileNTsize;
  3594.         ret = Hwrite(Writesdg.aid, writesize, (uint8 *)data); /* done */
  3595.         if (ret == FAIL)  {
  3596.             Hclose(Sfile_id); return FAIL;
  3597.         } 
  3598.     }
  3599.     else {          /* must step through the data */
  3600.         /* compute number of occurrences of the least sig dim */
  3601.         if (Fortorder) 
  3602.             for (i=(int32)rank-1, j=1; i>0; i--) j *= windims[i];
  3603.         else for (i=0, j=1; i<(int32)rank-1; i++) j *= windims[i];
  3604.         numelements = windims[leastsig];
  3605.         writesize = numelements * fileNTsize;
  3606.         datastride = dims[leastsig] * localNTsize;
  3607.         if (convert) {
  3608.             buf = (uint8 *)HDgetspace((uint32) writesize);
  3609.             if (buf == NULL)  {
  3610.                 Hclose(Sfile_id); return FAIL;
  3611.             }
  3612.             for (i=0; i<j; i++, datap += datastride) {
  3613.                 DFKconvert(datap, buf, numtype,
  3614.                     numelements, DFACC_WRITE, 0, 0);
  3615.                 ret = Hwrite(Writesdg.aid, writesize, buf);  /* done */
  3616.                 if (ret == FAIL) {
  3617.                     HDfreespace(buf);
  3618.                     Hclose(Sfile_id); return FAIL;
  3619.                 }
  3620.             }
  3621.             HDfreespace(buf);
  3622.         }
  3623.         else {        /* !contiguous    */
  3624.             for (i=0; i<j; i++, datap += datastride)
  3625.                 ret = Hwrite(Writesdg.aid, writesize, datap);
  3626.                 if (ret == FAIL) {
  3627.                     Hclose(Sfile_id); return FAIL;
  3628.                 }
  3629.         }
  3630.     }
  3631.  
  3632.     return(ret>=0 ? 0 : -1);
  3633. }
  3634.  
  3635. /* ------------------------------ DFSDgetcal ------------------------------ */
  3636. /*-----------------------------------------------------------------------------
  3637.  * Name:    DFSDgetcal()
  3638.  * Purpose: Get calibration and uncalibrated offsets for data values
  3639.  * Inputs:  pcal:  Pointer to float64 to return calibration value
  3640.  *          pcal_err:  Pointer to float64 to return calibration error value
  3641.  *          pioff:  Pointer to float64 to return uncalibrated offset value 
  3642.  *          pioff_err:  Pointer to float64 to return uncalibrated offset error value
  3643.  *          cal_nt : Pointer to int32 to return what the data's real NT is
  3644.  * Globals: IsCal
  3645.  * Returns: 0 on success, -1 if no values or if error, with DFerror set
  3646.  * Users:   HDF users, utilities, other routines
  3647.  * Invokes: none
  3648.  * Method:  Retrieves values from Readsdg
  3649.  * Remarks: none
  3650.  *---------------------------------------------------------------------------*/
  3651.  
  3652. #if defined __STDC__ || defined PC
  3653. int DFSDgetcal(float64 *pcal, float64 *pcal_err, float64 *pioff, float64 *pioff_err,
  3654.                int32 *cal_nt)
  3655. #else
  3656. int DFSDgetcal(pcal, pcal_err, pioff, pioff_err, cal_nt)
  3657. float64 *pcal, *pcal_err, *pioff, *pioff_err;
  3658. int32   *cal_nt;
  3659. #endif /* __STDC__ || PC */
  3660. {
  3661.  
  3662.     static char *FUNC = "DFSDgetcal";
  3663.  
  3664.     HEclear();
  3665.     
  3666.     if (Newdata<0) {
  3667.         HERROR(DFE_BADCALL);
  3668.         return(FAIL);
  3669.     }
  3670.  
  3671.     if (IsCal) {
  3672.         *pcal      = Readsdg.cal;
  3673.         *pcal_err  = Readsdg.cal_err;
  3674.         *pioff     = Readsdg.ioff;
  3675.         *pioff_err = Readsdg.ioff_err;
  3676.         *cal_nt    = Readsdg.cal_type;
  3677.         return(0);
  3678.     } else {
  3679.         HERROR(DFE_NOVALS);
  3680.         return(FAIL);
  3681.     }
  3682.  
  3683. } /* DFSDgetcal */
  3684.  
  3685.  
  3686. /* ------------------------------ DFSDsetcal ------------------------------ */
  3687. /*-----------------------------------------------------------------------------
  3688.  * Name:    DFSDsetcal()
  3689.  * Purpose: Set calibration and offset (before calibration) of data
  3690.  * Inputs:  cal:  Calibration
  3691.  *          cal_err:  Calibration error
  3692.  *          ioff:  Uncalibrated offset
  3693.  *          ioff_err:  Uncalibrated offset error
  3694.  *          cal_nt:  Numbertype of uncalibrated data
  3695.  * Globals: Ref
  3696.  * Returns: SUCCEED on success, FAIL if no calibration values or if error
  3697.  * Users:   HDF users, utilities, other routines
  3698.  * Invokes: none
  3699.  * Method:  Modify Writesdg, set Ref
  3700.  * Remarks: Automatically cleared after call to DFSDputdata or DFSDadddata
  3701.  *---------------------------------------------------------------------------*/
  3702. #if defined __STDC__ || defined PC
  3703. int DFSDsetcal(float64 cal, float64 cal_err, float64 ioff, float64 ioff_err,
  3704.                int32 cal_nt)
  3705. #else
  3706. int DFSDsetcal(cal, cal_err, ioff, ioff_err, cal_nt)
  3707. float64 cal, cal_err, ioff, ioff_err;
  3708. int32 cal_nt;
  3709. #endif /* __STDC__ || PC */
  3710. {
  3711.     HEclear();
  3712.  
  3713.     Writesdg.cal      = (float64) cal;
  3714.     Writesdg.cal_err  = (float64) cal_err;
  3715.     Writesdg.ioff     = (float64) ioff;
  3716.     Writesdg.ioff_err = (float64) ioff_err;
  3717.     Writesdg.cal_type = (int32)   cal_nt;
  3718.  
  3719.     Ref.cal = 0;
  3720.  
  3721.     return(SUCCEED);
  3722. }
  3723.  
  3724.