ncdf4a13/ncdump/dumplib.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *   Copyright 1993, University Corporation for Atmospheric Research
00003  *   See netcdf/README file for copying and redistribution conditions.
00004  *   $Header: /upc/share/CVS/netcdf-3/ncdump/dumplib.c,v 1.8 2005/11/16 02:29:14 russ Exp $
00005  *********************************************************************/
00006 
00007 /*
00008  * We potentially include <stdarg.h> before <stdio.h> in order to obtain a
00009  * definition for va_list from the GNU C compiler.
00010  */
00011 #include <stdarg.h>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <string.h>
00015 
00016 #include "netcdf.h"
00017 #include "dumplib.h"
00018 #include "ncdump.h"
00019 
00020 static char* has_c_format_att(int ncid, int varid);
00021 static vnode* newvnode(void);
00022 
00023 int float_precision_specified = 0; /* -p option specified float precision */
00024 int double_precision_specified = 0; /* -p option specified double precision */
00025 char float_var_fmt[] = "%.NNg";
00026 char double_var_fmt[] = "%.NNg";
00027 char float_att_fmt[] = "%#.NNgf";
00028 char double_att_fmt[] = "%#.NNg";
00029 
00030 /*
00031  * Print error message to stderr and exit
00032  */
00033 void
00034 error(const char *fmt, ...)
00035 {
00036     va_list args ;
00037 
00038     (void) fprintf(stderr,"%s: ", progname);
00039     va_start(args, fmt) ;
00040     (void) vfprintf(stderr,fmt,args) ;
00041     va_end(args) ;
00042 
00043     (void) fprintf(stderr, "\n") ;
00044     (void) fflush(stderr);      /* to ensure log files are current */
00045     exit(EXIT_FAILURE);
00046 }
00047 
00048 void *
00049 emalloc (                       /* check return from malloc */
00050         size_t size)
00051 {
00052     void   *p;
00053 
00054     p = (void *) malloc (size);
00055     if (p == 0) {
00056         error ("out of memory\n");
00057     }
00058     return p;
00059 }
00060 
00061 #define LINEPIND        "    "  /* indent of continued lines */
00062 
00063 static int linep;
00064 static int max_line_len;
00065 
00066 void
00067 set_indent(int in)
00068 {
00069     linep = in;
00070 }
00071 
00072 
00073 void
00074 set_max_len(int len)
00075 {
00076     max_line_len = len-2;
00077 }
00078 
00079 
00080 void
00081 lput(const char *cp)
00082 {
00083     size_t nn = strlen(cp);
00084 
00085     if (nn+linep > max_line_len && nn > 2) {
00086         (void) fputs("\n", stdout);
00087         (void) fputs(LINEPIND, stdout);
00088         linep = (int)strlen(LINEPIND);
00089     }
00090     (void) fputs(cp,stdout);
00091     linep += nn;
00092 }
00093 
00094 /* In case different formats specified with -d option, set them here. */
00095 void
00096 set_formats(int float_digits, int double_digits)
00097 {
00098     (void) sprintf(float_var_fmt, "%%.%dg", float_digits);
00099     (void) sprintf(double_var_fmt, "%%.%dg", double_digits);
00100     (void) sprintf(float_att_fmt, "%%#.%dgf", float_digits);
00101     (void) sprintf(double_att_fmt, "%%#.%dg", double_digits);
00102 }
00103 
00104 
00105 static char *
00106 has_c_format_att(
00107     int ncid,                   /* netcdf id */
00108     int varid                   /* variable id */
00109     )
00110 {
00111     nc_type cfmt_type;
00112     size_t cfmt_len;
00113 #define C_FMT_NAME      "C_format" /* name of C format attribute */
00114 #define MAX_CFMT_LEN    100     /* max length of C format attribute */
00115     static char cfmt[MAX_CFMT_LEN];
00116     
00117     /* we expect nc_inq_att to fail if there is no "C_format" attribute */
00118     int nc_stat = nc_inq_att(ncid, varid, "C_format", &cfmt_type, &cfmt_len);
00119 
00120     switch(nc_stat) {
00121     case NC_NOERR:
00122         if (cfmt_type == NC_CHAR && cfmt_len != 0 && cfmt_len < MAX_CFMT_LEN) {
00123             int nc_stat = nc_get_att_text(ncid, varid, "C_format", cfmt);
00124             if(nc_stat != NC_NOERR) {
00125                 fprintf(stderr, "Getting 'C_format' attribute %s\n", 
00126                         nc_strerror(nc_stat));
00127                 (void) fflush(stderr);
00128             }
00129             return &cfmt[0];
00130         }
00131         break;
00132     case NC_ENOTATT:
00133         break;
00134     default:
00135         fprintf(stderr, "Inquiring about 'C_format' attribute %s\n", 
00136                 nc_strerror(nc_stat));
00137         (void) fflush(stderr);
00138         break;
00139     }
00140     return 0;
00141 }
00142 
00143 
00144 /*
00145  * Determine print format to use for each value for this variable.  Use value
00146  * of attribute C_format if it exists, otherwise a sensible default.
00147  */
00148 const char *
00149 get_fmt(
00150      int ncid,                  /* netcdf id */
00151      int varid,                 /* variable id */
00152      nc_type type               /* netCDF data type */
00153      )
00154 {
00155     char *c_format_att;
00156 
00157     /* float or double precision specified with -p option overrides any
00158        C_format attribute value, so check for that first. */
00159 
00160     if (float_precision_specified && type == NC_FLOAT)
00161         return float_var_fmt;
00162 
00163     if (double_precision_specified && type == NC_DOUBLE)
00164         return double_var_fmt;
00165 
00166     /* If C_format attribute exists, return it */
00167     c_format_att = has_c_format_att(ncid, varid);
00168     if (c_format_att)
00169       return c_format_att;    
00170 
00171     /* Otherwise return sensible default. */
00172     switch (type) {
00173       case NC_BYTE:
00174         return "%d";
00175       case NC_CHAR:
00176         return "%s";
00177       case NC_SHORT:
00178         return "%d";
00179       case NC_INT:
00180         return "%d";
00181       case NC_FLOAT:
00182         return float_var_fmt;
00183       case NC_DOUBLE:
00184         return double_var_fmt;
00185       default:
00186         error("pr_vals: bad type");
00187     }
00188 
00189     return 0;
00190 }
00191 
00192 
00193 static vnode*
00194 newvnode(void)
00195 {
00196     vnode *newvp = (vnode*) emalloc(sizeof(vnode));
00197     return newvp;
00198 }
00199 
00200 
00201 /*
00202  * Get a new, empty variable list.
00203  */
00204 vnode*
00205 newvlist(void)
00206 {
00207     vnode *vp = newvnode();
00208 
00209     vp -> next = 0;
00210     vp -> id = -1;              /* bad id */
00211 
00212     return vp;
00213 }
00214 
00215 
00216 void
00217 varadd(vnode* vlist, int varid)
00218 {
00219     vnode *newvp = newvnode();
00220     
00221     newvp -> next = vlist -> next;
00222     newvp -> id = varid;
00223     vlist -> next = newvp;
00224 }
00225 
00226 
00227 /* 
00228  * return 1 if variable identified by varid is member of variable
00229  * list vlist points to.
00230  */
00231 int
00232 varmember(const vnode* vlist, int varid)
00233 {
00234     vnode *vp = vlist -> next;
00235 
00236     for (; vp ; vp = vp->next)
00237       if (vp->id == varid)
00238         return 1;
00239     return 0;    
00240 }
00241 
00242 
00243 /*
00244  * return 1 if varid identifies a coordinate variable
00245  * else return 0
00246  */
00247 int
00248 iscoordvar(int ncid, int varid)
00249 {
00250     int ndims;
00251     int dimid;
00252     ncdim_t *dims;
00253     int is_coord = 0;           /* true if variable is a coordinate variable */
00254     char varname[NC_MAX_NAME];
00255     int varndims;
00256 
00257     NC_CHECK( nc_inq_ndims(ncid, &ndims) );
00258     dims = (ncdim_t *) emalloc((ndims + 1) * sizeof(ncdim_t));
00259     for (dimid = 0; dimid < ndims; dimid++) {
00260         NC_CHECK( nc_inq_dimname(ncid, dimid, dims[dimid].name) );
00261     }
00262     NC_CHECK( nc_inq_varname(ncid, varid, varname) );
00263     NC_CHECK( nc_inq_varndims(ncid, varid, &varndims) );
00264    
00265     for (dimid = 0; dimid < ndims; dimid++) {
00266         if (strcmp(dims[dimid].name, varname) == 0 && varndims == 1) {
00267             is_coord = 1;
00268             break;
00269         }
00270     }
00271     free(dims);
00272     return is_coord;
00273 }
00274 
00275 
00276 /*
00277  * return 1 if varid identifies a record variable
00278  * else return 0
00279  */
00280 int
00281 isrecvar(int ncid, int varid)
00282 {
00283     int recdimid;
00284     int ndims;
00285     int is_recvar = 0;
00286     int *dimids;
00287 
00288     NC_CHECK( nc_inq_unlimdim(ncid, &recdimid) );
00289     NC_CHECK( nc_inq_varndims(ncid, varid, &ndims) );
00290     if (ndims > 0) {
00291         dimids = (int *) emalloc((ndims + 1) * sizeof(int));
00292         NC_CHECK( nc_inq_vardimid(ncid, varid, dimids) );
00293         /* TODO assumes only one unlimited dimension, but netcdf4 alllows multiple */
00294         if(dimids[0] == recdimid)
00295             is_recvar = 1;
00296         free(dimids);
00297     }
00298     return is_recvar;
00299 }

Generated on Thu Mar 16 18:10:13 2006 for nco by  doxygen 1.4.4