home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / hdf / hdf.lha / DFSD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-06  |  91.6 KB  |  2,784 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.10r2
  3. *                July 1, 1990
  4. *
  5. * NCSA HDF Version 3.10r2 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. #ifdef RCSID
  18. static char RcsId[] = "@(#)$Revision: 3.12 $"
  19. #endif
  20. /*
  21. $Header: /pita/work/HDF/dev/RCS/src/dfsd.c,v 3.12 90/09/20 11:04:32 clow beta $
  22. $Log:    dfsd.c,v $
  23.  * Revision 3.12  90/09/20  11:04:32  clow
  24.  * Changed DFSDIgetslice to call DFIseek and DFIread
  25.  * (internal routines without the overhead of checking)
  26.  * in lieu of DFseek and DFread in its loops.
  27.  * This shaves a little off the reading time.
  28.  * 
  29.  * Revision 3.11  90/08/31  12:41:58  clow
  30.  * fixed problems with the getslice routine so that
  31.  * it now reads in only as much as is needed;
  32.  * is smart about contigueous chunks;
  33.  * does the proper seek for all contigueous chunks.
  34.  * 
  35.  * Revision 3.10  90/07/11  09:48:25  clow
  36.  * Modified so that we could do inquiry after doing a getdata.
  37.  * 
  38.  * Revision 3.9  90/07/05  14:06:03  clow
  39.  * Fix bug where transposition is used in getslice
  40.  * 
  41.  * Revision 3.8  90/06/29  17:35:52  clow
  42.  * Fixed bug in DFSDIgetdata and DFSDreadref where the new sdg info is
  43.  * not read.
  44.  * 
  45.  * Revision 3.7  90/06/29  16:49:12  clow
  46.  * Added some spaces before the #pragma line so that the SGI's c compiler
  47.  * will not complain.  Sigh.
  48.  * 
  49.  * Revision 3.6  90/06/28  13:49:12  clow
  50.  * fix bug on DFSDIgetslice and DFSDputslice when the dimensions are collapse
  51.  * 
  52.  * Revision 3.5  90/06/21  10:39:45  clow
  53.  * Fixed bug in Iputslice which calculates the pointer to the data wrongly
  54.  * 
  55.  * Revision 3.4  90/06/13  16:17:38  clow
  56.  * added DFSDreadref that will set the ref of the next SD read in.
  57.  * 
  58.  * Revision 3.3  90/06/07  17:40:02  clow
  59.  * new, faster put/getslice routines done by john walder
  60.  * fixed bug in the getslice routine where the slice is from the
  61.  * wrong coordinates
  62.  * 
  63. */
  64. /*-----------------------------------------------------------------------------
  65.  File:  dfsd.c
  66.  
  67.  Purpose:
  68.     Routines for input and output of scientific data
  69.  
  70.  Invokes:
  71.     df.c dfgroup.c dfkit.c dfi.h df.h dfsd.h
  72.  
  73.  Public functions:
  74.     DFSDgetdims - get rank and dim sizes
  75.     DFSDgetdatastrs - get label, unit, format and coord system of data
  76.     DFSDgetdimstrs - get label, unit and format for a dimension
  77.     DFSDgetdimscale - get scale for a dimension
  78.     DFSDgetmaxmin - get max and min of data
  79.     DFSDgetdata - get data values
  80.     DFSDsetlengths - set lengths of label, unit, format strings on gets
  81.     DFSDsetdims - set rank and dim sizes
  82.     DFSDsetdatastrs - set data label, unit, format and coord system
  83.     DFSDsetdimstrs - set dim labels, units and formats
  84.     DFSDsetdimscale - set scale for a dimension
  85.     DFSDsetmaxmin - get max and min of data
  86.     DFSDputdata - output data, data info, and display info
  87.     DFSDrestart - forget info about last file accessed - restart from beginning
  88.     DFSDnumber - return number of SDGs in file
  89.     DFSDclear - forget all info set
  90.     DFSDlastref - get reference number of last SDG read or written
  91.     DFSDsettype - set output data type, m/c format, number type and array order
  92.     DFSDgetslice - get part of the data, specified as a slice
  93.     DFSDstartslice - set up to write SD
  94.     DFSDputslice - write specified number of data items to file
  95.     DFSDendslice - end of series of writes, write out SDG
  96.  
  97. Lower level functions:
  98.     DFSDgetsdg - read SDG into struct
  99.     DFSDputsdg - read SDG into struct
  100.  
  101. Private functions:
  102.     DFSDIopen - open or reopen file
  103.     DFSDIsdginfo - find next sdg in file
  104.     DFSDIclear - clear sdg data structure of all info
  105.     DFSDIgetdata - read data from file
  106.     DFSDIputdata - write data to file
  107.     DFSDIgetslice - get slice
  108.  
  109. Fortran stub functions:
  110.     dsisdas_ - set data label, unit, format and coord system
  111.     dsisdis_ - set dim labels, units and formats
  112.  
  113.  Remarks: 
  114.     An SDG stores actual data from scietific computations, which are
  115.       subsequently to be converted to images.
  116.     This version assumes that all the values are floating point.
  117.  *---------------------------------------------------------------------------*/
  118.  
  119.  
  120. #include "df.h"
  121. /* #include "dfconvert.h" */
  122.  
  123. #ifdef DF_CAPFNAMES
  124. #   define dsisdas_ DSISDAS
  125. #   define dsisdis_ DSISDIS
  126. #endif /* DF_CAPFNAMES */                                            
  127.  
  128. #define LABEL   0
  129. #define UNIT    1
  130. #define FORMAT  2
  131. #define COORDSYS 3
  132.  
  133. static DFSsdg Readsdg =        /* struct for reading */
  134. { {0, 0}, 0, NULL, NULL, { NULL, NULL, NULL },
  135.   { NULL, NULL, NULL }, NULL, 0.0, 0.0 },
  136.  
  137.     Writesdg =            /* struct for writing */
  138. { {0, 0}, 0, NULL, NULL, { NULL, NULL, NULL },
  139.   { NULL, NULL, NULL }, NULL, 0.0, 0.0 };
  140.  
  141. static  uint16  Writeref=0;    /* ref of next SDG to write to file */
  142. static int Newdata=(-1);    /* Values in Readsdg fresh? */
  143.                 /* -1 : no descriptor read */
  144.                 /* 1 : descriptor read */
  145. static int Nextsdg = 1;        /* Signal if DFSDgetdata should get the */
  146.                 /* next sdg */
  147. static DF *Sdfile=NULL;        /* pointer to file for slice writes */
  148. static int32  *Sddims;        /*dims written so far in slice write */
  149.  
  150. static struct {            /* Indicators of status (s) of info:    */
  151.     int dims;            /* s = -1: there is no info in this category */
  152.     int nt;            /* s = 0: info was set, but not yet written */
  153.     int coordsys;        /* s>0:info was set and written with ref no.s*/
  154.     int luf[3];
  155.     int scales;
  156.     int maxmin;
  157.     int transpose;
  158. } Ref = {  -1, -1, -1, { -1, -1, -1 }, -1, -1 , -1};
  159.     
  160. static int Maxstrlen[4] = { DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN };
  161. static int Ismaxmin = 0;    /* is there a max/min value on read? */
  162. static int FileTranspose = 0;    /* is the data in column major order? */
  163. static int Fortorder = 0;    /* should data be written col major? */
  164.  
  165. static int fileNT=DFNTF_IEEE,    /* default: all IEEE */
  166.            fileNTsize=4,    /* size of IEEE in bytes */
  167.            outNT=DFNTF_IEEE,    /* default output: IEEE */
  168.            outNTsize=4,        /* size of IEEE in bytes */
  169.            userNT=DFNTF_IEEE;    /* default */
  170. static int Readref = 0;
  171.  
  172. static char Lastfile[DF_MAXFNLEN] = "";    /* last file opened */
  173. static uint16 Lastref = 0;
  174.  
  175. /*-----------------------------------------------------------------------------
  176.  * Name:    DFSDgetdims
  177.  * Purpose: Get dimensions of data in next SDG
  178.  * Inputs:  filename: name of HDF file to use
  179.  *          prank: pointer to integer for returning rank (no of dimensions)
  180.  *          sizes: array of integers for returning size of each dimension
  181.  *          maxrank: size of array for returning dimensions
  182.  * Returns: 0 on success, -1 on failure with DFerror set
  183.  * Outputs: rank in prank, size of each dimension in sizes
  184.  *          If rank > maxrank, rank is set, and -1 is returned
  185.  * Users:   HDF users, utilities, other routines
  186.  * Invokes: DFSDIopen, DFIerr, DFclose, DFSDIsdginfo
  187.  * Method:  Opens file, calls DFSDIsdginfo to get SDG, copies rank etc, closes
  188.  *          file, returns
  189.  * Remarks: Always sequences to next SDG in file
  190.  *          User specifies maxrank, and allocates sizes as an array of integers
  191.  *          with dimension maxrank
  192.  *---------------------------------------------------------------------------*/
  193.  
  194. int DFSDgetdims(filename, prank, sizes, maxrank)
  195. char *filename;
  196. int *prank;
  197. int32 sizes[];
  198. int maxrank;
  199. {
  200.     int i;
  201.     DF *dfile;
  202.  
  203.     DFerror = DFE_NOERROR;
  204.     if (!prank) {        /* check if ptr is valid */
  205.         DFerror = DFE_BADPTR;
  206.         return(-1);
  207.     }
  208.  
  209.     dfile = DFSDIopen(filename, DFACC_READ); /* open/reopen file */
  210.     if (dfile == NULL) return(-1);
  211.  
  212.     if (DFSDIsdginfo(dfile)<0)    /* reads next SDG from file */
  213.         return(DFIerr(dfile));    /* on error, close file and return -1 */
  214.  
  215.     *prank = Readsdg.rank;    /* copy rank, dimensions */
  216.     if (maxrank<*prank) {    /* if not all dimensions copied */
  217.         DFerror = DFE_NOTENOUGH;
  218.         return(DFIerr(dfile));
  219.     }
  220.     for (i=0; i<*prank; i++)
  221.         sizes[i] = Readsdg.dimsizes[i];
  222.     Nextsdg = 0;
  223.     return(DFclose(dfile));
  224. }
  225.  
  226. /*-----------------------------------------------------------------------------
  227.  * Name:    DFSDgetdatastrs
  228.  * Purpose: Get information about data: label, units, format
  229.  * Inputs:  label: string to return label in, length Maxstrlen[LABEL]
  230.  *          unit: string to return unit in, length Maxstrlen[UNIT]
  231.  *          format: string to return format in, length Maxstrlen[FORMAT]
  232.  *          coordsys: string to return coord system, length Maxstrlen[COORDSYS]
  233.  * Returns: 0 on success, -1 on failure with DFerror set
  234.  * Outputs: label, unit, format, coord system in the appropriate arguments
  235.  * Users:   HDF users, utilities, other routines
  236.  * Invokes: none
  237.  * Method:  get values from struct Readsdg
  238.  * Remarks: none
  239.  *---------------------------------------------------------------------------*/
  240.  
  241. int DFSDgetdatastrs(label, unit, format, coordsys)
  242. char *label, *unit, *format, *coordsys;
  243. {
  244.     int32 luf;
  245.     char *lufp;
  246.  
  247.     DFerror = DFE_NOERROR;
  248.     
  249.     if (Newdata<0) {
  250.         DFerror = DFE_BADCALL;
  251.         return(-1);
  252.     }
  253.  
  254.     /* copy label, unit, format */
  255.     for (luf=LABEL; luf<=FORMAT; luf++) {
  256.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  257.         if (lufp)
  258.             if (Readsdg.dataluf[luf])
  259.                 DFIstrncpy(lufp, Readsdg.dataluf[luf], Maxstrlen[luf]);
  260.     }
  261.     /* copy coordsys */
  262.     if (coordsys)
  263.         if (Readsdg.coordsys)
  264.             DFIstrncpy(coordsys, Readsdg.coordsys, Maxstrlen[COORDSYS]);
  265.         else coordsys[0] = '\0';
  266.     return(0);
  267. }
  268.  
  269. /*-----------------------------------------------------------------------------
  270.  * Name:    DFSDgetdimstrs
  271.  * Purpose: Get information about a dimension: label, units, format
  272.  * Inputs:  dim: no of dimension to get information about
  273.  *          label: string to return label in, max length Maxstrlen[LABEL]
  274.  *          unit: string to return unit in, max length Maxstrlen[UNIT]
  275.  *          format: string to return format in, max length Maxstrlen[FORMAT]
  276.  * Returns: 0 on success, -1 on failure with DFerror set
  277.  * Outputs: label, unit, format in the appropriate arguments
  278.  *          NULL string if no value for the arguments
  279.  * Users:   HDF users, utilities, other routines
  280.  * Invokes: none
  281.  * Method:  get values from struct Readsdg
  282.  * Remarks: none
  283.  *---------------------------------------------------------------------------*/
  284.  
  285. int DFSDgetdimstrs(dim, label, unit, format)
  286. int dim;
  287. char *label, *unit, *format;
  288. {
  289.     int luf, rdim;
  290.     char *lufp;
  291.  
  292.     DFerror = DFE_NOERROR;
  293.     
  294.     if (Newdata<0) {
  295.         DFerror = DFE_BADCALL;
  296.         return(-1);
  297.     }
  298.  
  299.     rdim = dim-1;        /* translate dim to zero origin */
  300.     if ((rdim>=Readsdg.rank) || (rdim<0)) {
  301.         DFerror = DFE_BADDIM;
  302.         return(-1);
  303.     }
  304.  
  305.     /* copy labels etc */
  306.     for (luf=LABEL; luf<=FORMAT; luf++) {
  307.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  308.         if (lufp) {
  309.             if (!Readsdg.dimluf) { /* no labels etc */
  310.                 *lufp = '\0';
  311.                 continue;
  312.             }
  313.             if (Readsdg.dimluf[luf])
  314.                 DFIstrncpy(lufp, Readsdg.dimluf[luf][rdim], Maxstrlen[luf]);
  315.         }
  316.     }
  317.     return(0);
  318. }
  319.                 
  320. /*-----------------------------------------------------------------------------
  321.  * Name:    DFSDgetdatalen()
  322.  * Purpose: Get actual length of label, unit, format, coordsys strings
  323.  *          Called from FORTRAN
  324.  * Inputs:  llabel, lunit, lformat, lcoordsys - for returning lengths
  325.  * Globals: Readsdg
  326.  * Returns: 0 on success, -1 on error with DFerror set
  327.  * Users:   HDF users, utilities, other routines
  328.  * Invokes: none
  329.  * Method:  get lengths from Readsdg
  330.  *---------------------------------------------------------------------------*/
  331.  
  332. int DFSDgetdatalen(llabel, lunit, lformat, lcoordsys)
  333. int *llabel, *lunit, *lformat, *lcoordsys;
  334. {
  335.  
  336.     DFerror = DFE_NOERROR;
  337.  
  338.     if (Newdata<0) {
  339.         DFerror = DFE_BADCALL;
  340.         return(-1);
  341.     }
  342.     *llabel =  Readsdg.dataluf[LABEL] ? strlen(Readsdg.dataluf[LABEL]) : 0;
  343.     *lunit =  Readsdg.dataluf[UNIT] ? strlen(Readsdg.dataluf[UNIT]) : 0;
  344.     *lformat =  Readsdg.dataluf[FORMAT] ? strlen(Readsdg.dataluf[FORMAT]) : 0;
  345.     *lcoordsys =  Readsdg.coordsys ? strlen(Readsdg.coordsys) : 0;
  346.     return(0);
  347. }
  348.     
  349.  
  350. /*-----------------------------------------------------------------------------
  351.  * Name:    DFSDgetdimlen()
  352.  * Purpose: Get actual length of label, unit, format strings
  353.  *          Called from FORTRAN
  354.  * Inputs:  dim. llabel, lunit, lformat - for returning lengths
  355.  * Globals: Readsdg
  356.  * Returns: 0 on success, -1 on error with DFerror set
  357.  * Users:   HDF users, utilities, other routines
  358.  * Invokes: none
  359.  * Method:  get lengths from Readsdg
  360.  *---------------------------------------------------------------------------*/
  361.  
  362. int DFSDgetdimlen(dim, llabel, lunit, lformat)
  363. int dim;
  364. int *llabel, *lunit, *lformat;
  365. {
  366.  
  367.     DFerror = DFE_NOERROR;
  368.  
  369.     if (Newdata<0) {
  370.         DFerror = DFE_BADCALL;
  371.         return(-1);
  372.     }
  373.     if (dim>Readsdg.rank) {
  374.         DFerror = DFE_BADDIM;
  375.         return(-1);
  376.     }
  377.     *llabel =  Readsdg.dimluf[dim-1][LABEL] ?
  378.     strlen(Readsdg.dimluf[dim-1][LABEL]) : 0;
  379.     *lunit =  Readsdg.dimluf[dim-1][UNIT] ?
  380.     strlen(Readsdg.dimluf[dim-1][UNIT]) : 0;
  381.     *lformat =  Readsdg.dimluf[dim-1][FORMAT] ?
  382.     strlen(Readsdg.dimluf[dim-1][FORMAT]) : 0;
  383.     return(0);
  384. }
  385.  
  386. /*-----------------------------------------------------------------------------
  387.  * Name:    DFSDgetdimscale
  388.  * Purpose: Get dimension scale
  389.  * Inputs:  dim: no of dimension to get scale for
  390.  *          size: size of scale array
  391.  *          scale: array to return scale in
  392.  * Returns: 0 on success, -1 on failure with DFerror set
  393.  * Outputs: scale if present, else -1
  394.  * Users:   HDF users, utilities, other routines
  395.  * Invokes: none
  396.  * Method:  get values from struct Readsdg
  397.  * Remarks: none
  398.  *---------------------------------------------------------------------------*/
  399.  
  400. int DFSDgetdimscale(dim, maxsize, scale)
  401. int dim;
  402. int32 maxsize;
  403. float32 scale[];
  404. {
  405.     int32 i;
  406.     int rdim;
  407.  
  408.     DFerror = DFE_NOERROR;
  409.     
  410.     if (Newdata<0) {
  411.         DFerror = DFE_BADCALL;
  412.         return(-1);
  413.     }
  414.  
  415.     rdim = dim-1;        /* translate dim to zero origin */
  416.     if ((rdim>=Readsdg.rank) || (rdim<0)) {
  417.         DFerror = DFE_BADDIM;
  418.         return(-1);
  419.     }
  420.  
  421.     if (maxsize < Readsdg.dimsizes[rdim]) {
  422.         DFerror = DFE_NOSPACE;
  423.         return(-1);
  424.     }
  425.  
  426.     if (!scale) {
  427.         DFerror = DFE_BADPTR;
  428.         return(-1);
  429.     }
  430.  
  431.     if (!Readsdg.dimscales || !Readsdg.dimscales[rdim]) { /* no scale */
  432.         DFerror = DFE_NOVALS;
  433.         return(-1);
  434.     }
  435.  
  436.     for (i=0; i<Readsdg.dimsizes[rdim]; i++) /* copy scale */
  437.         scale[i] = Readsdg.dimscales[rdim][i];
  438.  
  439.     return(0);
  440. }
  441.  
  442. /*-----------------------------------------------------------------------------
  443.  * Name:    DFSDgetmaxmin()
  444.  * Purpose: Get maximum and minimum data values
  445.  * Inputs:  pmax: pointer to float32 to return maximum value in
  446.  *          pmin: pointer to float32 to return minimum value in
  447.  * Globals: Ismaxmin
  448.  * Returns: 0 on success, -1 if no maxmin values or if error, with DFerror set
  449.  * Users:   HDF users, utilities, other routines
  450.  * Invokes: none
  451.  * Method:  Retrieves values from Readsdg
  452.  * Remarks: none
  453.  *---------------------------------------------------------------------------*/
  454.  
  455. int DFSDgetmaxmin(pmax, pmin)
  456. float32 *pmax, *pmin;
  457. {
  458.  
  459.     DFerror = DFE_NOERROR;
  460.     
  461.     if (Newdata<0) {
  462.         DFerror = DFE_BADCALL;
  463.         return(-1);
  464.     }
  465.  
  466.     if (Ismaxmin) {
  467.         *pmax = Readsdg.max_data;
  468.         *pmin = Readsdg.min_data;
  469.         return(0);
  470.     } else {
  471.         DFerror = DFE_NOVALS;
  472.         return(-1);
  473.     }
  474. }
  475.  
  476. /*-----------------------------------------------------------------------------
  477.  * Name:    DFSDgetdata
  478.  * Purpose: Get data from SDG.  Will sequence to next SDG if DFSDgetdims not
  479.  *          called.
  480.  * Inputs:  filename: name of HDF file to use
  481.  *          rank: no of dimensions of array "data"
  482.  *          maxsizes: actual dimensions of array "data"
  483.  *          data: data for returning scientific data
  484.  * Returns: 0 on success, -1 on failure with DFerror set
  485.  * Outputs: actual scientific data in array
  486.  * Users:   HDF users, utilities, other routines
  487.  * Invokes: DFSDIgetdata
  488.  * Method:  call DFSDIgetdata
  489.  * Remarks: maxsizes may be larger than actual size.  In that event, the actual
  490.  *          data may not be contiguous in the array "data"
  491.  *          User sets maxsizes before call.
  492.  *          It is not necessary to call DFSDgetdata first if the dimensions
  493.  *          are correct
  494.  *---------------------------------------------------------------------------*/
  495.  
  496. int DFSDgetdata(filename, rank, maxsizes, data)
  497. char *filename;
  498. int rank;
  499. int32 maxsizes[];
  500. float32 data[];
  501. {
  502.     return(DFSDIgetdata(filename, rank, maxsizes, data, 0));    /* 0 == C */
  503. }
  504.                 
  505.  
  506. /*-----------------------------------------------------------------------------
  507.  * Name:    DFSDsetlengths()
  508.  * Purpose: Set maximum length for label, unit, format, coordsys strings
  509.  * Inputs:  maxlen_label, maxlen_format, maxlen_unit, maxlen_coordsys:
  510.  *              maximum length of each string.
  511.  * Globals: Maxstrlen
  512.  * Returns: 0 on success, -1 on error with DFerror set
  513.  * Users:   HDF users, utilities, other routines
  514.  * Invokes: none
  515.  * Method:  Stores values in global Maxstrlen
  516.  * Remarks: The get routines assume the array passed in by user is of this len
  517.  *          If this routine is not called, the lengths default to DFS_MAXLEN
  518.  *          The length includes the string terminator NULL byte
  519.  *---------------------------------------------------------------------------*/
  520.  
  521. int DFSDsetlengths(maxlen_label, maxlen_unit, maxlen_format, maxlen_coordsys)
  522. int maxlen_label, maxlen_unit, maxlen_format, maxlen_coordsys;
  523. {
  524.  
  525.     if (maxlen_label>0) Maxstrlen[LABEL] = maxlen_label;
  526.     if (maxlen_unit>0) Maxstrlen[UNIT] = maxlen_unit;
  527.     if (maxlen_format>0) Maxstrlen[FORMAT] = maxlen_format;
  528.     if (maxlen_coordsys>0) Maxstrlen[COORDSYS] = maxlen_coordsys;
  529.     return(0);
  530. }
  531.     
  532.  
  533. /*-----------------------------------------------------------------------------
  534.  * Name:    DFSDsetdims()
  535.  * Purpose: Set rank and sizes for subsequent SDGs
  536.  * Inputs:  rank: rank of array that holds the raw data
  537.  *          dimsizes: sizes of all of the dimensions
  538.  * Globals: Writesdg, Ref
  539.  * Returns: 0 on success, -1 on error with DFerror set
  540.  * Users:   HDF users, utilities, other routines
  541.  * Invokes: DFSDclear
  542.  * Method:  Stores values in global structure Writesdg
  543.  * Remarks: If dimensions change, all previous "set"s are cleared
  544.  *          This routine must be called before DFSDsetdimstrs and
  545.  *          DFSDsetdimscales.  It need not be called if these routines are
  546.  *          not called, and the correct dimensions are supplied to DFSDputdata
  547.  *          or DFSDadddata
  548.  *---------------------------------------------------------------------------*/
  549.  
  550. int DFSDsetdims(rank, dimsizes)
  551. int16 rank;
  552. int32  dimsizes[];
  553. {
  554.     int i;
  555.  
  556.     DFerror = DFE_NOERROR;
  557.  
  558.     if (Sdfile!=NULL) {
  559.         DFerror = DFE_BADCALL;
  560.         return(-1);
  561.     }
  562.  
  563.     if (Writesdg.rank == rank)    /* check if dimensions same */
  564.         if (Writesdg.dimsizes) {
  565.             for (i=0; i<rank; i++)
  566.                 if (Writesdg.dimsizes[i] != dimsizes[i]) break;
  567.             if (i == rank) return(0); /* Dimensions same as before */
  568.         }   
  569.     
  570.     /* forget all attributes set previously */
  571.     if (DFSDIclear(&Writesdg)<0) return(-1);
  572.  
  573.     /* allocate dimensions */
  574.     Writesdg.dimsizes = (int32 *) DFIgetspace((unsigned)(rank*sizeof(int32)));
  575.     if (Writesdg.dimsizes==NULL) return(-1);
  576.  
  577.     /* copy dimensions */
  578.     Writesdg.rank = rank;
  579.     for (i=0; i<rank; i++)
  580.         Writesdg.dimsizes[i] = dimsizes[i];
  581.  
  582.     /* Note dimensions modified */
  583.     Ref.dims = 0;
  584.     return(0);
  585. }
  586.  
  587. /*-----------------------------------------------------------------------------
  588.  * Name:    DFSDsetdatastrs()
  589.  * Purpose: Set label, unit and format for displaying subsequent SDGs
  590.  * Inputs:  label: label to be used to describe data
  591.  *          unit: unit corresponding to data values
  592.  *          format: format to be used in displaying data values
  593.  *          coordsys: type of coordinate system
  594.  * Globals: Writesdg, Ref
  595.  * Returns: 0 on success, -1 on failure with DFerror set
  596.  * Users:   HDF users, utilities, other routines
  597.  * Invokes: none
  598.  * Method:  Stores values in global structure Writesdg
  599.  * Remarks: should we validate coordsys? proposed strings: "cartesian",
  600.  *          "polar" (="spherical") and "cylindrical".  Do "spherical" and
  601.  *          "cylindrical" make sense for 2D?
  602.  *---------------------------------------------------------------------------*/
  603.  
  604. int DFSDsetdatastrs(label, unit, format, coordsys)
  605. char *label, *unit, *format, *coordsys;
  606. {
  607.     int luf;            /* takes values LABEL, UNIT, FORMAT */
  608.                 /* in succession */
  609.     char *lufp;            /* points to label, unit, format */
  610.                 /* in succession */
  611.     DFerror = DFE_NOERROR;
  612.  
  613.     for (luf=LABEL; luf<=FORMAT; luf++) {
  614.     /* set lufp to point to label etc. as apppropriate */
  615.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  616.  
  617.     /* free space if allocated */
  618.         Writesdg.dataluf[luf] = DFIfreespace(Writesdg.dataluf[luf]);
  619.  
  620.     /* copy string */
  621.         if (lufp) {
  622.             Writesdg.dataluf[luf] = DFIgetspace((unsigned) strlen(lufp)+1);
  623.             if (Writesdg.dataluf[luf]==NULL) return(-1);
  624.             strcpy(Writesdg.dataluf[luf], lufp);
  625.         }
  626.     }
  627.  
  628.     Writesdg.coordsys = DFIfreespace(Writesdg.coordsys);
  629.  
  630.     if (coordsys) {
  631.         Writesdg.coordsys = DFIgetspace((unsigned) strlen(coordsys)+1);
  632.         if (Writesdg.coordsys==NULL) return(-1);
  633.         strcpy(Writesdg.coordsys, coordsys);
  634.     }
  635.  
  636.     /* indicate that label, unit, format and coordsys info modified */
  637.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = Ref.coordsys = 0;
  638.  
  639.     return(0);
  640. }
  641.  
  642. /*-----------------------------------------------------------------------------
  643.  * Name:    DFSDsetdimstrs()
  644.  * Purpose: For the given dimension, set label, unit, format
  645.  *          This routine needs to be called once for each dimension whose 
  646.  *          values the user wants to set.
  647.  * Inputs:  dim: the dimension that this info applies to
  648.  *          label: label to be used to describe this dimension
  649.  *          unit: units for dimension
  650.  *          format: format to be used in displaying
  651.  * Globals: Writesdg, Ref
  652.  * Returns: 0 on success, -1 on failure with DFerror set
  653.  * Users:   HDF users, utilities, other routines
  654.  * Invokes: none
  655.  * Method:  Stores values in global structure Writesdg
  656.  *---------------------------------------------------------------------------*/
  657.  
  658. int DFSDsetdimstrs(dim, label, unit, format)
  659. int dim;
  660. char *label, *unit, *format;
  661. {
  662.  
  663.     int i, rdim;
  664.     int luf;            /* takes values LABEL, UNIT, FORMAT */
  665.                 /* in succession */
  666.     char *lufp;            /* points to label, unit, format */
  667.                 /* in succession */
  668.     DFerror = DFE_NOERROR;
  669.  
  670.     rdim = dim-1;        /* translate from 1 to 0 origin */
  671.  
  672.     if ((rdim>=Writesdg.rank) || (rdim<0)) {
  673.         DFerror = DFE_BADDIM;
  674.         return(-1);
  675.     }
  676.  
  677.     for (luf=LABEL; luf<=FORMAT; luf++) {
  678.     /* set lufp to point to label etc. as apppropriate */
  679.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  680.  
  681.     /* allocate space if necessary */
  682.         if (!Writesdg.dimluf[luf]) {
  683.             Writesdg.dimluf[luf] =
  684.                 (char **) DFIgetspace((unsigned) Writesdg.rank * sizeof(char *));
  685.             if (Writesdg.dimluf[luf]==NULL) return(-1);
  686.             for (i=0; i<Writesdg.rank; i++) /* set allocated pointers to NULL*/
  687.                 Writesdg.dimluf[luf][i] = NULL;
  688.         }
  689.  
  690.     /* free string space if allocated */
  691.         Writesdg.dimluf[luf][rdim] = DFIfreespace(Writesdg.dimluf[luf][rdim]);
  692.  
  693.     /* copy string */
  694.         if (lufp) {
  695.             Writesdg.dimluf[luf][rdim] = DFIgetspace((unsigned) strlen(lufp)+1);
  696.             if (Writesdg.dimluf[luf][rdim]==NULL) return(-1);
  697.             strcpy(Writesdg.dimluf[luf][rdim], lufp);
  698.         }
  699.     }
  700.     /* Indicate that this info has not been written to file */
  701.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = 0;
  702.  
  703.     return(0);
  704. }
  705.  
  706. /*-----------------------------------------------------------------------------
  707.  * Name:    DFSDsetdimscale()
  708.  * Purpose: For the given dimension, set scale values
  709.  *          This routine needs to be called once for each dimension whose 
  710.  *          values the user wants to set.
  711.  * Inputs:  dim: the dimension that this info applies to
  712.  *          dimsize: number of points in the scale
  713.  *          scale: array of numbers that will make up the scale
  714.  * Globals: Writesdg, Ref
  715.  * Returns: 0 on success, -1 on failure with DFerror set
  716.  * Users:   HDF users, utilities, other routines
  717.  * Invokes: none
  718.  * Method:  Stores values in global structure Writesdg
  719.  *---------------------------------------------------------------------------*/
  720.  
  721. int DFSDsetdimscale(dim, dimsize, scale)
  722. int dim;
  723. int32   dimsize;
  724. float32 scale[];
  725. {
  726.  
  727.     int i, rdim;
  728.     DFerror = DFE_NOERROR;
  729.  
  730.     rdim = dim-1;        /* translate from 1 to 0 origin */
  731.  
  732.     if (!Writesdg.dimsizes) {
  733.         DFerror = DFE_BADCALL;
  734.         return(-1);
  735.     }
  736.     if ((rdim>=Writesdg.rank) || (rdim<0) /* check dimensions */
  737.     || (dimsize!=Writesdg.dimsizes[rdim])) {
  738.         DFerror = DFE_BADDIM;
  739.         return(-1);
  740.     }
  741.  
  742.     if (!scale) {        /* No scale for this dimension */
  743.         if (Writesdg.dimscales)
  744.             Writesdg.dimscales[rdim] =
  745.         (float32 *) DFIfreespace((char*) Writesdg.dimscales[rdim]);
  746.         Ref.scales = 0;
  747.         return(0);
  748.     }
  749.         
  750.     /* allocate space for dimscales if necessary */
  751.     if (!Writesdg.dimscales) {
  752.         Writesdg.dimscales =
  753.         (float32 **) DFIgetspace((unsigned)Writesdg.rank * sizeof(float32 *));
  754.         if (Writesdg.dimscales==NULL) return(-1);
  755.         for (i=0; i<Writesdg.rank; i++) /* set allocated pointers to NULL */
  756.             Writesdg.dimscales[i] = NULL;
  757.     }
  758.  
  759.     if (!Writesdg.dimscales[rdim]) {
  760.     /* allocate dimension scale space if necessary */
  761.         Writesdg.dimscales[rdim] =
  762.         (float32 *) DFIgetspace((unsigned) dimsize*sizeof(float32));
  763.         if (Writesdg.dimscales[rdim]==NULL) return(-1);
  764.     }
  765.  
  766.     for (i=0; i<dimsize; i++)    /* copy scale */
  767.         Writesdg.dimscales[rdim][i] = scale[i];
  768.  
  769.     /* Indicate scales modified */
  770.     Ref.scales = 0;
  771.  
  772.     return(0);
  773. }
  774.  
  775. /*-----------------------------------------------------------------------------
  776.  * Name:    DFSDsetmaxmin()
  777.  * Purpose: Set maximum and minimum data values
  778.  * Inputs:  maxi: maximum value
  779.  *          mini: minimum value
  780.  * Globals: Ref
  781.  * Returns: 0 on success, -1 if no maxmin values or if error, with DFerror set
  782.  * Users:   HDF users, utilities, other routines
  783.  * Invokes: none
  784.  * Method:  Modify Writesdg, set Ref
  785.  * Remarks: Automatically cleared after call to DFSDputdata or DFSDadddata
  786.  *---------------------------------------------------------------------------*/
  787.  
  788. int DFSDsetmaxmin(maxi, mini)
  789. float32 maxi, mini;
  790. {
  791.  
  792.     DFerror = DFE_NOERROR;
  793.     
  794.     Writesdg.max_data = maxi;
  795.     Writesdg.min_data = mini;
  796.     Ref.maxmin = 0;
  797.  
  798.     return(0);
  799. }
  800.  
  801.  
  802. /*-----------------------------------------------------------------------------
  803.  * Name:    DFSDputdata
  804.  * Purpose: Calls DFSDIputdata to write data and SDG to file
  805.  * Inputs:  filename: name of HDF file to use
  806.  *          rank: rank of data array
  807.  *          dimsizes: sizes of the dimensions of data array
  808.  *          data: array that holds data
  809.  * Globals: Writeref
  810.  * Returns: 0 on success, -1 on failure with DFerror set
  811.  * Users:   HDF users, utilities, other routines
  812.  * Invokes: DFSDIputdata
  813.  * Method:  Invoke DFSDIputdata
  814.  *---------------------------------------------------------------------------*/
  815.  
  816. int DFSDputdata(filename, rank, dimsizes, data)
  817. char *filename;
  818. int16 rank;
  819. int32 dimsizes[];
  820. float32 *data;
  821. {
  822.  
  823.     /* 0, 0 specify create mode, C style array (row major) */
  824.     return(DFSDIputdata(filename, rank, dimsizes, data, 0, 0));
  825. }
  826.  
  827. /*-----------------------------------------------------------------------------
  828.  * Name:    DFSDadddata
  829.  * Purpose: Calls DFSDIputdata to append data and SDG to file
  830.  * Inputs:  filename: name of HDF file to use
  831.  *          rank: rank of data array
  832.  *          dimsizes: sizes of the dimensions of data array
  833.  *          data: array that holds data
  834.  * Globals: Writeref
  835.  * Returns: 0 on success, -1 on failure with DFerror set
  836.  * Users:   HDF users, utilities, other routines
  837.  * Invokes: DFSDIputdata
  838.  * Method:  Invoke DFSDIputdata
  839.  *---------------------------------------------------------------------------*/
  840.  
  841. int DFSDadddata(filename, rank, dimsizes, data)
  842. char *filename;
  843. int16 rank;
  844. int32 dimsizes[];
  845. float32 *data;
  846. {
  847.  
  848.     /* 1, 0 specifies append mode, C style array (row major) */
  849.     return(DFSDIputdata(filename, rank, dimsizes, data, 1, 0));
  850. }
  851.  
  852.  
  853. /*-----------------------------------------------------------------------------
  854.  * Name:    DFSDrestart
  855.  * Purpose: Do not remember info about file - get again from first data set
  856.  * Inputs:  none
  857.  * Returns: 0 on success
  858.  * Users:   HDF programmers
  859.  * Remarks: Just reset Lastfile to NULL
  860.  *          Subsequent gets will starts from first image
  861.  *          Next put will write all "set" info to file
  862.  *---------------------------------------------------------------------------*/
  863.  
  864. int DFSDrestart()
  865. {
  866.     Lastfile[0] = '\0';
  867.     Readref = 0;
  868.     return(0);
  869. }
  870.     
  871.  
  872. /*-----------------------------------------------------------------------------
  873.  * Name:    DFSDnumber
  874.  * Purpose: Return number of SDGs in file
  875.  * Inputs:  filename - name of HDF file
  876.  * Globals: none
  877.  * Returns: number of SDGs on success, -1 on error with DFerror set
  878.  * Users:   HDF users, utilities, other routines
  879.  * Invokes: DFSDIopen, DFclose, DFnumber
  880.  * Method:  open file, invoke DFnumber, close file
  881.  * Remarks: none
  882.  *---------------------------------------------------------------------------*/
  883.  
  884. int DFSDnumber(filename)
  885. char *filename;
  886. {
  887.     DF *dfile;
  888.     int nsdgs=0;
  889.  
  890.     DFerror = DFE_NOERROR;
  891.  
  892.     /* should use reopen if same file as last time - more efficient */
  893.     dfile = DFSDIopen(filename, DFACC_READ);
  894.     if (dfile==NULL) return(-1);
  895.  
  896.     nsdgs = DFnumber(dfile, DFTAG_SDG);       /* count number of SDGs */
  897.     if (DFclose(dfile)<0) return(-1);
  898.     return(nsdgs);
  899. }
  900.  
  901.  
  902. /*-----------------------------------------------------------------------------
  903.  * Name:    DFSDclear
  904.  * Purpose: Clear all "set" values
  905.  * Inputs:  none
  906.  * Globals: Writesdg, Ref
  907.  * Returns: 0 on success, -1 on error with DFerror set
  908.  * Users:   HDF users, utilities, other routines
  909.  * Invokes: DFSDIclear
  910.  * Method:  Invoke DFSDIclear
  911.  * Remarks: none
  912.  *---------------------------------------------------------------------------*/
  913.  
  914. int DFSDclear()
  915. {
  916.     return(DFSDIclear(&Writesdg));
  917. }
  918.  
  919.  
  920. /*-----------------------------------------------------------------------------
  921.  * Name:    DFSDlastref
  922.  * Purpose: Return last ref written or read
  923.  * Inputs:  none
  924.  * Globals: Lastref
  925.  * Returns: ref on success, -1 on error with DFerror set
  926.  * Users:   HDF users, utilities, other routines
  927.  * Invokes: none
  928.  * Method:  return Lastref
  929.  * Remarks: none
  930.  *---------------------------------------------------------------------------*/
  931.  
  932. int DFSDlastref()
  933. {
  934.     return((int) Lastref);
  935. }
  936.  
  937. /*-----------------------------------------------------------------------------
  938.  * Name:    DFR8readref
  939.  * Purpose: Set ref of image to get next
  940.  * Inputs:  filename: file to which this applies
  941.  *          ref: reference number of next get
  942.  * Returns: 0 on success, -1 on failure
  943.  * Users:   HDF programmers, other routines and utilities
  944.  * Invokes: DFR8Iopen, DFIfind
  945.  * Remarks: checks if image with this ref exists
  946.  *---------------------------------------------------------------------------*/
  947.  
  948.     int
  949. DFSDreadref(filename, ref)
  950.     char *filename;
  951.     uint16 ref;
  952. {
  953.     DF *dfile;
  954.     int cdd;
  955.     DFdle *dlep;
  956.  
  957.     DFerror = DFE_NOERROR;
  958.     dfile = DFSDIopen(filename, DFACC_READ);
  959.     if (!dfile) return (-1);
  960.     if (DFIfind(dfile, DFTAG_SDG, ref,1,0,0, &dlep, &cdd) < 0)
  961.     return (DFIerr(dfile));
  962.     Readref = ref;
  963.     Newdata = -1;
  964.     return DFclose(dfile);
  965. }
  966.  
  967. /*-----------------------------------------------------------------------------
  968.  * Name:    DFSDgetslice
  969.  * Purpose: Get slice of data from SDG.  Will sequence to next SDG if
  970.  *          DFSDgetdims, DFSDgetdata or DFSDgetslice not called earlier.
  971.  * Inputs:  filename: name of HDF file to use
  972.  *          winst: array of size = rank of data, containing start of slice
  973.  *          windims: array of size rank, containing end of slice
  974.  *          data: array for returning slice
  975.  *          dims: dimensions of array data
  976.  * Returns: 0 on success, -1 on failure with DFerror set
  977.  * Outputs: slice of data in data
  978.  * Users:   DFSDIgetdata
  979.  * Invokes: DFSDIgetslice
  980.  * Method:  call DFSDIgetslice
  981.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  982.  *          data may not be contiguous in the array "data".
  983.  *          User sets dims before call.
  984.  *---------------------------------------------------------------------------*/
  985.  
  986. int DFSDgetslice(filename, winst, windims, data, dims)
  987. char *filename;
  988. int32 winst[], windims[];
  989. int32 dims[];
  990. float32 data[];
  991. {
  992.     return(DFSDIgetslice(filename, winst, windims, data, dims, 0));
  993. }
  994.  
  995. /*-----------------------------------------------------------------------------
  996.  * Name:    DFSDstartslice
  997.  * Purpose: Set up to write slice of data to SDG.
  998.  * Inputs:  filename: name of HDF file to write to
  999.  * Returns: 0 on success, -1 on failure with DFerror set
  1000.  * Users:   DFSDIputdata
  1001.  * Invokes: DFSDIopen, DFnewref, DFaccess
  1002.  * Method:  call DFSDIputslice
  1003.  * Remarks: DFSDsetdims must have been called first
  1004.  *          No call which needs a file open may be made after this
  1005.  *          till DFSDendslice is called
  1006.  *---------------------------------------------------------------------------*/
  1007.  
  1008. int DFSDstartslice(filename)
  1009. char *filename;
  1010. {
  1011.     int i;
  1012.  
  1013.     DFerror = DFE_NOERROR;
  1014.  
  1015.     if (!Writesdg.rank) {    /* dimensions not set */
  1016.         DFerror = DFE_BADDIM;
  1017.         return(-1);
  1018.     }
  1019.  
  1020.     Sdfile = DFSDIopen(filename, DFACC_WRITE);
  1021.     if (Sdfile == NULL) return(-1);
  1022.  
  1023.     if (!Writeref) Writeref = DFnewref(Sdfile);
  1024.     if (!Writeref) return(-1);
  1025.  
  1026.     Writesdg.data.tag = DFTAG_SD;
  1027.     Writesdg.data.ref = Writeref;
  1028.  
  1029.         /* set up to write image */
  1030.     if (DFaccess(Sdfile, DFTAG_SD, Writeref, "w")<0)
  1031.             return(DFIerr(Sdfile));
  1032.  
  1033.     /* allocate array for keeping track of dims written */
  1034.     Sddims = (int32 *) DFIgetspace((unsigned) Writesdg.rank * sizeof(int32));
  1035.     if (Sddims==NULL) return(DFIerr(Sdfile));
  1036.     
  1037.     for (i=0; i<Writesdg.rank; i++)
  1038.         Sddims[i] = 0;        /* nothing written so far */
  1039.  
  1040.     return(0);
  1041. }
  1042.  
  1043.  
  1044. /*-----------------------------------------------------------------------------
  1045.  * Name:    DFSDputslice
  1046.  * Purpose: Put slice of data to SDG.
  1047.  * Inputs:  winend: array of size rank, containing end of slice
  1048.  *          data: array containing slice
  1049.  *          dims: dimensions of array data
  1050.  * Returns: 0 on success, -1 on failure with DFerror set
  1051.  * Users:   DFSDIputdata
  1052.  * Invokes: DFSDIputslice
  1053.  * Method:  call DFSDIputslice
  1054.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  1055.  *          data may not be contiguous in the array "data".
  1056.  *          DFSDstartslice must have been called first
  1057.  *---------------------------------------------------------------------------*/
  1058.  
  1059. int DFSDputslice(winend, data, dims)
  1060. int32 winend[];
  1061. int32 dims[];
  1062. float32 data[];
  1063. {
  1064.  
  1065.     return(DFSDIputslice(winend, data, dims, 0));
  1066. }
  1067.  
  1068.  
  1069. /*-----------------------------------------------------------------------------
  1070.  * Name:    DFSDendslice
  1071.  * Purpose: Write of data to SDG completed, write SDG and close file
  1072.  * Inputs:  none
  1073.  * Returns: 0 on success, -1 on failure with DFerror set
  1074.  * Users:   DFSDIputdata
  1075.  * Invokes: DFSDputsdg, DFclose, DFIerr
  1076.  * Method:  call DFSDputsdg, close Sdfile
  1077.  * Remarks: checks that slice writes were completed.
  1078.  *---------------------------------------------------------------------------*/
  1079.  
  1080. int DFSDendslice()
  1081. {
  1082.     int i, ret;
  1083.  
  1084.     DFerror = DFE_NOERROR;
  1085.  
  1086.     if (!Sdfile) {
  1087.         DFerror = DFE_BADCALL;
  1088.         return(-1);
  1089.     }
  1090.  
  1091.     /* check if slice writes complete */
  1092.     for (i=0; i<Writesdg.rank; i++) {
  1093.         if (!Fortorder && (i==0) && (Sddims[i]==Writesdg.dimsizes[i]))continue;
  1094.         if (Fortorder && (i==Writesdg.rank-1) &&
  1095.         (Sddims[i] == Writesdg.dimsizes[i])) continue;
  1096.         if((Fortorder || i>0) && (!Fortorder || i<Writesdg.rank-1)
  1097.        && (Sddims[i] == 0)) continue;
  1098.         DFerror = DFE_BADCALL;
  1099.         return(-1);
  1100.     }
  1101.  
  1102.  
  1103.     if (DFSDputsdg(Sdfile, Writeref, &Writesdg)<0) return(DFIerr(Sdfile));
  1104.  
  1105.     Lastref = Writeref;        /* remember ref written */
  1106.     Writeref=0;            /* don't know ref to write next */
  1107.  
  1108.     ret = DFclose(Sdfile);
  1109.     Sdfile = NULL;        /* partial write complete */
  1110.     Sddims = (int32 *) DFIfreespace((char*) Sddims);
  1111.  
  1112.     return(ret);
  1113. }
  1114.  
  1115.  
  1116. /*-----------------------------------------------------------------------------
  1117.  * Name:    DFSDsettype
  1118.  * Purpose: Set data type, machine type, number type and array order for output
  1119.  * Inputs:  datatype: only DFNT_FLOAT currently supported
  1120.  *          machine type: only the local machine type is supported
  1121.  *          number type: only local float number type and DFNTF_IEEE supported
  1122.  *          array order: may be either C or Fortran order
  1123.  * Returns: 0 on success, -1 on failure with DFerror set
  1124.  * Outputs: none
  1125.  * Users:   HDF users
  1126.  * Invokes: none
  1127.  * Method:  set globals
  1128.  * Remarks: Setting array order may not work if partial writes are attempted
  1129.  *          Sometimes call may accept types which later cause errors when
  1130.  *          conversion is attempted.
  1131.  *---------------------------------------------------------------------------*/
  1132.  
  1133. int DFSDsettype(datatype, machinetype, numbertype, arrayorder)
  1134. int datatype, machinetype, numbertype, arrayorder;
  1135. {
  1136.     if (Sdfile !=NULL) {    /* cannot set type during slice writes */
  1137.         DFerror = DFE_BADCALL;
  1138.         return(-1);
  1139.     }
  1140.  
  1141.     if (datatype && (datatype != DFNT_FLOAT)) {
  1142.         DFerror = DFE_BADDATATYPE;
  1143.         return(-1);
  1144.     }
  1145.  
  1146.     if (machinetype) {
  1147.         outNT = (machinetype>>8) & 0x0f;
  1148.         if ((machinetype!=DF_MT) && (outNT!=DFNTF_IEEE)) {
  1149.             DFerror = DFE_BADMCTYPE;
  1150.             return(-1);
  1151.         }
  1152.     }
  1153.  
  1154.     if (numbertype) outNT = numbertype;
  1155.     if (outNT == ((DF_MT>>8) & 0x0f)) outNTsize = sizeof(float32);
  1156.     else if (outNT == DFNTF_IEEE) outNTsize = 4; /* sizeof IEEE in bytes */
  1157.     else {
  1158.         DFerror = DFE_BADNUMTYPE;
  1159.         return(-1);
  1160.     }
  1161.  
  1162.     if (arrayorder==DFO_FORTRAN) {
  1163.     Fortorder = 1; 
  1164.     if (Ref.transpose<0) Ref.transpose = 0;
  1165.     }
  1166.     else if (arrayorder==DFO_C) {
  1167.     Fortorder = 0;
  1168.     if (Ref.transpose>=0) Ref.transpose = -1;
  1169.     }
  1170.     else if (arrayorder) {
  1171.         DFerror = DFE_BADORDER;
  1172.         return(-1);
  1173.     }
  1174.  
  1175.     return(0);
  1176. }
  1177.  
  1178. /******************************************************************************/
  1179. /*--------------------- Lower level routines --------------------------------*/
  1180. /******************************************************************************/
  1181.  
  1182. /*-----------------------------------------------------------------------------
  1183.  * Name:    DFSDgetsdg
  1184.  * Purpose: Reads in SDG
  1185.  * Inputs:  dfile: pointer to HDF file containing SDG
  1186.  *          ref: ref of SDG to read
  1187.  *          sdg: pointer to DFSsdg struct to read SDG into
  1188.  * Returns: 0 on success, -1 on failure with DFerror set
  1189.  * Users:   HDF programmers, DFSDgetdims, DFSDgetdata
  1190.  * Invokes: DFgetelement, DFdiread, DFdiget, DFaccess, DFread
  1191.  * Method:  Reads in SDG using DFdiread.  Gets each tag/ref using DFdiget.
  1192.  *          Reads in dimensions, labels, units, formats, scales, coordinate
  1193.  *          system using DFgetelement.  Mallocs space for these, freeing
  1194.  *          previously allocated space.
  1195.  * Remarks: This is specific to floating point data
  1196.  *---------------------------------------------------------------------------*/
  1197.  
  1198. int DFSDgetsdg(dfile, ref, sdg)
  1199. DF *dfile;
  1200. uint16 ref;
  1201. DFSsdg *sdg;
  1202. {
  1203.     int i, j, luf, cdd;
  1204.     int error;            /* used by DFconvert macro */
  1205.     DFdle *dlep;
  1206.     struct DFdi elmt, nt;
  1207.     register char *isscales;
  1208.     register char *buf, *p;
  1209.     char ntstring[4];
  1210.  
  1211.     DFerror = DFE_NOERROR;
  1212.  
  1213.     if (DFIcheck(dfile))
  1214.         return( -1);
  1215.  
  1216.     if (!ref) {
  1217.         DFerror = DFE_BADREF;
  1218.         return(-1);
  1219.     }
  1220.  
  1221.     if (DFdiread(dfile, DFTAG_SDG, ref)<0) /* read RIG into memory */
  1222.         return(-1);
  1223.  
  1224.     userNT = (DF_MT>>8) & 0x0f;    /* get third nibble from right */
  1225.  
  1226.     DFSDIclear(sdg);
  1227.     Ismaxmin = 0;
  1228.  
  1229.     while (!DFdiget(&elmt)) {    /* get next tag/ref from RIG */
  1230.         luf = -1;        /* flag value for label/unit format gets */
  1231.         switch (elmt.tag) {    /* process tag/ref */
  1232.  
  1233.             case DFTAG_SD:    /* data tag/ref */
  1234.                 sdg->data.tag = elmt.tag; /* put tag/ref in struct */
  1235.                 sdg->data.ref = elmt.ref;
  1236.                 break;
  1237.  
  1238.             case DFTAG_SDD:    /* dimension */
  1239.                 if (DFaccess(dfile, elmt.tag, elmt.ref, "r")<0) return(-1);
  1240.  
  1241.                 /* read rank */
  1242. #ifdef DF_STRUCTOK
  1243.                 if (DFread(dfile, &sdg->rank, (int32) 2)<0) return(-1);
  1244. #else /*DF_STRUCTOK*/
  1245.                 if (DFread(dfile, DFtbuf, (int32) 2)<0) return(-1);
  1246.                 {
  1247.                     register char *p;
  1248.                     p = DFtbuf;
  1249.                     INT16READ(p, sdg->rank);
  1250.                 }
  1251. #endif /*DF_STRUCTOK*/
  1252.  
  1253.         /* get space for dimensions */
  1254.                 sdg->dimsizes = (int32 *) DFIgetspace((unsigned) sdg->rank *
  1255.                               sizeof(int32));
  1256.                 if (sdg->dimsizes==NULL) return(-1);
  1257.  
  1258.         /* read dimension record */
  1259. #ifdef DF_STRUCTOK
  1260.                 if (DFread(dfile, sdg->dimsizes, (int32) 4*sdg->rank)<0)
  1261.                                                                     return(-1);
  1262.                             /* read NT */
  1263.                 if (DFread(dfile, &nt, (int32) 4)<0) return(-1);
  1264.  
  1265. #else /*DF_STRUCTOK*/
  1266.                 if (DFread(dfile, DFtbuf, (int32) 4*sdg->rank)<0) return(-1);
  1267.                 {
  1268.                     register char *p;
  1269.                     p = DFtbuf;
  1270.                     for (i=0; i<sdg->rank; i++)
  1271.                         INT32READ(p, sdg->dimsizes[i]);
  1272.  
  1273.                             /* read NT */
  1274.                     if (DFread(dfile, DFtbuf, (int32) 4)<0) return(-1);
  1275.                     p = DFtbuf;
  1276.                     UINT16READ(p, nt.tag);
  1277.                     UINT16READ(p, nt.ref);
  1278.                 }
  1279. #endif /*DF_STRUCTOK*/
  1280.                             /* read NT */
  1281.                 if (DFgetelement(dfile, nt.tag, nt.ref, ntstring)<0)
  1282.                     return(-1);
  1283.  
  1284.                             /* check float data */
  1285.                 if (ntstring[1] != DFNT_FLOAT) {
  1286.                     DFerror = DFE_BADCALL;
  1287.                     return(-1);
  1288.                 }
  1289.  
  1290.                             /* set NT info */
  1291.                 fileNT = ntstring[3];
  1292.                 fileNTsize = ntstring[2] / 8;
  1293.  
  1294.                             /* read and check all scale NTs */
  1295.                 for (i=0; i<sdg->rank; i++) {
  1296. #ifdef DF_STRUCTOK
  1297.                             /* read NT tag/ref */
  1298.                     if (DFread(dfile, &nt, (int32) 4)<0) return(-1);
  1299.  
  1300. #else /*DF_STRUCTOK*/
  1301.                     if (DFread(dfile, DFtbuf, (int32) 4)<0) return(-1);
  1302.                     {
  1303.                         register char *p;
  1304.                         p = DFtbuf;
  1305.                         UINT16READ(p, nt.tag);
  1306.                         UINT16READ(p, nt.ref);
  1307.                     }
  1308. #endif /*DF_STRUCTOK*/
  1309.                             /* read NT itself */
  1310.                     if (DFgetelement(dfile, nt.tag,nt.ref, ntstring)<0)
  1311.                         return(-1);
  1312.  
  1313.                             /* check float data */
  1314.                     if (ntstring[1] != DFNT_FLOAT) {
  1315.                         DFerror = DFE_BADCALL;
  1316.                         return(-1);
  1317.                     }
  1318.                 }
  1319.  
  1320.                 break;
  1321.  
  1322.             case DFTAG_SDL:     /* labels */
  1323.                 if (luf==(-1)) luf = LABEL;
  1324.  
  1325.             case DFTAG_SDU:     /* units */
  1326.                 if (luf==(-1)) luf = UNIT;
  1327.  
  1328.             case DFTAG_SDF:     /* formats */
  1329.                 if (luf==(-1)) luf = FORMAT;
  1330.  
  1331.                 if (!sdg->dimsizes) {           /* internal error */
  1332.                     DFerror = DFE_CORRUPT;
  1333.                     return(-1);
  1334.                 }
  1335.  
  1336.                         /* get needed size of buffer, allocate */
  1337.                 if (DFIfind(dfile, elmt.tag, elmt.ref, 1, (uint16) 0,
  1338.                 (uint16) 0, &dlep, &cdd)<0)
  1339.                     return(-1);
  1340.                 buf = DFIgetspace((unsigned) dlep->dd[cdd].length);
  1341.                 if (buf==NULL) return(-1);
  1342.  
  1343.                         /* read in luf */
  1344.                 if (DFgetelement(dfile, elmt.tag, elmt.ref, buf)<0) {
  1345.                     buf = DFIfreespace(buf);
  1346.                     return(-1);
  1347.                 }
  1348.                 p = buf;
  1349.                         /* allocate data luf space */
  1350.                 sdg->dataluf[luf] = DFIgetspace((unsigned) strlen(p)+1);
  1351.                 if (sdg->dataluf[luf]==NULL) {
  1352.                     buf = DFIfreespace(buf);
  1353.                     return(-1);
  1354.                 }
  1355.  
  1356.         /* extract data luf */
  1357.                 strcpy(sdg->dataluf[luf], p);
  1358.                 p += strlen(sdg->dataluf[luf])+1;
  1359.  
  1360.         /* get space for dimluf array */
  1361.                 sdg->dimluf[luf] =
  1362.             (char **) DFIgetspace((unsigned) sdg->rank * sizeof(char *));
  1363.                 if (sdg->dimluf[luf]==NULL) {
  1364.                     buf = DFIfreespace(buf);
  1365.                     return(-1);
  1366.                 }
  1367.  
  1368.                                 /* extract dimension lufs */
  1369.                 for (i=0; i<sdg->rank; i++) {
  1370.                     sdg->dimluf[luf][i] = DFIgetspace((unsigned) strlen(p)+1);
  1371.                     if (sdg->dimluf[luf][i]==NULL) {
  1372.                         buf = DFIfreespace(buf);
  1373.                         return(-1);
  1374.                     }
  1375.                     strcpy(sdg->dimluf[luf][i], p);
  1376.                     p += strlen(sdg->dimluf[luf][i])+1;
  1377.                 }
  1378.                 buf = DFIfreespace(buf);
  1379.                 break;
  1380.  
  1381.             case DFTAG_SDS:     /* scales */
  1382.                 if (!sdg->dimsizes) {           /* internal error */
  1383.                     DFerror = DFE_CORRUPT;
  1384.                     return(-1);
  1385.                 }
  1386.         /* set up to read scale */
  1387.                 if (DFaccess(dfile, elmt.tag, elmt.ref, "r")<0) return(-1);
  1388.  
  1389.         /* read isscales */
  1390.                 isscales = DFIgetspace((unsigned) sdg->rank);
  1391.                 if (isscales==NULL) return(-1);
  1392.                 if (DFread(dfile, isscales, (int32) sdg->rank)<0) return(-1);
  1393.  
  1394.         /* allocate scale pointers */
  1395.                 sdg->dimscales =
  1396.                     (float32 **) DFIgetspace((unsigned) sdg->rank *
  1397.                          sizeof(float32 *));
  1398.                 if (sdg->dimscales==NULL) {
  1399.                     isscales = DFIfreespace(isscales);
  1400.                     return(-1);
  1401.                 }
  1402.  
  1403.                             /* read scales */
  1404.                 for (i=0; i<sdg->rank; i++) {
  1405.                     sdg->dimscales[i] = NULL;       /* default */
  1406.                     if (!isscales[i]) continue;
  1407.  
  1408.                             /* space for scale */
  1409.                     sdg->dimscales[i] = (float32 *)
  1410.             DFIgetspace((unsigned) sdg->dimsizes[i] *
  1411.                     sizeof(float32));
  1412.                     if (sdg->dimscales[i]==NULL) {
  1413.                         isscales = DFIfreespace(isscales);
  1414.                         return(-1);
  1415.                     }
  1416.  
  1417.                     if (userNT == fileNT) {     /* no conversion needed */
  1418.                         if (DFread(dfile, (char*) sdg->dimscales[i], 
  1419.                                 (int32) (sdg->dimsizes[i]*fileNTsize))<0) {
  1420.                             isscales = DFIfreespace(isscales);
  1421.                             return(-1);
  1422.                         }
  1423.                     }
  1424.  
  1425.                     else {                      /* conversion necessary */
  1426.                         register char *p;
  1427.  
  1428.                                 /* allocate conversion buffer */
  1429.                         buf = DFIgetspace((unsigned) sdg->dimsizes[i] *
  1430.                       fileNTsize);
  1431.                         if (buf==NULL) {
  1432.                             isscales = DFIfreespace(isscales);
  1433.                             return(-1);
  1434.                         }
  1435.  
  1436.                                 /* read scale from file */
  1437.                         if (DFread(dfile, buf,
  1438.                                 (int32) (sdg->dimsizes[i]*fileNTsize))<0) {
  1439.                             buf = DFIfreespace(buf);
  1440.                             isscales = DFIfreespace(isscales);
  1441.                             return(-1);
  1442.                         }
  1443.                             
  1444.                         p = buf;
  1445.                 /* convert, all at once */
  1446.                         DFconvert(p, (char*) sdg->dimscales[i], DFNT_FLOAT,
  1447.                                  fileNT, userNT, sdg->dimsizes[i], error);
  1448.  
  1449.                         buf = DFIfreespace(buf);
  1450.                     }
  1451.                 }
  1452.                 isscales = DFIfreespace(isscales);
  1453.                 break;
  1454.  
  1455.             case DFTAG_SDC:    /* coordsys */
  1456.         /* find and allocate necessary space */
  1457.                 if (DFIfind(dfile, elmt.tag, elmt.ref, 1, 0, 0, &dlep, &cdd)<0)
  1458.                     return(-1);
  1459.                 sdg->coordsys = DFIgetspace((unsigned) dlep->dd[cdd].length);
  1460.                 if (sdg->coordsys==NULL) return(-1);
  1461.  
  1462.         /* read coordsys */
  1463.                 if (DFgetelement(dfile, elmt.tag, elmt.ref, sdg->coordsys)<0)
  1464.                     return(-1);
  1465.                 break;
  1466.  
  1467.             case DFTAG_SDM:    /* max/min */
  1468.                 if (fileNT==userNT) {       /* no conversion */
  1469.                     if (DFgetelement(dfile, elmt.tag, elmt.ref,
  1470.                      (char*) &sdg->max_data)<0)
  1471.                         return(-1);
  1472.                 }
  1473.                 else {
  1474.                         /* allocate buffer */
  1475. #ifndef CVT_BUG
  1476.             float32 mm[2];
  1477. #endif
  1478.                     buf = DFIgetspace((unsigned) 2 * fileNTsize);
  1479.                     if (buf==NULL) return(-1);
  1480.  
  1481.                         /* read and convert max/min */
  1482.                     if (DFgetelement(dfile, elmt.tag, elmt.ref, buf)<0)
  1483.                         return(-1);
  1484. #ifdef CVT_BUG
  1485.                     DFconvert(buf, (char*) &sdg->max_data, DFNT_FLOAT, fileNT,
  1486.                   userNT, 1, error);
  1487.                     DFconvert(buf+fileNTsize, (char*) &sdg->min_data,
  1488.                   DFNT_FLOAT, fileNT, userNT, 1, error);
  1489. #else
  1490.             DFconvert(buf, (char*)mm, DFNT_FLOAT,
  1491.                   fileNT, userNT, 2, error);
  1492.             sdg->max_data = mm[0];
  1493.             sdg->min_data = mm[1];
  1494. #endif
  1495.                     buf = DFIfreespace(buf);
  1496.                 }
  1497.                 Ismaxmin = 1;
  1498.                 break;
  1499.                     
  1500.             case DFTAG_SDT:
  1501.                 FileTranspose = 1;
  1502.                 break;
  1503.             default:            /* ignore unknown tags */
  1504.                 break;
  1505.         }
  1506.     }
  1507.     return(0);
  1508. }
  1509.  
  1510.  
  1511. /*-----------------------------------------------------------------------------
  1512.  * Name:    DFSDputsdg
  1513.  * Purpose: Write SDG out to HDF file
  1514.  * Inputs:  dfile: HDF file pointer
  1515.  *          ref: ref to put SDG with
  1516.  *          sdg: struct containing SDG info to put
  1517.  * Returns: 0 on success, -1 on failure with DFerror set
  1518.  * Users:   HDF programmers, utilities, DFSDputdata, other routines
  1519.  * Invokes: DFIcheck, DFdistart, DFdiadd, DFdiend, DFputelement, DFaccess,
  1520.  *          DFwrite
  1521.  * Remarks: Writes out NTs
  1522.  *---------------------------------------------------------------------------*/
  1523.  
  1524. int DFSDputsdg(dfile, ref, sdg)
  1525. DF *dfile;
  1526. uint16 ref;
  1527. DFSsdg *sdg;
  1528. {
  1529.     int i,j, localNT, luf;
  1530.     int error;            /* used by DFConvert macro */
  1531.     uint16 luftag;
  1532.     char ntstring[4];
  1533.     char *buf, *Isscales=NULL;
  1534.     DFdi nt;
  1535.  
  1536.     DFerror = DFE_NOERROR;
  1537.  
  1538.     if (DFIcheck(dfile))
  1539.         return( -1);
  1540.  
  1541.     if (!ref) {
  1542.         DFerror = DFE_BADREF;
  1543.         return(-1);
  1544.     }
  1545.  
  1546.     localNT = (DF_MT>>8) & 0x0f;            /* get third nibble from right */
  1547.  
  1548.         /* prepare to start writing sdg */
  1549.     if (DFdisetup(10)<0) return(-1);        /* max 10 tag/refs in set */
  1550.  
  1551.     if (DFdiput(sdg->data.tag, sdg->data.ref) < 0) return(-1);
  1552.  
  1553.     if (Ref.nt<=0) {
  1554.             /* construct and write out NT */
  1555.         ntstring[0] = DFNT_VERSION;         /* version */
  1556.         ntstring[1] = DFNT_FLOAT;           /* type */
  1557.         ntstring[2] = outNTsize*8;          /* width of float class in bits */
  1558.         ntstring[3] = outNT;                /* class: IEEE floating point */
  1559.         if (DFputelement(dfile, DFTAG_NT, ref, ntstring, (int32) 4) <0)
  1560.             return(-1);
  1561.         Ref.nt = ref;
  1562.     }
  1563.  
  1564.     if (Ref.dims<=0) {
  1565.         if (DFaccess(dfile, DFTAG_SDD, ref, "w")<0) return(-1);
  1566.  
  1567.                 /* write rank, dimensions */
  1568. #ifdef DF_STRUCTOK
  1569.         if (DFwrite(dfile, &sdg->rank, 2)<0) return(-1);
  1570.         if (DFwrite(dfile, sdg->dimsizes, 4 * sdg->rank)<0) return(-1);
  1571. #else /*DF_STRUCTOK*/
  1572.         {
  1573.             register char *p;
  1574.             p = DFtbuf;
  1575.             UINT16WRITE(p, sdg->rank);
  1576.             for (i=0; i<sdg->rank; i++)
  1577.                 INT32WRITE(p, sdg->dimsizes[i]);
  1578.             if (DFwrite(dfile, DFtbuf, (int32) (p-DFtbuf))<0)
  1579.                 return(-1);
  1580.         }
  1581. #endif /*DF_STRUCTOK*/
  1582.  
  1583.                 /* write data NT and scale NTs */
  1584.         nt.tag = DFTAG_NT;
  1585.         nt.ref = Ref.nt;                /* same NT for scales too */
  1586.  
  1587.             /* <= used to write 1 data  NT + rank scale NTs */
  1588.         for (i=0; i<=sdg->rank; i++)    /* scale NTs written even if no scale!*/
  1589.  
  1590. #ifdef DF_STRUCTOK
  1591.             if (DFwrite(dfile, &nt, (int32) 4)<0) return(-1);
  1592. #else /*DF_STRUCTOK*/
  1593.         {
  1594.             register char *p;
  1595.             p = DFtbuf;
  1596.             UINT16WRITE(p, nt.tag);
  1597.             UINT16WRITE(p, nt.ref);
  1598.             if (DFwrite(dfile, DFtbuf, (int32) (p-DFtbuf))<0)
  1599.                 return(-1);
  1600.         }
  1601. #endif /*DF_STRUCTOK*/
  1602.             
  1603.         Ref.dims = ref;
  1604.     }
  1605.     /* write dimension tag/ref */
  1606.     if (DFdiput(DFTAG_SDD,(uint16) Ref.dims) < 0) return(-1);
  1607.  
  1608.             /* write out label/unit/format */
  1609.     for (luf=LABEL; luf<=FORMAT; luf++) {
  1610.         luftag = (luf==LABEL) ? DFTAG_SDL : (luf==UNIT) ? DFTAG_SDU : DFTAG_SDF;
  1611.  
  1612.             /* this block of code checks if luf is NULL, else writes it */
  1613.         if (!Ref.luf[luf]) {            /* if luf was set */
  1614.             Ref.luf[luf] = -1;          /* assume it is NULL */
  1615.             for (i=0; i<sdg->rank; i++) {
  1616.                 if ((sdg->dataluf[luf] && sdg->dataluf[luf][0]) ||
  1617.                     (sdg->dimluf[luf] && sdg->dimluf[luf][i]
  1618.                                       && sdg->dimluf[luf][i][0])) {
  1619.                             /* if luf is non-NULL */
  1620.  
  1621.                             /* set up to write */
  1622.                     if (DFaccess(dfile, luftag, ref, "w")<0) return(-1);
  1623.  
  1624.                             /* write data luf */
  1625.                     if (sdg->dataluf[luf]) {
  1626.                         if (DFwrite(dfile, sdg->dataluf[luf],
  1627.                             (int32) strlen(sdg->dataluf[luf])+1)<0) return(-1);
  1628.                     }
  1629.                     else {  /* write NULL */
  1630.                         if (DFwrite(dfile, "", (int32) 1)<0) return(-1);
  1631.                     }
  1632.                         
  1633.  
  1634.                             /* write dim lufs */
  1635.                     for (j=0; j<sdg->rank; j++)
  1636.                       if (sdg->dimluf[luf] && sdg->dimluf[luf][j]) {
  1637.                         if (DFwrite(dfile, sdg->dimluf[luf][j],
  1638.                            (int32) strlen(sdg->dimluf[luf][j])+1)<0) return(-1);
  1639.                       }
  1640.                       else {    /* write NULL */
  1641.                         if (DFwrite(dfile, "", (int32) 1)<0) return(-1);
  1642.                       }
  1643.                     
  1644.                     Ref.luf[luf] = ref;    /* remember ref */
  1645.                     break;
  1646.                 }
  1647.             }
  1648.         }
  1649.     /* write luf tag/ref */
  1650.         if (Ref.luf[luf]>0) if (DFdiput(luftag, (uint16)Ref.luf[luf]) < 0)
  1651.         return(-1);
  1652.     }
  1653.  
  1654.     /* check if there is a scale and write it out */
  1655.     if (!Ref.scales) {        /* if scale set */
  1656.         Isscales = DFIgetspace((unsigned) sdg->rank);
  1657.         if (Isscales==NULL) return(-1);
  1658.         Ref.scales = (-1);                  /* assume there is no scale */
  1659.  
  1660.                     /* set up Isscales array */
  1661.         for (i=0; i<sdg->rank; i++) {
  1662.             if (sdg->dimscales && sdg->dimscales[i]) {  /* a scale exists */
  1663.                 Isscales[i] = 1;
  1664.                 Ref.scales = 0;             /* flag: write out scales */
  1665.             }
  1666.             else Isscales[i] = 0;
  1667.         }
  1668.     }
  1669.  
  1670.     if (!Ref.scales) {      /* write out scale */
  1671.         if (DFaccess(dfile, DFTAG_SDS, ref, "w")<0) {
  1672.             Isscales = DFIfreespace(Isscales);
  1673.             return(-1);
  1674.         }
  1675.                             /* write Isscales */
  1676.         if (DFwrite(dfile, Isscales, (int32) sdg->rank)<0) {
  1677.             Isscales = DFIfreespace(Isscales);
  1678.             return(-1);
  1679.         }
  1680.                             /* Write scales */
  1681.         for (j=0; j<sdg->rank; j++) {
  1682.             if (!Isscales[j]) continue;
  1683.             if (localNT==outNT) {       /* no conversion needed */
  1684.                 if (DFwrite(dfile, (char*) sdg->dimscales[j],
  1685.                             (int32) (sizeof(float32) * sdg->dimsizes[j]))<0) {
  1686.                     Isscales = DFIfreespace(Isscales);
  1687.                     return(-1);
  1688.                 }
  1689.             }
  1690.             else {              /* convert and write */
  1691.                         /* allocate buffer */
  1692.                 buf = DFIgetspace((unsigned) (outNTsize * sdg->dimsizes[j]));
  1693.                 if (buf==NULL) {
  1694.                     Isscales = DFIfreespace(Isscales);
  1695.                     return(-1);
  1696.                 }
  1697.  
  1698.                         /* convert, all at once */
  1699.                 DFconvert((char*) sdg->dimscales[j], buf, DFNT_FLOAT,
  1700.               localNT, outNT, sdg->dimsizes[j], error);
  1701.                         /* write it all out */
  1702.                 if (DFwrite(dfile, buf,
  1703.                 (int32) (outNTsize * sdg->dimsizes[j]))<0) {
  1704.                     Isscales = DFIfreespace(Isscales);
  1705.                     buf = DFIfreespace(buf);
  1706.                     return(-1);
  1707.                 }
  1708.                 buf = DFIfreespace(buf);
  1709.             }
  1710.         }
  1711.         Ref.scales = ref;
  1712.     }
  1713.     Isscales = DFIfreespace(Isscales);
  1714.     if (Ref.scales>0) if (DFdiput(DFTAG_SDS, (uint16) Ref.scales) < 0)
  1715.     return(-1);
  1716.  
  1717.     /* write coordsys */
  1718.     if (!sdg->coordsys || !sdg->coordsys[0]) Ref.coordsys = (-1);
  1719.     if (!Ref.coordsys) {
  1720.         if (DFputelement(dfile, DFTAG_SDC, ref, sdg->coordsys,
  1721.                             (int32) (strlen(sdg->coordsys)+1))<0) return(-1);
  1722.         Ref.coordsys = ref;
  1723.     }
  1724.     if (Ref.coordsys>0) if (DFdiput(DFTAG_SDC, (uint16) Ref.coordsys) < 0)
  1725.     return(-1);
  1726.         
  1727.     /* write max/min */
  1728.     if (!Ref.maxmin) {
  1729.         if (localNT == outNT) {     /* no conversion */
  1730.             if (DFputelement(dfile, DFTAG_SDM, ref, (char*) &sdg->max_data,
  1731.                  (int32) (2 * sizeof(float32)))<0) return(-1);
  1732.             Ref.maxmin = ref;
  1733.         }
  1734.         else {
  1735.         /* allocate buffer */
  1736. #ifndef CVT_BUG
  1737.         float32 mm[2];
  1738.         mm[0] = sdg->max_data;
  1739.         mm[1] = sdg->min_data;
  1740. #endif
  1741.             buf = DFIgetspace((unsigned) 2*outNTsize); /* max/min is 8 bytes */
  1742.             if (buf==NULL) return(-1);
  1743.  
  1744.         /* convert */
  1745. #ifndef CVT_BUG
  1746.         DFconvert((char*) mm, buf, DFNT_FLOAT, localNT, outNT,2, error);
  1747. #else
  1748.             DFconvert((char*) &sdg->max_data, buf, DFNT_FLOAT, localNT, outNT,
  1749.                       1, error);
  1750.             DFconvert((char*) &sdg->min_data, buf+outNTsize, DFNT_FLOAT,
  1751.               localNT, outNT, 1, error);
  1752. #endif
  1753.         /* write */
  1754.             if (DFputelement(dfile, DFTAG_SDM, ref, buf,
  1755.                  (int32) (2*outNTsize))<0) {
  1756.                 buf = DFIfreespace(buf);
  1757.                 return(-1);
  1758.             }
  1759.             Ref.maxmin = ref;
  1760.             buf = DFIfreespace(buf);
  1761.         }
  1762.     }
  1763.     if (Ref.maxmin>0) if (DFdiput(DFTAG_SDM, (uint16) Ref.maxmin) < 0)
  1764.     return(-1);
  1765.     Ref.maxmin = (-1);        /* max/min should be reset for each data set */
  1766.  
  1767.     if (!Ref.transpose) {
  1768.         if (DFaccess(dfile, DFTAG_SDT, ref, "w")<0) return(-1);
  1769.         Ref.transpose = ref;
  1770.     }
  1771.         
  1772.     if (Ref.transpose>0) if (DFdiput(DFTAG_SDT, (uint16) Ref.transpose) < 0)
  1773.     return(-1);
  1774.  
  1775.     /* write out SDG */
  1776.     return(DFdiwrite(dfile, DFTAG_SDG, ref));
  1777. }
  1778.  
  1779.  
  1780. /******************************************************************************/
  1781. /*----------------------- Internal routines ---------------------------------*/
  1782. /******************************************************************************/
  1783.  
  1784. /*-----------------------------------------------------------------------------
  1785.  * Name:    DFSDIopen
  1786.  * Purpose: open or reopen a file
  1787.  * Inputs:  filename: name of file to open
  1788.  *          access : access mode
  1789.  * Returns: file pointer on success, NULL on failure with DFerror set
  1790.  * Users:   HDF systems programmers, many SD routines
  1791.  * Invokes: DFopen
  1792.  * Remarks: This is a hook for someday providing more efficient ways to
  1793.  *          reopen a file, to avoid re-reading all the headers
  1794.  *---------------------------------------------------------------------------*/
  1795.  
  1796. DF *DFSDIopen(filename, access)
  1797. char *filename;
  1798. int access;
  1799. {
  1800.  
  1801.     DF *dfile;
  1802.  
  1803.     if (Sdfile!=NULL) {     /* in the middle of a partial write */
  1804.         DFerror = DFE_ALROPEN;
  1805.         return(NULL);
  1806.     }
  1807.  
  1808.         /* use reopen if same file as last time - more efficient */
  1809.     if (strncmp(Lastfile,filename,DF_MAXFNLEN) || (access==DFACC_CREATE)) {
  1810.                                     /* treat create as different file */
  1811.         if (!(dfile = DFopen(filename, access, -1))) return(NULL);
  1812.         Newdata = (-1);         /* data in Readsdg is not fresh */
  1813.         Readsdg.data.ref = 0;   /* No SDG read yet */
  1814.  
  1815.                     /* remember no info written to file */
  1816.         Ref.scales  = (Ref.scales  >= 0) ? 0 : Ref.scales;
  1817.         Ref.luf[LABEL]  = (Ref.luf[LABEL]  >= 0) ? 0 : Ref.luf[LABEL];
  1818.         Ref.luf[UNIT]   = (Ref.luf[UNIT]   >= 0) ? 0 : Ref.luf[UNIT];
  1819.         Ref.luf[FORMAT] = (Ref.luf[FORMAT] >= 0) ? 0 : Ref.luf[FORMAT];
  1820.         Ref.dims    = (Ref.dims    >= 0) ? 0 : Ref.dims;
  1821.         Ref.coordsys = (Ref.coordsys >= 0) ? 0 : Ref.coordsys;
  1822.         Ref.maxmin = (Ref.maxmin >= 0) ? 0 : Ref.maxmin;
  1823.         Ref.nt = (Ref.nt >= 0) ? 0 : Ref.nt;
  1824.     }
  1825.     else
  1826.         if (!(dfile = DFopen(filename, access, -1))) return(NULL);
  1827.  
  1828.     strncpy(Lastfile, filename, DF_MAXFNLEN); 
  1829.             /* remember filename, so reopen may be used next time if same file*/
  1830.  
  1831.     return(dfile);
  1832. }
  1833.  
  1834.  
  1835. /*-----------------------------------------------------------------------------
  1836.  * Name:    DFSDIsdginfo
  1837.  * Purpose: Locates next sdg in file
  1838.  * Inputs:  dfile: pointer to DF file
  1839.  * Returns: 0 on success, -1 on failure with DFerror set
  1840.  * Users:   HDF systems programmers, DFSDgetdims, DFSDgetdata
  1841.  * Invokes: DFIfind, DFSDgetsdg
  1842.  * Method:  Call DFIfind to find SDG, then DFSDgetsdg to read it in to Readsdg
  1843.  * Remarks: none
  1844.  *---------------------------------------------------------------------------*/
  1845.  
  1846. DFSDIsdginfo(dfile)
  1847. DF *dfile;
  1848. {
  1849.     DFdle *dlep;
  1850.     int cdd;
  1851.  
  1852.     if (DFIcheck(dfile)) {
  1853.         DFerror = DFE_BADCALL;
  1854.         return(-1);
  1855.     }
  1856.         
  1857.     /* find next sdg */
  1858.     if ((!Readref
  1859.      && DFIfind(dfile, DFTAG_SDG, DFREF_WILDCARD, !Readsdg.data.ref,
  1860.         DFTAG_SDG, Readsdg.data.ref, &dlep, &cdd) <0)
  1861.     ||
  1862.     (Readref
  1863.      && DFIfind(dfile, DFTAG_SDG, Readref, 1, 0, 0, &dlep, &cdd) < 0)) {
  1864.         Newdata = (-1);
  1865.         DFerror = DFE_NOMATCH;
  1866.         return(-1);
  1867.     }
  1868.     if (DFSDgetsdg(dfile, dlep->dd[cdd].ref, &Readsdg)<0) return(-1);
  1869.  
  1870.     Lastref = dlep->dd[cdd].ref; /* remember ref read */
  1871.  
  1872.     /* now Readsdg is fresh */
  1873.     Newdata=1;
  1874.     Readref = 0;
  1875.  
  1876.     return(0);
  1877. }
  1878.  
  1879.  
  1880. /*-----------------------------------------------------------------------------
  1881.  * Name:    DFSDIclear
  1882.  * Purpose: Reset all "set" values, free allocated space
  1883.  * Inputs:  sdg: pointer to sdg struct to clear
  1884.  * Globals: Ref
  1885.  * Returns: 0 on success, -1 on error with DFerror set
  1886.  * Users:   HDF users, utilities, other routines
  1887.  * Invokes: none
  1888.  * Method:  Release space in sdg
  1889.  * Remarks: none
  1890.  *---------------------------------------------------------------------------*/
  1891.  
  1892. int DFSDIclear(sdg)
  1893. DFSsdg *sdg;
  1894. {
  1895.     int luf, i;
  1896.  
  1897.     DFerror = DFE_NOERROR;
  1898.  
  1899.     if (Sdfile !=NULL) {                /* cannot clear during slice writes */
  1900.         DFerror = DFE_BADCALL;
  1901.         return(-1);
  1902.     }
  1903.  
  1904.     sdg->dimsizes = (int32 *) DFIfreespace((char*) sdg->dimsizes);
  1905.  
  1906.     sdg->coordsys = DFIfreespace(sdg->coordsys);
  1907.  
  1908.         /* free label/unit/format pointers */
  1909.     for (luf=LABEL; luf<=FORMAT; luf++) {
  1910.         if (sdg->dimluf[luf])       /* free strings */
  1911.             for (i=0; i<sdg->rank; i++)
  1912.                 sdg->dimluf[luf][i] = DFIfreespace(sdg->dimluf[luf][i]);
  1913.  
  1914.     /* free string pointers */
  1915.         sdg->dimluf[luf] = (char **) DFIfreespace((char*) sdg->dimluf[luf]);
  1916.  
  1917.     /* free data string */
  1918.         sdg->dataluf[luf] = DFIfreespace(sdg->dataluf[luf]);
  1919.     }
  1920.  
  1921.     /* free scale pointers */
  1922.     if (sdg->dimscales)
  1923.         for (i=0; i<sdg->rank; i++)
  1924.             sdg->dimscales[i] = (float32 *)
  1925.         DFIfreespace((char*) sdg->dimscales[i]);
  1926.  
  1927.     /* free array of scale pointers */
  1928.     sdg->dimscales = (float32 **) DFIfreespace((char*)sdg->dimscales);
  1929.  
  1930.     sdg->rank = 0;
  1931.  
  1932.     Ref.dims = -1;
  1933.     Ref.scales = Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = (-1);
  1934.     Ref.coordsys = Ref.maxmin = (-1);
  1935.     return(0);
  1936. }
  1937.  
  1938.  
  1939. /*-----------------------------------------------------------------------------
  1940.  * Name:    DFSDIgetdata
  1941.  * Purpose: Get data from SDG.  Will sequence to next SDG if DFSDgetdims not
  1942.  *          called.
  1943.  * Inputs:  filename: name of HDF file to use
  1944.  *          rank: no of dimensions of array "data"
  1945.  *          maxsizes: actual dimensions of array "data"
  1946.  *          data: data for returning scientific data
  1947.  *          isfortran : 0 if called from C, 1 when called from FORTRAN
  1948.  * Returns: 0 on success, -1 on failure with DFerror set
  1949.  * Outputs: actual scientific data in array
  1950.  * Users:   DFSDgetdata
  1951.  * Invokes: DFSDIgetslice, DFIgetspace, DFIfreespace, DFSDIopen, DFclose,
  1952.  *          DFIerr, DFSDIsdginfo
  1953.  * Method:  Open file, call DFSDIsdginfo to read sdg if necessary, set up
  1954.  *          window start and end arrays, call DFSDIgetslice.
  1955.  * Remarks: maxsizes may be larger than actual size.  In that event, the actual
  1956.  *          data may not be contiguous in the array "data"
  1957.  *          User sets maxsizes before call.
  1958.  *---------------------------------------------------------------------------*/
  1959.  
  1960.  
  1961. int DFSDIgetdata(filename, rank, maxsizes, data, isfortran)
  1962. char *filename;
  1963. int rank;
  1964. int32 maxsizes[];
  1965. float32 data[];
  1966. int isfortran;
  1967. {
  1968.     int32 *winst, *windims;
  1969.     int ret, i;
  1970.     DF *dfile;
  1971.  
  1972.     DFerror = DFE_NOERROR;
  1973.  
  1974.     if (Newdata!=1 || Nextsdg) { /* if Readsdg not fresh */
  1975.         dfile = DFSDIopen(filename, DFACC_READ);
  1976.         if (dfile == NULL) return(-1);
  1977.         if (DFSDIsdginfo(dfile)<0) /* reads next SDG from file */
  1978.             return(DFIerr(dfile));
  1979.         if (DFclose(dfile)<0) return(-1);
  1980.     }
  1981.  
  1982.     winst = (int32 *) DFIgetspace((unsigned) Readsdg.rank * sizeof(int32));
  1983.     if (winst==NULL) return(-1);
  1984.     windims = (int32 *) DFIgetspace((unsigned) Readsdg.rank * sizeof(int32));
  1985.     if (windims==NULL) {
  1986.         DFIfreespace((char*) winst);
  1987.         return(-1);
  1988.     }
  1989.  
  1990.     for (i=0; i<rank; i++) {
  1991.         winst[i] = 1;
  1992.         windims[i] = Readsdg.dimsizes[i];
  1993.     }
  1994.  
  1995.     ret = DFSDIgetslice(filename, winst, windims, data, maxsizes,
  1996.             isfortran);
  1997.     winst = (int32 *) DFIfreespace((char*) winst);
  1998.     windims = (int32 *) DFIfreespace((char*) windims);
  1999.     Nextsdg = 1;
  2000.     return(ret);
  2001. }
  2002.  
  2003.  
  2004. /*-----------------------------------------------------------------------------
  2005.  * Name:    DFSDIputdata
  2006.  * Purpose: Writes entire SDG to file
  2007.  * Inputs:  filename: name of HDF file to use
  2008.  *          rank: rank of data array
  2009.  *          dimsizes: sizes of the dimensions of data array
  2010.  *          data: array that holds data
  2011.  *          accmode: 0 if write to new file, 1 if append to file
  2012.  *          isfortran: 0 if C, 1 if FORTRAN
  2013.  * Globals: Writeref
  2014.  * Returns: 0 on success, -1 on failure with DFerror set
  2015.  * Users:   HDF users, utilities, other routines
  2016.  * Invokes: DFSDIopen, DFclose, DFIgetspace, DFIfreespace, DFSDIputslice,
  2017.  *          DFSDstartslice, DFSDendslice
  2018.  * Method:  Create file if necessary, allocate arrays, call slice routines
  2019.  *---------------------------------------------------------------------------*/
  2020.  
  2021. int DFSDIputdata(filename, rank, dimsizes, data, accmode, isfortran)
  2022. char *filename;
  2023. int16  rank;
  2024. int32   *dimsizes;
  2025. float32 *data;
  2026. int accmode;
  2027. int isfortran;
  2028. {
  2029.     int ret;
  2030.     DF *dfile;
  2031.  
  2032.     DFerror = DFE_NOERROR;
  2033.  
  2034.     if (!accmode) {                             /* new file */
  2035.         dfile = DFSDIopen(filename, DFACC_CREATE);
  2036.         if (dfile == NULL) return(-1);
  2037.         if (DFclose(dfile)<0) return(-1);
  2038.     }
  2039.  
  2040.     if (Ref.dims)       /* don't call setdims if already called */
  2041.         if (DFSDsetdims(rank, dimsizes)<0) return(-1);
  2042.  
  2043.     if (DFSDstartslice(filename)<0) return(-1);
  2044.  
  2045.     if ((ret=DFSDIputslice(Writesdg.dimsizes, data, dimsizes, isfortran)) <0)
  2046.     return ret;
  2047.  
  2048.     return DFSDendslice();
  2049. }
  2050.  
  2051. /*----------------------------------------------------------------------------
  2052.  * Name:    DFSDIgetslice
  2053.  * Purpose: Get slice of data from SDG.  Will sequence to next SDG if
  2054.  *          DFSDgetdims, DFSDgetdata or DFSDgetslice not called earlier.
  2055.  * Inputs:  filename: name of HDF file to use
  2056.  *          winst: array of size = rank of data, containing start of slice
  2057.  *          windims: array of size rank, containing size of slice
  2058.  *          data: array for returning slice
  2059.  *          dims: dimensions of array data
  2060.  *          isfortran : 0 if called from C, 1 when called from FORTRAN
  2061.  * Returns: 0 on success, -1 on failure with DFerror set
  2062.  * Outputs: slice of data in data
  2063.  * Users:   DFSDIgetdata
  2064.  * Invokes: DFSDIopen, DFclose, DFIerr, DFSDIsdginfo, DFaccess, DFread
  2065.  * Method:  Open file, call DFSDIsdginfo to read sdg if necessary, read the
  2066.  *          data, convert types if necessary, place in data as appropriate
  2067.  *          data is assumed column major for FORTRAN, row major for C
  2068.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  2069.  *          data may not be contiguous in the array "data".
  2070.  *          User sets dims before call.
  2071.  *--------------------------------------------------------------------------*/
  2072.  
  2073. int DFSDIgetslice(filename, winst, windims, data, dims, isfortran)
  2074.     char    *filename;
  2075.     int32    winst[];    /* array containing starting dimensions */
  2076.                 /* of the slice    */
  2077.     int32    windims[];    /* array containing the size of the slice */
  2078.     int32    dims[];        /* array containing the dimensions of data[] */
  2079.     float32    data[];        /* array to hold the floating point data read*/
  2080.     int        isfortran;    /* true if called from Fortran */
  2081.  
  2082. {
  2083.     int
  2084.     rank,            /* number of dimensions in data[] */
  2085.     leastsig,        /* fastest varying subscript in the array */
  2086.     error;            /* flag if an error occurred */
  2087.                 /* used by DFconvert macro */
  2088.     int
  2089.     convert,        /* true if machine NT = NT to be read */
  2090.     done,            /* true if we are at end of the slice */
  2091.     transposed;        /* true if we must transpose */
  2092.                 /* the data before writing */
  2093.     int32
  2094.     i, j,            /* temporaries */
  2095.     numfloats,        /* number of floats to read at once */
  2096.     readsize,        /* number of bytes to read at once */ 
  2097.     stride,            /* number of floats in one row of data[] */
  2098.     *dimsleft,        /* array for tracking the current position */
  2099.                 /* in data[] */
  2100.     *offset,        /* array for accessing the next element */
  2101.                 /* in data[] */
  2102.     *foffset,        /* array for accessing the next element */
  2103.                 /* from the file   */
  2104.     fileoffset,        /* offset into the current dataset */
  2105.                 /* in the file          */
  2106.     *wstart,        /* tmp array containing starting slice dims */
  2107.     *wdims,            /* tmp array containing the slice size */
  2108.     *adims,            /* tmp array containing the dimensions */
  2109.                 /* of data[] */
  2110.     *fdims;            /* tmp array containing the */
  2111.                 /* dataset dimensions */
  2112.             
  2113.     float32
  2114.     *datap,            /* ptr into data[] at starting offset */
  2115.                 /* of current block */
  2116.     *dp,            /* ptr into data[] at an element */
  2117.                 /* of the current row */
  2118.     *scatterbuf;        /* buffer to hold the */
  2119.                 /* current row contiguously */
  2120.     char
  2121.     *buf;            /* buffer containing the */
  2122.                 /* converted current row */
  2123.     DF    *dfile;            /* HDF file pointer */
  2124.  
  2125.     DFerror = DFE_NOERROR;
  2126.  
  2127.     if (!data) {
  2128.         DFerror = DFE_BADPTR;
  2129.         return(-1);
  2130.     }
  2131.  
  2132.     dfile = DFSDIopen(filename, DFACC_READ);
  2133.     if (dfile == NULL) return(-1);
  2134.  
  2135.     if (Newdata!=1) {        /* if Readsdg not fresh */
  2136.         if (DFSDIsdginfo(dfile)<0) /* reads next SDG from file */
  2137.             return(DFIerr(dfile));
  2138.     }
  2139.  
  2140.     rank = Readsdg.rank;
  2141.  
  2142.     /* get dimensions of slice to extract, set nwindims. also err check */
  2143.     for (i=0; i<rank; i++) {
  2144.         /* check validity for the dimension ranges */
  2145.         if ((windims[i]<=0) || (winst[i]<=0)
  2146.         || (winst[i]+windims[i]-1 > Readsdg.dimsizes[i])) {
  2147.         DFerror = DFE_BADDIM;
  2148.         return(DFIerr(dfile));
  2149.     }
  2150.     /* check if space allocated is sufficient */
  2151.     if (dims[i]<windims[i]) {
  2152.             DFerror = DFE_NOTENOUGH;
  2153.             return(DFIerr(dfile));
  2154.         }
  2155.     }
  2156.  
  2157.     /* allocate buffers */
  2158.     wstart = (int32 *) DFIgetspace((unsigned) 4 * rank * sizeof(int32));
  2159.     if (wstart == NULL) {
  2160.     DFerror = DFE_NOSPACE;
  2161.         return(DFIerr(dfile));
  2162.     }
  2163.     wdims = wstart + rank;
  2164.     adims = wdims + rank;
  2165.     fdims = adims + rank;
  2166.  
  2167.     /* copy arrays to private workspace (so that they are in row major order)*/
  2168.     for (i=0; i<rank; i++) {
  2169.     int ii = isfortran ? rank-i-1 : i;
  2170.     adims[i] = dims[ii];
  2171.     ii = FileTranspose ? rank-i-1 : i;
  2172.     wstart[i] = winst[ii]-1; /* translate to 0 origin */
  2173.     wdims[i] = windims[ii];
  2174.     fdims[i] = Readsdg.dimsizes[ii];
  2175.     }
  2176.  
  2177.     userNT     = (DF_MT>>8) & 0x0f; /* get third nibble from right*/
  2178.     convert    = (fileNT != userNT); /* is conversion necessary */
  2179.     transposed = isfortran ^ FileTranspose; /* is transposition needed */
  2180.  
  2181.     /*
  2182.      * Note that if the data is transposed we must work on a row by row
  2183.      * basis and cannot collapse dimensions.
  2184.      */
  2185.     if (!transposed) {
  2186.     /* collapse dimensions if contiguous both in the file and in memory */
  2187.     for (i=rank-1; i>0; i--) { /* stop before most sig dim */
  2188.         if (adims[i] > wdims[i] /* not all of data[] will be filled */
  2189.         || wstart[i] != 0 /* reading only part of the dataset */
  2190.         || wdims[i] < fdims[i])
  2191.         break;
  2192.         wstart[i-1] = wstart[i-1] * wdims[i];
  2193.         wdims[i-1] *= wdims[i];
  2194.         adims[i-1] = fdims[i-1] = wdims[i-1];
  2195.         rank--;
  2196.     }
  2197.     }
  2198.     leastsig = rank-1;        /* which is least sig dim */
  2199.  
  2200.     /* position at start of image */
  2201.     if (DFaccess(dfile, Readsdg.data.tag, Readsdg.data.ref, "r") < 0) {
  2202.     DFIfreespace((char *)wstart);
  2203.         return(DFIerr(dfile));
  2204.     }
  2205.  
  2206.     error = 0;
  2207.     if (rank==1 && !convert) {
  2208.     /* all data is contiguous with no conversions */
  2209.     readsize = adims[0] * sizeof(float32);
  2210.     if (DFIseek(dfile, wstart[0]*fileNTsize) < 0 ||
  2211.         readsize != DFread(dfile, (char *)data, readsize))
  2212.         error=1;
  2213.     } else {
  2214.     /*
  2215.      * The data must be further manipulated.
  2216.      * It may be transposed, may need conversion, may not be contiguous, or
  2217.      * any combination of these.
  2218.      */
  2219.     numfloats  = wdims[leastsig];
  2220.     readsize = numfloats * fileNTsize;
  2221.  
  2222.     /* allocate 1 row buffers */
  2223.     if (convert) {
  2224.         if ((buf = DFIgetspace((unsigned) readsize)) == NULL) {
  2225.         DFIfreespace((char *)wstart);
  2226.         DFerror = DFE_NOSPACE;
  2227.         return(DFIerr(dfile));
  2228.         }
  2229.     } else buf = NULL;
  2230.  
  2231.     if (transposed) {
  2232.         scatterbuf = (float32 *)DFIgetspace((unsigned) numfloats
  2233.                         *sizeof(float32));
  2234.         if (scatterbuf == NULL) {
  2235.         DFIfreespace((char *)wstart);
  2236.         DFIfreespace(buf);
  2237.         DFerror = DFE_NOSPACE;
  2238.         return(DFIerr(dfile));
  2239.         }
  2240.     } else scatterbuf = NULL;
  2241.  
  2242.     offset = (int32 *) DFIgetspace((unsigned)3 * rank * sizeof(int32));
  2243.     if (offset==NULL) {
  2244.         DFIfreespace((char *)wstart);
  2245.         DFIfreespace(buf);
  2246.         DFIfreespace((char *)scatterbuf);
  2247.         DFerror = DFE_NOSPACE;
  2248.         return(DFIerr(dfile));
  2249.     }
  2250.     foffset = offset + rank;
  2251.     dimsleft = foffset + rank;
  2252.  
  2253.     /* compute initial position in the data */
  2254.     for (i=leastsig; i>=0; i--)
  2255.         dimsleft[i] = wdims[i];
  2256.  
  2257.     /* compute offsets in the source array */
  2258.     if (transposed) {
  2259.         offset[0] = 1;
  2260.         for (i=0; i<leastsig; i++)
  2261.         offset[i+1] = offset[i] * adims[leastsig - i];
  2262.     } else {
  2263.         offset[leastsig] = 1;
  2264.         for (i = leastsig; i>0; i--)
  2265.         offset[i-1] = offset[i] * adims[i];
  2266.     }
  2267.     stride = offset[leastsig];
  2268.  
  2269.     /* compute offsets in the file */
  2270.     for (i=leastsig, foffset[i]=1*fileNTsize; i>0; i--)
  2271.         foffset[i-1] = foffset[i] * fdims[i];
  2272.  
  2273.     /*
  2274.      * Compute starting position in file
  2275.      * All file reads are done relative to this starting offset.
  2276.      * Cumulative offset is from most sig to next to least sig dim.
  2277.      */
  2278.     for (i=0, fileoffset=0; i<leastsig; i++) 
  2279.         fileoffset = (fileoffset+wstart[i]) * fdims[i+1];
  2280.     fileoffset += wstart[leastsig]; /* adjust for last dim */
  2281.     fileoffset *= fileNTsize; /* convert to bytes */
  2282.  
  2283.     datap = data;
  2284.     done = 0;
  2285.  
  2286.     /* -- now read in the data */
  2287.     do {
  2288.         /* move to the next data element in the file */
  2289.         if (DFIseek(dfile, fileoffset) < 0) {
  2290.         error=1;
  2291.         break;
  2292.         }
  2293.  
  2294.         /* read and convert one contiguous block of data */
  2295.         if (convert) {
  2296.         if (readsize != DFIread(dfile, buf, readsize)) {
  2297.             error=1;
  2298.             break;
  2299.         }
  2300.         DFconvert(buf, transposed ? (char *)scatterbuf : (char *)datap,
  2301.               DFNT_FLOAT, fileNT, userNT, numfloats, error);
  2302.         }
  2303.         else
  2304.         if (readsize != DFIread(dfile, transposed ?
  2305.                        (char *)scatterbuf :
  2306.                        (char *)datap, readsize)) {
  2307.             error=1;
  2308.             break;
  2309.         }
  2310.  
  2311.         if (transposed) {
  2312.         /* scatter out the elements of one row */
  2313. #ifdef UNICOS
  2314. #pragma ivdep
  2315. #endif
  2316.         for (dp=datap, i=0; i<numfloats; i++) {
  2317.             *dp = scatterbuf[i];
  2318.             dp += stride;
  2319.         }
  2320.         }
  2321.  
  2322.         /*
  2323.          * Find starting place of the next row/block.
  2324.          * Note that all moves are relative:
  2325.          *   this preserves the starting offsets of each dimension 
  2326.          */
  2327.         for (i=leastsig-1; i>=0; i--) {
  2328.         if (--dimsleft[i] > 0) {
  2329.             /* move to next element in the current dimension */
  2330.             datap += offset[i];
  2331.             fileoffset += foffset[i];
  2332.             break;
  2333.         } else {
  2334.             dimsleft[i] = wdims[i];
  2335.             /*
  2336.              * Note that we are still positioned at the beginning of
  2337.              * the last element in the current dimension 
  2338.              */
  2339.             /* move back to the beginning of dimension i */
  2340.             datap -= offset[i] * (wdims[i]-1);
  2341.             /* move back to beginning read position of dimension i */
  2342.             fileoffset -= foffset[i] * (wdims[i]-1);
  2343.             if (i==0) done = 1;
  2344.         }
  2345.         }
  2346.     } while (!done && leastsig > 0);
  2347.  
  2348.     DFIfreespace(buf);
  2349.     DFIfreespace((char *)scatterbuf);
  2350.     DFIfreespace((char *)offset);
  2351.     }
  2352.  
  2353.     DFIfreespace((char *)wstart);
  2354.     return( error ? DFIerr(dfile) : DFclose(dfile) );
  2355. }
  2356.  
  2357. /*----------------------------------------------------------------------------
  2358.  * Name:    DFSDIputslice
  2359.  * Purpose: Put slice of data to SDG.
  2360.  * Inputs:  windims: array of size rank, containing size of slice
  2361.  *          data: array containing slice
  2362.  *          dims: dimensions of array data
  2363.  *            isfortran: 0 for C, 1 for Fortran
  2364.  * Returns: 0 on success, -1 on failure with DFerror set
  2365.  * Users:   DFSDputslice
  2366.  * Invokes: DFwrite, DFIgetspace, DFIfreespace
  2367.  * Method:  check dimensions for contiguity, convert types if necessary
  2368.  *          write to file
  2369.  * Remarks: dims may be larger than size of slice.  In that event, the actual
  2370.  *          data may not be contiguous in the array "data".
  2371.  *          DFSDstartslice must have been called first
  2372.  *          Note, writes must be contiguous - successive calls to putslice
  2373.  *          must write out array consecutively, according to the setting
  2374.  *          of the Fortorder variable - row major if 0, column major if 1
  2375.  *--------------------------------------------------------------------------*/
  2376.  
  2377. int DFSDIputslice(windims, data, dims, isfortran)
  2378.  
  2379.     int32    windims[];    /* array containing dimensions of the slice */
  2380.     int32    dims[];        /* array containing the dimensions of data[] */
  2381.     float32    data[];        /* array of the floating point data to write */
  2382.     int        isfortran;    /* true if called from Fortran */
  2383. {
  2384.     int
  2385.     rank,            /* number of dimensions in data[] */
  2386.     ret,            /* return code from DFwrite */
  2387.     leastsig;        /* fastest varying subscript in the array */
  2388.     int
  2389.     convert,        /* true if machine NT = NT to be written */
  2390.     done,            /* true if we are at end of the slice */
  2391.     transposed,        /* true if we must transpose */
  2392.                 /* the data before writing    */
  2393.     contiguous;        /* true if there are no gaps */
  2394.                 /* in the data to be written    */
  2395.     int error;            /* used by DFconvert macro */
  2396.     int32
  2397.     i, j,            /* temporaries */
  2398.     numfloats,        /* number of floats to write out per row */
  2399.     writesize,        /* number of bytes to write out per row */
  2400.     stride,            /* number of bytes in one row of data[] */
  2401.     *dimsleft,        /* array for tracking the */
  2402.                 /* current position in data[]    */
  2403.     *offset;        /* array for accessing the */
  2404.                 /* next element in data[] */
  2405.     float32
  2406.     *datap,            /* pointer into data[] at */
  2407.                 /* the start of the current row    */
  2408.     *dp,            /* pointer into data[] to an element */
  2409.                 /* of the current row */
  2410.     *gatherbuf;        /* buffer to hold the current row */
  2411.                 /* contiguously */
  2412.     char
  2413.     *buf,            /* buffer containing the */
  2414.                 /* converted current row */
  2415.     *outbufp;        /* pointer to the buffer containing */
  2416.                 /* the data to write */
  2417.  
  2418.     DFerror = DFE_NOERROR;
  2419.  
  2420.     if (!data) {
  2421.         DFerror = DFE_BADPTR;
  2422.         return(-1);
  2423.     }
  2424.  
  2425.     if (!Sdfile) {
  2426.         DFerror = DFE_BADCALL;
  2427.         return(-1);
  2428.     }
  2429.  
  2430.     rank = Writesdg.rank;
  2431.  
  2432.     for (i=0; i<rank; i++) {
  2433.         /* check validity for the dimension ranges */
  2434.         if ((windims[i]<=0) || (windims[i]>Writesdg.dimsizes[i])) {
  2435.             DFerror = DFE_BADDIM;
  2436.             return(-1);
  2437.         }
  2438.     /* check if space allocated is sufficient */
  2439.     if (dims[i] < windims[i]) {
  2440.         DFerror = DFE_NOTENOUGH;
  2441.         return(-1);
  2442.     }
  2443.     }
  2444.  
  2445.     /* check to see if the slices fit together */
  2446.     if (Fortorder) {
  2447.     /* find the first significant dimension */
  2448.     for (i=rank-1; windims[i] == 1 && i>0; i--)
  2449.         ;
  2450.     /* check that all 'lesser' dims match */
  2451.     for (j=i-1; j>=0; j--)
  2452.         if (dims[j] != windims[j]) {
  2453.         DFerror = DFE_BADDIM;
  2454.         return (-1);
  2455.         }
  2456.     /* update Sddims to reflect new write */
  2457.     Sddims[i] += windims[i];
  2458.     for (; i<rank-1 && Sddims[i] >= dims[i]; i++) {
  2459.         Sddims[i+1] += Sddims[i] / dims[i]; /* promote the unit */
  2460.         Sddims[i] %= dims[i];
  2461.     }
  2462.     } else {
  2463.     /* find the first significant dimension */
  2464.     for (i=0; windims[i] == 1 && i<rank-1; i++)
  2465.         ;
  2466.     /* check that all 'lesser' dims match */
  2467.     for (j=i+1; j<rank; j++)
  2468.         if (dims[j] != windims[j]) {
  2469.         DFerror = DFE_BADDIM;
  2470.         return (-1);
  2471.         }
  2472.     /* update Sddims to reflect new write */
  2473.     Sddims[i] += windims[i];
  2474.     for (;i>0 && Sddims[i] >= dims[i]; i--) {
  2475.         Sddims[i-1] += Sddims[i] / dims[i]; /* promote the unit */
  2476.         Sddims[i] %= dims[i];
  2477.     }
  2478.     }
  2479.  
  2480.     leastsig = Fortorder ? 0 : rank-1; /* which is least sig dim */
  2481.     userNT = (DF_MT>>8) & 0x0f;    /* get third nibble from right */
  2482.     convert = (outNT != userNT); /* is conversion necessary */
  2483.     transposed = isfortran ^ Fortorder;    /* is data transposition needed */
  2484.  
  2485.     contiguous = !transposed;
  2486.     for (i=0; contiguous && i<rank; i++) {
  2487.     /* check if data at the start of the users array will be contiguous */
  2488.     /* NOTE: do this if a winstart[] array is ever added */
  2489.  
  2490.     /* check if data at the end of the users array will be contiguous */
  2491.     if (dims[i] > Writesdg.dimsizes[i])
  2492.         contiguous = 0;
  2493.     }
  2494.  
  2495.     /*
  2496.      *    3 Factors that determine how we write (in order of importance)
  2497.      *    transposed, conversion, contiguous
  2498.      */
  2499.  
  2500.     if (!transposed) {
  2501.     if (!convert && contiguous) {
  2502.         /* compute total number of floats to write */
  2503.         for (i=0, numfloats=1; i<rank; i++) numfloats *= windims[i];
  2504.         writesize = numfloats * sizeof(float32);
  2505.         if ((ret = DFwrite(Sdfile, (char *)data, writesize)) < 0)
  2506.         return(DFIerr(Sdfile));
  2507.     }
  2508.     else {            /* must step through the data */
  2509.         /* compute number of occurrences of the least sig dim */
  2510.         if (Fortorder)
  2511.         for (i=rank-1, j=1; i>0; i--) j *= windims[i];
  2512.         else
  2513.         for (i=0, j=1; i<rank-1; i++) j *= windims[i];
  2514.         numfloats = windims[leastsig];
  2515.         writesize = numfloats * outNTsize;
  2516.         stride = dims[leastsig];
  2517.         if (convert) { 
  2518.         buf = DFIgetspace((unsigned) writesize);
  2519.         if (buf == NULL) return(DFIerr(Sdfile));
  2520.         for (i=0; i<j; i++, data+=stride) {
  2521.             DFconvert((char *)data, buf, DFNT_FLOAT,
  2522.                   userNT, outNT, numfloats, error);
  2523.             if ((ret = DFwrite(Sdfile, buf, writesize)) < 0) {
  2524.             DFIfreespace(buf);
  2525.             return(DFIerr(Sdfile));
  2526.             }
  2527.         }
  2528.         DFIfreespace(buf);
  2529.         }
  2530.         else {
  2531.         for (i=0; i<j; i++, data+=stride)
  2532.             if ((ret = DFwrite(Sdfile, (char *)data, writesize)) < 0)
  2533.             return(DFIerr(Sdfile));
  2534.         }
  2535.     }
  2536.     } else {            /* transposed */
  2537.     numfloats = windims[leastsig];
  2538.     writesize = numfloats * outNTsize;
  2539.  
  2540.     /* allocate 1 row buffers */
  2541.     if (!convert) buf = NULL;
  2542.     else {
  2543.         if ((buf = DFIgetspace((unsigned) writesize)) == NULL) {
  2544.         DFerror = DFE_NOSPACE;
  2545.         return(-1);
  2546.         }
  2547.     }
  2548.     gatherbuf = (float32 *)DFIgetspace((unsigned) numfloats
  2549.                        *sizeof(float32));
  2550.     offset = (int32 *) DFIgetspace((unsigned) 2 * rank * sizeof(int32));
  2551.     dimsleft = offset + rank;
  2552.     if (gatherbuf==NULL || offset==NULL) {
  2553.         DFIfreespace(buf);
  2554.         DFIfreespace((char *)gatherbuf);
  2555.         DFIfreespace((char *)offset);
  2556.         DFerror = DFE_NOSPACE;
  2557.         return(-1);
  2558.     }
  2559.  
  2560.     /* initialize the dimension counter */
  2561.     for (i=0; i<rank; i++)
  2562.         dimsleft[i] = windims[i];
  2563.  
  2564.     datap = data;
  2565.     done = 0;
  2566.     outbufp = convert ? buf : (char *)gatherbuf;
  2567.  
  2568.     /* -- now write out the data */
  2569.  
  2570.     /* compute offsets in the source array */
  2571.     if (isfortran)
  2572.         for (i=0, offset[0]=1; i<rank-1; i++)
  2573.         offset[i+1] = offset[i]*dims[i];
  2574.     else
  2575.         for (i=rank-1, offset[i]=1; i > 0; i--)
  2576.         offset[i-1] = offset[i]*dims[i];
  2577.     stride = offset[leastsig];
  2578.  
  2579.     /* step thru the data on a row by row basis */
  2580.     do {
  2581.         /* gather the elements of one row together */
  2582. #ifdef UNICOS
  2583. #pragma ivdep
  2584. #endif
  2585.         for (dp=datap, i=0; i<numfloats; i++) {
  2586.         gatherbuf[i] = *dp;
  2587.         dp += stride;
  2588.         }
  2589.  
  2590.         /* convert and write the row */
  2591.         if (convert)
  2592.         DFconvert((char *)gatherbuf, buf, DFNT_FLOAT,
  2593.               userNT, outNT, numfloats, error);
  2594.         ret = DFwrite(Sdfile, outbufp, writesize);
  2595.  
  2596.         /* find the start of the next row */
  2597.         if (Fortorder) {
  2598.         for (i=1; i<rank; i++) {
  2599.             if (--dimsleft[i] > 0) {
  2600.             /* move to next element in the current dimension */
  2601.             datap += offset[i];
  2602.             break;
  2603.             }
  2604.             else {    /* move back to the beginning of dimension i */
  2605.             datap -= offset[i]*(dimsleft[i] = windims[i]);
  2606.             datap += offset[i];
  2607.             if (i == rank-1) done = 1;
  2608.             }
  2609.         }
  2610.         } else {        /* !Fortorder */
  2611.         for (i=rank-2; i>=0; i--) {
  2612.             if (--dimsleft[i] > 0) {
  2613.             /* move to next element in the current dimension */
  2614.             datap += offset[i];
  2615.             break;
  2616.             }
  2617.             else {    /* move back to the beginning of dimension i */
  2618.             datap -= offset[i]*(dimsleft[i] = windims[i]);
  2619.             datap += offset[i];
  2620.             if (i == 0) done = 1;
  2621.             }
  2622.         }
  2623.         }
  2624.     } while (!done && ret >= 0 && rank > 1);
  2625.  
  2626.     DFIfreespace(buf);
  2627.     DFIfreespace((char *)gatherbuf);
  2628.     DFIfreespace((char *)offset);
  2629.     }
  2630.  
  2631.     return(ret>=0 ? 0 : -1);
  2632. }
  2633.  
  2634. /******************************************************************************/
  2635. /*----------------------- Internal routines ---------------------------------*/
  2636. /******************************************************************************/
  2637.  
  2638. /*-----------------------------------------------------------------------------
  2639.  * Name:    dsisdas_
  2640.  * Purpose: Set label, unit and format for displaying subsequent SDGs
  2641.  * Inputs:  label: label to be used to describe data
  2642.  *          unit: unit corresponding to data values
  2643.  *          format: format to be used in displaying data values
  2644.  *          coordsys: type of coordinate system
  2645.  *          isfortran: 1 if called from Fortran, 0 if called from C
  2646.  *          llabel, lunit, lformat, lcoordsys: lengths of correspoding strings
  2647.  * Globals: Writesdg, Ref
  2648.  * Returns: 0 on success, -1 on failure with DFerror set
  2649.  * Users:   HDF users, utilities, other routines
  2650.  * Invokes: none
  2651.  * Method:  Stores values in global structure Writesdg
  2652.  * Remarks: none
  2653.  *---------------------------------------------------------------------------*/
  2654.  
  2655.     FCALLKEYW int
  2656. dsisdas_(label, unit, format, coordsys, isfortran, llabel, lunit,
  2657.      lformat, lcoordsys)
  2658.     char *label, *unit, *format, *coordsys;
  2659.     int *isfortran;
  2660.     int *llabel, *lunit, *lformat, *lcoordsys;
  2661. {
  2662.  
  2663.     int luf;                /* takes values LABEL, UNIT, FORMAT in succession */
  2664.     char *lufp;             /* points to label, unit, format in succession */
  2665.     int luflen;             /* length of luf */
  2666.  
  2667.     DFerror = DFE_NOERROR;
  2668.  
  2669.     for (luf=LABEL; luf<=FORMAT; luf++) {
  2670.     /* set lufp to point to label etc. as apppropriate */
  2671.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  2672.         if (*isfortran)
  2673.             luflen = (luf==LABEL) ? *llabel : (luf==UNIT) ? *lunit : *lformat;
  2674.         else luflen = strlen(lufp);
  2675.  
  2676.     /* free space if allocated */
  2677.         Writesdg.dataluf[luf] = DFIfreespace(Writesdg.dataluf[luf]);
  2678.  
  2679.     /* copy string */
  2680.         if (lufp) {
  2681.             Writesdg.dataluf[luf] = DFIgetspace((unsigned) luflen+1);
  2682.             if (Writesdg.dataluf[luf]==NULL) return(-1);
  2683.             strncpy(Writesdg.dataluf[luf], lufp, luflen);
  2684.             Writesdg.dataluf[luf][luflen] = '\0';
  2685.         }
  2686.     }
  2687.  
  2688.     Writesdg.coordsys = DFIfreespace(Writesdg.coordsys);
  2689.     luflen = *isfortran ? *lcoordsys : strlen(coordsys);
  2690.  
  2691.     if (coordsys) {
  2692.         Writesdg.coordsys = DFIgetspace((unsigned) luflen+1);
  2693.         if (Writesdg.coordsys==NULL) return(-1);
  2694.         strncpy(Writesdg.coordsys, coordsys, luflen);
  2695.         Writesdg.coordsys[luflen] = '\0';
  2696.     }
  2697.  
  2698.     /* indicate that label, unit, format and coordsys info modified */
  2699.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = Ref.coordsys = 0;
  2700.  
  2701.     return(0);
  2702. }
  2703.  
  2704.  
  2705. /*-----------------------------------------------------------------------------
  2706.  * Name:    dsisdis_
  2707.  * Purpose: For the given dimension, set label, unit, format
  2708.  *          This routine needs to be called once for each dimension whose 
  2709.  *          values the user wants to set.
  2710.  * Inputs:  dim: the dimension that this info applies to
  2711.  *          label: label to be used to describe this dimension
  2712.  *          unit: units for dimension
  2713.  *          format: format to be used in displaying
  2714.  *          isfortran: 1 if called from Fortran, 0 otherwise
  2715.  *          llabel, lunit, lformat: lengths of corresponding strings
  2716.  * Globals: Writesdg, Ref
  2717.  * Returns: 0 on success, -1 on failure with DFerror set
  2718.  * Users:   HDF users, utilities, other routines
  2719.  * Invokes: none
  2720.  * Method:  Stores values in global structure Writesdg
  2721.  *---------------------------------------------------------------------------*/
  2722.  
  2723.     FCALLKEYW int
  2724. dsisdis_(dim, label, unit, format, isfortran, llabel, lunit, lformat)
  2725.     int *dim;
  2726.     char    *label, *unit, *format;
  2727.     int *isfortran;
  2728.     int *llabel, *lunit, *lformat;
  2729. {
  2730.  
  2731.     int i, rdim;
  2732.     int luf;                /* takes values LABEL, UNIT, FORMAT in succession */
  2733.     char *lufp;             /* points to label, unit, format in succession */
  2734.     int luflen;             /* length of lufp */
  2735.  
  2736.     DFerror = DFE_NOERROR;
  2737.  
  2738.     rdim = *dim-1;      /* translate from 1 to 0 origin */
  2739.  
  2740.     if ((rdim>=Writesdg.rank) || (rdim<0)) {
  2741.         DFerror = DFE_BADDIM;
  2742.         return(-1);
  2743.     }
  2744.  
  2745.     for (luf=LABEL; luf<=FORMAT; luf++) {
  2746.             /* set lufp to point to label etc. as apppropriate */
  2747.         lufp = (luf==LABEL) ? label : (luf==UNIT) ? unit : format;
  2748.         if (*isfortran)
  2749.             luflen = (luf==LABEL) ? *llabel : (luf==UNIT) ? *lunit : *lformat;
  2750.         else luflen = strlen(lufp);
  2751.  
  2752.             /* allocate space if necessary */
  2753.         if (!Writesdg.dimluf[luf]) {
  2754.             Writesdg.dimluf[luf] =
  2755.                 (char **) DFIgetspace((unsigned)Writesdg.rank * sizeof(char *));
  2756.             if (Writesdg.dimluf[luf]==NULL) return(-1);
  2757.             for (i=0; i<Writesdg.rank; i++) /* set allocated pointers to NULL */
  2758.                 Writesdg.dimluf[luf][i] = NULL;
  2759.         }
  2760.  
  2761.     /* free string space if allocated */
  2762.         Writesdg.dimluf[luf][rdim] = DFIfreespace(Writesdg.dimluf[luf][rdim]);
  2763.  
  2764.     /* copy string */
  2765.         if (lufp) {
  2766.             Writesdg.dimluf[luf][rdim] = DFIgetspace((unsigned) luflen+1);
  2767.             if (Writesdg.dimluf[luf][rdim]==NULL) return(-1);
  2768.             strncpy(Writesdg.dimluf[luf][rdim], lufp, luflen);
  2769.             Writesdg.dimluf[luf][rdim][luflen] = '\0';
  2770.         }
  2771.     }
  2772.  
  2773.     /* Indicate that this info has not been written to file */
  2774.     Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = 0;
  2775.  
  2776.     return(0);
  2777. }
  2778.  
  2779.