home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / plotting / imagetoo / imagetl1.lha / Imagetool / HDF / dfsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-20  |  91.1 KB  |  2,773 lines

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