#include "../config.h" /*After much deliberation, it was decided NOT to Internationalize this file.*/ /* This module provides access routines to take an HDF file and return an HTML description of its contents. The function hdfGrokFile() will take a whole file and return stuff that can be seen at the "top level" (i.e. all datasets, all raster images and all Vgroups which are not contained within other Vgroups). The function hdfGrokReference() will return a description of what can be "seen" from a given location in the file. Typically, this will be how users can navigate their way through a forest of Vgroups. */ /* #define CHOUCK */ #ifdef HAVE_HDF #define HDF #if defined(__sgi) #define IRIS4 #endif #if defined(_IBMR2) #define IBM6000 #endif #if defined(sun) #define SUN #ifndef Void #define Void void #endif #endif #if defined(cray) #define UNICOS #endif #if defined(__alpha) #define DEC_ALPHA #endif #if defined(__hpux) #define HP9000 #endif /* VMS defines itself */ /* netCDF error toggle */ extern int ncopts; /* wanker */ extern char *use_this_url_instead; #ifndef DISABLE_TRACE extern int srcTrace; #endif #include "mfhdf.h" #include "mosaic.h" #include "HTML.h" /* for ImageInfo */ #ifdef HAVE_DTM #include "netdata.h" #endif #include /* make all in-lined images smaller than hdfImageSize X hdfImageSize */ #define hdfImageSize get_pref_int(eHDF_MAX_IMAGE_DIMENSION) /* limits on datasets and attribute counts to send into brief mode */ #define MAX_DATASET_DISPLAY get_pref_int(eHDF_MAX_DISPLAYED_DATASETS) #define MAX_ATTRIBUTE_DISPLAY get_pref_int(eHDF_MAX_DISPLAYED_ATTRIBUTES) /* if is HDF Power User then drop most of the supporting text */ #define POWER_USER get_pref_boolean(eHDF_POWER_USER) #define SHOW_URL FALSE static FILE * fp; static int brief; static char * my_url; #ifdef CHOUCK /* forward decls */ void hdfStartImage PROTO(()); void hdfEndImage PROTO(()); ImageInfo * hdfFetchImage PROTO((intn *bg)); void hdfXsds PROTO((char *name, int32 rank)); void hdfXvgroup PROTO((char *name, char *class, int32 count)); #endif /* CHOUCK */ /* return a string description of the number type */ char * #ifdef PROTOTYPE get_type(int32 nt) #else get_type(nt) int32 nt; #endif { switch(nt) { case DFNT_CHAR : return("8-bit characters"); case DFNT_INT8 : return("signed 8-bit integers"); case DFNT_UINT8 : return("unsigned 8-bit integers"); case DFNT_INT16 : return("signed 16-bit integers"); case DFNT_UINT16 : return("unsigned 8-bit integers"); case DFNT_INT32 : return("signed 32-bit integers"); case DFNT_UINT32 : return("unsigned 32-bit integers"); case DFNT_FLOAT32 : return("32-bit floating point numbers"); case DFNT_FLOAT64 : return("64-bit floating point numbers"); default : return("unknown number type"); } } /* get_type */ /* return a string dump of buffer */ /* FREES the incoming buffer !!!!!!!!!!!!!!!!!! */ char * #ifdef PROTOTYPE buffer_to_string(char * tbuff, int32 nt, int32 count) #else buffer_to_string(tbuff, nt, count) char * tbuff; int32 nt; int32 count; #endif { intn i; char * buffer; if(nt == DFNT_CHAR) { tbuff[count] = '\0'; return tbuff; } buffer = (char *) HDgetspace(80 * count); if(buffer == NULL) return NULL; buffer[0] = '\0'; switch(nt) { case DFNT_INT8 : case DFNT_UINT8 : sprintf(buffer, "%d", ((int8 *)tbuff)[0]); for(i = 1; i < count; i++) sprintf(buffer, "%s, %d", buffer, ((int8 *)tbuff)[i]); break; case DFNT_INT16 : case DFNT_UINT16 : sprintf(buffer, "%d", ((int16 *)tbuff)[0]); for(i = 1; i < count; i++) sprintf(buffer, "%s, %d", buffer, ((int16 *)tbuff)[i]); break; case DFNT_INT32 : case DFNT_UINT32 : sprintf(buffer, "%d", ((int32 *)tbuff)[0]); for(i = 1; i < count; i++) sprintf(buffer, "%s, %d", buffer, ((int32 *)tbuff)[i]); break; case DFNT_FLOAT32 : sprintf(buffer, "%f", ((float32 *)tbuff)[0]); for(i = 1; i < count; i++) sprintf(buffer, "%s, %f", buffer, ((float32 *)tbuff)[i]); break; case DFNT_FLOAT64 : sprintf(buffer, "%f", ((float64 *)tbuff)[0]); for(i = 1; i < count; i++) sprintf(buffer, "%s, %f", buffer, ((float64 *)tbuff)[i]); break; } HDfreespace((void *)tbuff); return buffer; } /* buffer_to_string */ /* return a string of the contents of an attribute */ char * #ifdef PROTOTYPE get_attribute(int32 id, int32 num, int32 nt, int32 count) #else get_attribute(id, num, nt, count) int32 id; int32 nt; int32 count; int32 num; #endif { char *tbuff; int32 dsize; int32 status; dsize = DFKNTsize(nt); if(dsize < 1) return NULL; tbuff = HDgetspace(dsize * (count + 1)); if(tbuff == NULL) return NULL; status = SDreadattr(id, num, tbuff); if(status == FAIL) return NULL; return(buffer_to_string(tbuff, nt, count)); } /* Print out the info for data sets in the file. This code is based on the multi-file interface of HDF 3.3 so it is able to decode netCDF files as well a strict HDF files */ #ifdef PROTOTYPE do_sds(char *fname) #else do_sds(fname) char *fname; #endif { int32 fid; int32 sds; int32 dsets, nattr, nattrs, status; int32 i, j; char name[512]; int32 nt, dimsizes[50], rank; intn count; /* SWP */ int k; char attr_name[MAX_NC_NAME]; int32 ant; int32 alen; char attr_data[MAX_NC_NAME]; char longname[MAX_NC_NAME]; fid = SDstart(fname, DFACC_RDONLY); if(fid == FAIL) return; status = SDfileinfo(fid, &dsets, &nattr); if(status == FAIL) return; if(dsets + nattr < 1) return; fprintf(fp, "

Datasets

\n"); /* see if enough to send us into brief mode */ if(dsets > MAX_DATASET_DISPLAY) brief = TRUE; fprintf(fp, "There are %d dataset%s and %d global attribute%s in this file.

\n", dsets, (dsets == 1 ? "" : "s"), nattr, (nattr == 1 ? "" : "s")); if(dsets) { fprintf(fp, "Available datasets :\n"); fprintf(fp, "

\n"); } if(nattr) { fprintf(fp, "Global attributes :\n"); fprintf(fp, "\n"); } SDend(fid); } /* do_sds */ /* If there are a lot of attributes we need to do them in a separate window That's what this function is for */ do_attributes(char *fname, int index) { char name[MAX_NC_NAME]; int32 nattrs, nt, dims[MAX_VAR_DIMS], rank, status; int32 fid, sds; intn j, count; fid = SDstart(fname, DFACC_RDONLY); if(fid == FAIL) return; sds = SDselect(fid, index); if(sds == FAIL) return; status = SDgetinfo(sds, name, &rank, dims, &nt, &nattrs); if(status == FAIL) return; if(nattrs) { fprintf(fp, "Dataset %s has the following attributes :\n", name); fprintf(fp, "\n"); } SDend(fid); } /* do_attributes */ /* Print out info about file ids and descriptions */ #ifdef PROTOTYPE do_fanns(int32 fid) #else do_fanns(fid) int32 fid; #endif { char *buffer; int32 status; int32 len; len = DFANgetfidlen(fid, 1); if(len > 0) { buffer = HDgetspace(len + 1); if(buffer == NULL) return; status = DFANgetfid(fid, buffer, len + 1, 1); if(status == FAIL) return; fprintf(fp, "This file has the following label: %s

\n", buffer); HDfreespace((void *)buffer); } len = DFANgetfdslen(fid, 1); if(len > 0) { buffer = HDgetspace(len + 1); if(buffer == NULL) return; status = DFANgetfds(fid, buffer, len, 1); if(status == FAIL) return; buffer[len] = '\0'; fprintf(fp, "Here is the file description:

%s
\n", buffer); HDfreespace((void *)buffer); } } /* do_fanns */ /* Print out labels and descriptions for this item */ #ifdef PROTOTYPE print_desc(char *fname, uint16 tag, uint16 ref, char *name) #else print_desc(fname, tag, ref, name) char *fname; uint16 tag, ref; char *name; #endif { int32 len, status; char *buffer; len = DFANgetlablen(fname, tag, ref); if(len > 0) { buffer = HDgetspace(len + 1); if(buffer == NULL) return; status = DFANgetlabel(fname, tag, ref, buffer, len + 1); if(status == SUCCEED) { name[0] = tolower(name[0]); if(POWER_USER) fprintf(fp, "Label : %s

\n", name, buffer); else fprintf(fp, "This %s was given the label : %s

\n", name, buffer); } HDfreespace((void *)buffer); } len = DFANgetdesclen(fname, tag, ref); if(len > 0) { buffer = HDgetspace(len + 1); if(buffer == NULL) return; status = DFANgetdesc(fname, tag, ref, buffer, len + 1); if(status == SUCCEED) { buffer[len] = '\0'; name[0] = toupper(name[0]); fprintf(fp, "%s description :

%s
\n", name, buffer); } HDfreespace((void *)buffer); } } /* print_desc */ /* print out the info for RIGSs in the file */ #ifdef PROTOTYPE do_rigs(char *fname) #else do_rigs(fname) char *fname; #endif { int32 count, i, ref, len; int32 status, w, h; intn ip; count = DFR8nimages(fname); if(count < 1) return; fprintf(fp, "

Images

\n"); if(count == 1) fprintf(fp, "There is 1 image in this file :\n"); else fprintf(fp, "There are %d images in this file :\n", count); fprintf(fp, "\n"); } /* do_rigs */ /* print out the info for Palettes in the file */ #ifdef PROTOTYPE do_pals(char *fname) #else do_pals(fname) char *fname; #endif { int32 count, i, ref, len; int32 status, w, h, ip; char pal[768]; count = DFPnpals(fname); if(count < 1) return; fprintf(fp, "

Palettes

\n"); if(count == 1) fprintf(fp, "There is 1 palette in this file :\n"); else fprintf(fp, "There are %d palettes in this file :\n", count); fprintf(fp, "\n"); } /* do_pals */ /* ------------------------------ dump_vdata ------------------------------ */ #ifdef PROTOTYPE dump_vdata(int32 fid, int32 ref) #else dump_vdata(fid, ref) int32 fid; int32 ref; #endif { int32 vd; char name[VSNAMELENMAX + 1], class[VSNAMELENMAX + 1]; char fields[(FIELDNAMELENMAX + 1) * VSFIELDMAX]; char padded_fields[(FIELDNAMELENMAX + 2) * VSFIELDMAX]; int32 intr, sz, cnt; int32 nfields, single; char * p, * q; vd = VSattach(fid, ref, "r"); if(vd == FAIL) return; VSinquire(vd, &cnt, &intr, fields, &sz, name); VSgetclass(vd, class); nfields = VFnfields(vd); single = FALSE; if((cnt == 1) && (nfields == 1)) single = TRUE; if(name[0] == '\0') sprintf(name, "[no name value]"); fprintf(fp, "
  • Vdata %s", name); if(class[0]) fprintf(fp, " of class %s", class); if(!single) fprintf(fp," contains %d record%s", cnt, (cnt == 1 ? "" : "s")); fprintf(fp,". \n"); for(p = fields, q = padded_fields; *p; p++, q++) { *q = *p; if(*q == ',') *(++q) = ' '; } *q = '\0'; fprintf(fp, "This Vdata contains the field%s %s\n", (nfields == 1 ? "" : "s"), padded_fields); /* if there is a single field with one value print out its values */ if(single) { uint8 *tbuff; /* Attempted bugfix -- added 1 -- marca, 10:52pm sep 23. */ tbuff = (uint8 *)HDgetspace(VFfieldisize(vd, 0) + 1); if(tbuff == NULL) return; VSsetfields(vd, fields); VSread(vd, tbuff, 1, 0); tbuff = buffer_to_string(tbuff, VFfieldtype(vd, 0), VFfieldorder(vd, 0)); if(tbuff) { fprintf(fp, ": %s", tbuff); HDfreespace((void *)tbuff); } } fprintf(fp, ". \n"); VSdetach(vd); } /* dump_vdata */ /* ------------------------------- dump_vg -------------------------------- */ /* Print out some HTML for the given Vgroup. If X is TRUE then call the functions to register the Vgroup in the hacked up image */ #ifdef PROTOTYPE dump_vg(int32 fid, int32 ref, int32 X) #else dump_vg(fid, ref, X) int32 fid; int32 ref; int32 X; #endif { int32 vg, count; char name[VSNAMELENMAX + 1], class[VSNAMELENMAX + 1]; vg = Vattach(fid, ref, "r"); if(vg == FAIL) return; Vgetname(vg, name); Vgetclass(vg, class); count = Vntagrefs(vg); if(name[0] == '\0') sprintf(name, "[no name value]"); if(class[0] == '\0') sprintf(class, "[no class value]"); if(count) fprintf(fp, "
  • Vgroup %s of class %s has %d element%s.\n", DFTAG_VG, ref, name, class, count, (count == 1 ? "" : "s")); else fprintf(fp, "
  • Vgroup %s of class %s is empty.\n", name, class); #ifdef CHOUCK if(X) hdfXvgroup(name, class, count); #endif /* CHOUCK */ Vdetach(vg); } /* dump_vg */ /* print out the info for Vgroups in the file If where is -1 print out info for the Vgroups we can see at the top level (i.e. Vgroups which are not contained within other Vgroups) If where is a positive number assume that is the ref of a Vgroup and report everything that is contained within that Vgroup. Because of poor code design, a lot of functionality will be duplicated when reporting on the contents of a Vgroup. Oh well. Will give someone something to do later.... I guess we know why this used to be called spank.c */ #ifdef PROTOTYPE do_vgs(int32 fid, char *fname, int32 where) #else do_vgs(fid, fname, where) int32 fid; char * fname; int32 where; #endif { int32 curr_ref, i, count, cnt; int32 curr_vg, vg, vg1, vd; int32 tag, ref, myref, intr, sz; int any; char name[VSNAMELENMAX], class[VSNAMELENMAX]; if(where == -1) { if(Hnumber(fid, DFTAG_VG) < 1) return; any = FALSE; /* looking for top level VGroups */ curr_ref = -1; while((curr_ref = Vgetid(fid, curr_ref)) != FAIL) { int top_level = TRUE; /* look through all other VGroups */ myref = -1; while(top_level && ((myref = Vgetid(fid, myref)) != FAIL)) { if(myref == curr_ref) continue; vg = Vattach(fid, myref, "r"); if(vg == FAIL) continue; count = Vntagrefs(vg); for(i = 0; i < count; i++) { Vgettagref(vg, i, &tag, &ref); if(tag == (int32) DFTAG_VG && ref == curr_ref) top_level = FALSE; } Vdetach(vg); } if(top_level) { if(any == FALSE) { fprintf(fp, "

    Vgroups

    \n"); fprintf(fp, "The following Vgroups are visible at this level of the file.\n"); fprintf(fp, "\n"); } else { /* looking for stuff inside a given VGroup */ vg = Vattach(fid, where, "r"); if(vg == FAIL) return; Vgetname(vg, name); Vgetclass(vg, class); count = Vntagrefs(vg); /* set up title and stuff */ fprintf(fp, "Vgroup: %s\n", name); fprintf(fp, "

    Vgroup %s

    \n", name); fprintf(fp, "This Vgroup is named %s and is of class %s.\n", name, class); if(count == 0) { Vdetach(vg); return; } if(count == 1) fprintf(fp, "There is %d element in Vgroup %s : \n", count, name); else fprintf(fp, "There are %d elements in Vgroup %s : \n", count, name); fprintf(fp, "\n"); Vdetach(vg); } } /* do_vgs */ /* Process Vdatas that are visible from the top level (i.e. they are not inside any Vgroups) */ #ifdef PROTOTYPE do_lone_vds(int32 fid) #else do_lone_vds(fid) int32 fid; #endif { int32 count, vd; int32 i, *ids, status; count = VSlone(fid, NULL, 0); if(count < 1) return; ids = (int32 *) HDgetspace(sizeof(int32) * count); if(ids == NULL) return; status = VSlone(fid, ids, count); if(status != count) return; fprintf(fp, "

    Vdatas

    \n"); fprintf(fp, "There are %d Vdatas visible at this level of the file.\n", count); fprintf(fp, "