00001
00002
00003
00004
00005
00006
00007 #include <config.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <ctype.h>
00012 #include <stdlib.h>
00013
00014 #include <netcdf.h>
00015 #include "ncdump.h"
00016 #include "dumplib.h"
00017 #include "vardata.h"
00018
00019 #define int64_t long long
00020 #define uint64_t unsigned long long
00021
00022 static void usage(void);
00023 static char* name_path(const char* path);
00024 static const char* type_name(nc_type type);
00025 static void tztrim(char* ss);
00026 static void pr_att_string(size_t len, const char* string);
00027 static void pr_att_vals(nc_type type, size_t len, const double* vals);
00028 static void pr_att(int ncid, int varid, const char *varname, int ia);
00029 static void pr_attx(int ncid, int varid, int ia);
00030 static void do_ncdump(const char* path, fspec_t* specp);
00031 static void do_ncdumpx(const char* path, fspec_t* specp);
00032 static void make_lvars(char* optarg, fspec_t* fspecp);
00033 static void set_sigdigs( const char* optarg);
00034 static void set_precision( const char *optarg);
00035 int main(int argc, char** argv);
00036
00037 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
00038
00039 char *progname;
00040
00041 static void
00042 usage(void)
00043 {
00044 #define USAGE "\
00045 [-c] Coordinate variable data and header information\n\
00046 [-h] Header information only, no data\n\
00047 [-v var1[,...]] Data for variable(s) <var1>,... only\n\
00048 [-b [c|f]] Brief annotations for C or Fortran indices in data\n\
00049 [-f [c|f]] Full annotations for C or Fortran indices in data\n\
00050 [-l len] Line length maximum in data section (default 80)\n\
00051 [-n name] Name for netCDF (default derived from file name)\n\
00052 [-p n[,n]] Display floating-point values with less precision\n\
00053 [-x] Output XML (NcML) instead of CDL\n\
00054 file Name of netCDF file\n"
00055
00056 (void) fprintf(stderr,
00057 "%s [-c|-h] [-v ...] [[-b|-f] [c|f]] [-l len] [-n name] [-p n[,n]] [-x] file\n%s",
00058 progname,
00059 USAGE);
00060
00061 (void) fprintf(stderr,
00062 "netcdf library version %s\n",
00063 nc_inq_libvers());
00064 exit(EXIT_FAILURE);
00065 }
00066
00067
00068
00069
00070
00071
00072 static char *
00073 name_path(const char *path)
00074 {
00075 const char *cp;
00076 char *new;
00077 char *sp;
00078
00079 #ifdef vms
00080 #define FILE_DELIMITER ']'
00081 #endif
00082 #ifdef MSDOS
00083 #define FILE_DELIMITER '\\'
00084 #endif
00085 #ifndef FILE_DELIMITER
00086 #define FILE_DELIMITER '/'
00087 #endif
00088 cp = strrchr(path, FILE_DELIMITER);
00089 if (cp == 0)
00090 cp = path;
00091 else
00092 cp++;
00093 new = (char *) emalloc((unsigned) (strlen(cp)+1));
00094 (void) strcpy(new, cp);
00095 if ((sp = strrchr(new, '.')) != NULL)
00096 *sp = '\0';
00097 return new;
00098 }
00099
00100
00101 static const char *
00102 type_name(nc_type type)
00103 {
00104 switch (type) {
00105 case NC_BYTE:
00106 return "byte";
00107 case NC_CHAR:
00108 return "char";
00109 case NC_SHORT:
00110 return "short";
00111 case NC_INT:
00112 return "int";
00113 case NC_FLOAT:
00114 return "float";
00115 case NC_DOUBLE:
00116 return "double";
00117 #ifdef USE_NETCDF4
00118 case NC_UBYTE:
00119 return "ubyte";
00120 case NC_USHORT:
00121 return "ushort";
00122 case NC_UINT:
00123 return "uint";
00124 case NC_INT64:
00125 return "long";
00126 case NC_UINT64:
00127 return "ulong";
00128 case NC_STRING:
00129 return "string";
00130 case NC_VLEN:
00131 return "vlen";
00132 case NC_OPAQUE:
00133 return "opaque";
00134 case NC_COMPOUND:
00135 return "compound";
00136 #endif
00137 default:
00138 error("type_name: bad type %d", type);
00139 return "bogus";
00140 }
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 static void
00150 tztrim(char *ss)
00151 {
00152 char *cp, *ep;
00153
00154 cp = ss;
00155 if (*cp == '-')
00156 cp++;
00157 while(isdigit((int)*cp) || *cp == '.')
00158 cp++;
00159 if (*--cp == '.')
00160 return;
00161 ep = cp+1;
00162 while (*cp == '0')
00163 cp--;
00164 cp++;
00165 if (cp == ep)
00166 return;
00167 while (*ep)
00168 *cp++ = *ep++;
00169 *cp = '\0';
00170 return;
00171 }
00172
00173
00174
00175
00176
00177 void pr_fmtvariant(int ncid, const char *path, const fspec_t* specp)
00178 {
00179 int format_version;
00180 char *format_str;
00181
00182 NC_CHECK( nc_inq_format(ncid, &format_version) );
00183 switch(format_version) {
00184 case NC_FORMAT_CLASSIC:
00185 format_str = "classic";
00186 break;
00187 case NC_FORMAT_64BIT:
00188 format_str = "64bit";
00189 break;
00190 case NC_FORMAT_NETCDF4:
00191 format_str = "netCDF4";
00192 break;
00193 case NC_FORMAT_NETCDF4_CLASSIC:
00194 format_str = " netCDF4_classic";
00195 break;
00196 default:
00197 error("unrecognized format: %s", path);
00198 break;
00199 }
00200 if (format_version == NC_FORMAT_CLASSIC) {
00201 Printf ("netcdf %s {\n", specp->name);
00202 } else {
00203 Printf ("netcdf %s { // format variant: %s \n", specp->name, format_str);
00204 }
00205 }
00206
00207
00208
00209
00210
00211 void pr_fmtvariantx(int ncid, const char *path)
00212 {
00213 int format_version;
00214 char *format_str;
00215
00216 NC_CHECK( nc_inq_format(ncid, &format_version) );
00217 switch(format_version) {
00218 case NC_FORMAT_CLASSIC:
00219 format_str = "classic";
00220 break;
00221 case NC_FORMAT_64BIT:
00222 format_str = "64bit";
00223 break;
00224 case NC_FORMAT_NETCDF4:
00225 format_str = "netCDF4";
00226 break;
00227 case NC_FORMAT_NETCDF4_CLASSIC:
00228 format_str = " netCDF4_classic";
00229 break;
00230 default:
00231 error("unrecognized format: %s", path);
00232 break;
00233 }
00234
00235 Printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<netcdf xmlns=\"http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2\" format=\"%s\" location=\"%s\">\n",
00236 format_str, path);
00237 }
00238
00239
00240
00241
00242
00243 static void
00244 pr_att_string(
00245 size_t len,
00246 const char *string
00247 )
00248 {
00249 int iel;
00250 const char *cp;
00251 const char *sp;
00252 unsigned char uc;
00253
00254 cp = string;
00255 Printf ("\"");
00256
00257 sp = cp + len - 1;
00258 while (len != 0 && *sp-- == '\0')
00259 len--;
00260 for (iel = 0; iel < len; iel++)
00261 switch (uc = *cp++ & 0377) {
00262 case '\b':
00263 Printf ("\\b");
00264 break;
00265 case '\f':
00266 Printf ("\\f");
00267 break;
00268 case '\n':
00269 Printf ("\\n\",\n\t\t\t\"");
00270 break;
00271 case '\r':
00272 Printf ("\\r");
00273 break;
00274 case '\t':
00275 Printf ("\\t");
00276 break;
00277 case '\v':
00278 Printf ("\\v");
00279 break;
00280 case '\\':
00281 Printf ("\\\\");
00282 break;
00283 case '\'':
00284 Printf ("\\'");
00285 break;
00286 case '\"':
00287 Printf ("\\\"");
00288 break;
00289 default:
00290 if (iscntrl(uc))
00291 Printf ("\\%03o",uc);
00292 else
00293 Printf ("%c",uc);
00294 break;
00295 }
00296 Printf ("\"");
00297
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 static void
00307 pr_att_vals(
00308 nc_type type,
00309 size_t len,
00310 const double *vals
00311 )
00312 {
00313 int iel;
00314 signed char sc;
00315 short ss;
00316 int ii;
00317 char gps[30];
00318 float ff;
00319 double dd;
00320 #ifdef USE_NETCDF4
00321 unsigned char uc;
00322 unsigned short us;
00323 unsigned int ui;
00324 int64_t i64;
00325 uint64_t ui64;
00326 #endif
00327 if (len == 0)
00328 return;
00329 for (iel = 0; iel < len-1; iel++) {
00330 switch (type) {
00331 case NC_BYTE:
00332 sc = (signed char) vals[iel] & 0377;
00333 Printf ("%db, ", sc);
00334 break;
00335 case NC_SHORT:
00336 ss = vals[iel];
00337 Printf ("%ds, ", ss);
00338 break;
00339 case NC_INT:
00340 ii = (int) vals[iel];
00341 Printf ("%d, ", ii);
00342 break;
00343 case NC_FLOAT:
00344 ff = vals[iel];
00345 (void) sprintf(gps, float_att_fmt, ff);
00346 tztrim(gps);
00347 Printf ("%s, ", gps);
00348 break;
00349 case NC_DOUBLE:
00350 dd = vals[iel];
00351 (void) sprintf(gps, double_att_fmt, dd);
00352 tztrim(gps);
00353 Printf ("%s, ", gps);
00354 break;
00355 #ifdef USE_NETCDF4
00356 case NC_UBYTE:
00357 uc = vals[iel];
00358 Printf ("%udub, ", uc);
00359 break;
00360 case NC_USHORT:
00361 us = vals[iel];
00362 Printf ("%huus, ", us);
00363 break;
00364 case NC_UINT:
00365 ui = vals[iel];
00366 Printf ("%u, ", ui);
00367 break;
00368 case NC_INT64:
00369 i64 = vals[iel];
00370 Printf ("%lldL, ", i64);
00371 break;
00372 case NC_UINT64:
00373 ui64 = vals[iel];
00374 Printf ("%lluUL, ", ui64);
00375 break;
00376 #endif
00377 default:
00378 error("pr_att_vals: bad type");
00379 }
00380 }
00381 switch (type) {
00382 case NC_BYTE:
00383 sc = (signed char) vals[iel] & 0377;
00384 Printf ("%db", sc);
00385 break;
00386 case NC_SHORT:
00387 ss = vals[iel];
00388 Printf ("%ds", ss);
00389 break;
00390 case NC_INT:
00391 ii = (int) vals[iel];
00392 Printf ("%d", ii);
00393 break;
00394 case NC_FLOAT:
00395 ff = vals[iel];
00396 (void) sprintf(gps, float_att_fmt, ff);
00397 tztrim(gps);
00398 Printf ("%s", gps);
00399 break;
00400 case NC_DOUBLE:
00401 dd = vals[iel];
00402 (void) sprintf(gps, double_att_fmt, dd);
00403 tztrim(gps);
00404 Printf ("%s", gps);
00405 break;
00406 #ifdef USE_NETCDF4
00407 case NC_UBYTE:
00408 uc = vals[iel];
00409 Printf ("%udub", uc);
00410 break;
00411 case NC_USHORT:
00412 us = vals[iel];
00413 Printf ("%huus", us);
00414 break;
00415 case NC_UINT:
00416 ui = vals[iel];
00417 Printf ("%u", ui);
00418 break;
00419 case NC_INT64:
00420 i64 = vals[iel];
00421 Printf ("%lldL", i64);
00422 break;
00423 case NC_UINT64:
00424 ui64 = vals[iel];
00425 Printf ("%lluUL", ui64);
00426 break;
00427 #endif
00428 default:
00429 error("pr_att_vals: bad type");
00430 }
00431 }
00432
00433 #ifndef HAVE_STRLCAT
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 size_t
00460 strlcat(char *dst, const char *src, size_t siz)
00461 {
00462 char *d = dst;
00463 const char *s = src;
00464 size_t n = siz;
00465 size_t dlen;
00466
00467
00468 while (n-- != 0 && *d != '\0')
00469 d++;
00470 dlen = d - dst;
00471 n = siz - dlen;
00472
00473 if (n == 0)
00474 return(dlen + strlen(s));
00475 while (*s != '\0') {
00476 if (n != 1) {
00477 *d++ = *s;
00478 n--;
00479 }
00480 s++;
00481 }
00482 *d = '\0';
00483
00484 return(dlen + (s - src));
00485 }
00486 #endif
00487
00488
00489
00490
00491
00492 static void
00493 pr_att_valsx(
00494 nc_type type,
00495 size_t len,
00496 const double *vals,
00497 char *attvals,
00498 size_t attvalslen
00499
00500
00501 )
00502 {
00503 int iel;
00504 double dd;
00505 int ii;
00506 #ifdef USE_NETCDF4
00507 unsigned int ui;
00508 int64_t i64;
00509 uint64_t ui64;
00510 #endif
00511
00512 attvals[0]='\0';
00513 if (len == 0)
00514 return;
00515 for (iel = 0; iel < len; iel++) {
00516 char gps[50];
00517 switch (type) {
00518 case NC_BYTE:
00519 case NC_SHORT:
00520 case NC_INT:
00521 ii = vals[iel];
00522 (void) sprintf(gps, "%d", ii);
00523 (void) strlcat(attvals, gps, attvalslen);
00524 (void) strlcat(attvals, iel < len-1 ? " " : "", attvalslen);
00525 break;
00526 #ifdef USE_NETCDF4
00527 case NC_UBYTE:
00528 case NC_USHORT:
00529 case NC_UINT:
00530 ui = vals[iel];
00531 (void) sprintf(gps, "%u", ui);
00532 (void) strlcat(attvals, gps, attvalslen);
00533 (void) strlcat(attvals, iel < len-1 ? " " : "", attvalslen);
00534 break;
00535 case NC_INT64:
00536
00537 i64 = vals[iel];
00538 (void) sprintf(gps, "%lld", i64);
00539 (void) strlcat(attvals, gps, attvalslen);
00540 (void) strlcat(attvals, iel < len-1 ? " " : "", attvalslen);
00541 break;
00542 case NC_UINT64:
00543
00544 ui64 = vals[iel];
00545 (void) sprintf(gps, "%llu", ui64);
00546 (void) strlcat(attvals, gps, attvalslen);
00547 (void) strlcat(attvals, iel < len-1 ? " " : "", attvalslen);
00548 break;
00549 #endif
00550 case NC_FLOAT:
00551 case NC_DOUBLE:
00552 dd = vals[iel];
00553 (void) sprintf(gps, double_att_fmt, dd);
00554 (void) strlcat(attvals, gps, attvalslen);
00555 (void) strlcat(attvals, iel < len-1 ? " " : "", attvalslen);
00556 break;
00557 default:
00558 error("pr_att_valsx: bad type");
00559 }
00560 }
00561 }
00562
00563
00564 static void
00565 pr_att(
00566 int ncid,
00567 int varid,
00568 const char *varname,
00569 int ia
00570 )
00571 {
00572 ncatt_t att;
00573
00574 NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
00575
00576 Printf ("\t\t%s:%s = ", varname, att.name);
00577
00578 NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) );
00579
00580 if (att.len == 0) {
00581 att.type = NC_CHAR;
00582 }
00583 switch (att.type) {
00584 case NC_CHAR:
00585 att.string = (char *) emalloc(att.len + 1);
00586 NC_CHECK( nc_get_att_text(ncid, varid, att.name, att.string ) );
00587 pr_att_string(att.len, att.string);
00588 free(att.string);
00589 break;
00590 default:
00591 att.vals = (double *) emalloc((att.len + 1) * sizeof(double));
00592 NC_CHECK( nc_get_att_double(ncid, varid, att.name, att.vals ) );
00593 pr_att_vals(att.type, att.len, att.vals);
00594 free(att.vals);
00595 break;
00596 }
00597 Printf (" ;\n");
00598 }
00599
00600
00601 static void
00602 pr_attx(
00603 int ncid,
00604 int varid,
00605 int ia
00606 )
00607 {
00608 ncatt_t att;
00609 char *attvals;
00610 int attvalslen = 0;
00611
00612 NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
00613 NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) );
00614
00615
00616
00617 switch (att.type) {
00618 case NC_CHAR:
00619 #ifdef USE_NETCDF4
00620
00621 case NC_STRING:
00622 #endif
00623 attvals = (char *) emalloc(att.len + 1);
00624 NC_CHECK( nc_get_att_text(ncid, varid, att.name, attvals ) );
00625 break;
00626 #ifdef USE_NETCDF4
00627
00628
00629
00630
00631
00632 #endif
00633
00634 default:
00635 att.vals = (double *) emalloc((att.len + 1) * sizeof(double));
00636 NC_CHECK( nc_get_att_double(ncid, varid, att.name, att.vals ) );
00637 attvalslen = 20*att.len;
00638 attvals = (char *) emalloc(attvalslen + 1);
00639 pr_att_valsx(att.type, att.len, att.vals, attvals, attvalslen);
00640 free(att.vals);
00641 free (attvals);
00642 break;
00643 }
00644
00645 Printf ("%s <attribute name=\"%s\" type=\"%s\" value=\"%s\" />\n",
00646 varid != NC_GLOBAL ? " " : "",
00647 att.name,
00648 att.type == NC_CHAR ? "String" : type_name(att.type),
00649 attvals);
00650 }
00651
00652
00653
00654 static void
00655 pr_shape(ncvar_t* varp, ncdim_t *dims)
00656 {
00657 char *shape;
00658 int shapelen = 0;
00659 int id;
00660
00661 if (varp->ndims == 0)
00662 return;
00663 for (id = 0; id < varp->ndims; id++) {
00664 shapelen += strlen(dims[varp->dims[id]].name) + 1;
00665 }
00666 shape = (char *) emalloc(shapelen);
00667 for (id = 0; id < varp->ndims; id++) {
00668 strlcat(shape, dims[varp->dims[id]].name, shapelen);
00669 strlcat(shape, id < varp->ndims-1 ? " " : "", shapelen);
00670 }
00671 Printf (" shape=\"%s\"", shape);
00672 free(shape);
00673 }
00674
00675
00676
00677
00678 static void
00679 do_ncdump_rec(int ncid, const char *path, fspec_t* specp)
00680 {
00681 int ndims;
00682 int nvars;
00683 int ngatts;
00684 int xdimid;
00685 int dimid;
00686 int varid;
00687 ncdim_t dims[NC_MAX_DIMS];
00688 size_t vdims[NC_MAX_DIMS];
00689 ncvar_t var;
00690 ncatt_t att;
00691 int id;
00692 int ia;
00693 int iv;
00694 vnode* vlist = 0;
00695 int nc_status;
00696
00697
00698
00699
00700
00701 if (specp->nlvars > 0) {
00702 vlist = newvlist();
00703 for (iv=0; iv < specp->nlvars; iv++) {
00704 NC_CHECK( nc_inq_varid(ncid, specp->lvars[iv], &varid) );
00705 varadd(vlist, varid);
00706 }
00707 }
00708
00709
00710 if (path)
00711 pr_fmtvariant(ncid, path, specp);
00712
00713
00714
00715
00716
00717 NC_CHECK( nc_inq(ncid, &ndims, &nvars, &ngatts, &xdimid) );
00718
00719 if (ndims > 0)
00720 Printf ("dimensions:\n");
00721 for (dimid = 0; dimid < ndims; dimid++) {
00722 NC_CHECK( nc_inq_dim(ncid, dimid, dims[dimid].name, &dims[dimid].size) );
00723 if (dimid == xdimid)
00724 Printf ("\t%s = %s ; // (%u currently)\n",dims[dimid].name,
00725 "UNLIMITED", (unsigned int)dims[dimid].size);
00726 else
00727 Printf ("\t%s = %u ;\n", dims[dimid].name, (unsigned int)dims[dimid].size);
00728 }
00729
00730 if (nvars > 0)
00731 Printf ("variables:\n");
00732
00733 for (varid = 0; varid < nvars; varid++) {
00734 NC_CHECK( nc_inq_varndims(ncid, varid, &var.ndims) );
00735 var.dims = (int *) emalloc((var.ndims + 1) * sizeof(int));
00736 NC_CHECK( nc_inq_var(ncid, varid, var.name, &var.type, 0,
00737 var.dims, &var.natts) );
00738 Printf ("\t%s %s", type_name(var.type), var.name);
00739 if (var.ndims > 0)
00740 Printf ("(");
00741 for (id = 0; id < var.ndims; id++) {
00742 Printf ("%s%s",
00743 dims[var.dims[id]].name,
00744 id < var.ndims-1 ? ", " : ")");
00745 }
00746 Printf (" ;\n");
00747
00748
00749 for (ia = 0; ia < var.natts; ia++)
00750 pr_att(ncid, varid, var.name, ia);
00751 free(var.dims);
00752 }
00753
00754
00755
00756 if (ngatts > 0)
00757 Printf ("\n// global attributes:\n");
00758 for (ia = 0; ia < ngatts; ia++)
00759 pr_att(ncid, NC_GLOBAL, "", ia);
00760
00761 if (! specp->header_only) {
00762 if (nvars > 0) {
00763 Printf ("data:\n");
00764 }
00765
00766 for (varid = 0; varid < nvars; varid++) {
00767
00768 if (specp->nlvars > 0 && ! varmember(vlist, varid))
00769 continue;
00770 NC_CHECK( nc_inq_varndims(ncid, varid, &var.ndims) );
00771 var.dims = (int *) emalloc((var.ndims + 1) * sizeof(int));
00772 NC_CHECK( nc_inq_var(ncid, varid, var.name, &var.type, 0,
00773 var.dims, &var.natts) );
00774
00775
00776
00777 if (specp->coord_vals && !iscoordvar(ncid,varid)) {
00778 continue;
00779 }
00780
00781
00782
00783 if (isrecvar(ncid, varid) && dims[xdimid].size == 0) {
00784 continue;
00785 }
00786
00787
00788 for (id = 0; id < var.ndims; id++)
00789 vdims[id] = dims[var.dims[id]].size;
00790 var.has_fillval = 1;
00791
00792
00793 nc_status = nc_inq_att(ncid,varid,_FillValue,&att.type,&att.len);
00794 if(nc_status == NC_NOERR &&
00795 att.type == var.type && att.len == 1) {
00796 if(var.type == NC_CHAR) {
00797 char fillc;
00798 NC_CHECK( nc_get_att_text(ncid, varid, _FillValue,
00799 &fillc ) );
00800 var.fillval = fillc;
00801 } else {
00802 NC_CHECK( nc_get_att_double(ncid, varid, _FillValue,
00803 &var.fillval) );
00804 }
00805 } else {
00806 switch (var.type) {
00807 case NC_BYTE:
00808
00809 var.has_fillval = 0;
00810 break;
00811 case NC_CHAR:
00812 var.fillval = NC_FILL_CHAR;
00813 break;
00814 case NC_SHORT:
00815 var.fillval = NC_FILL_SHORT;
00816 break;
00817 case NC_INT:
00818 var.fillval = NC_FILL_INT;
00819 break;
00820 case NC_FLOAT:
00821 var.fillval = NC_FILL_FLOAT;
00822 break;
00823 case NC_DOUBLE:
00824 var.fillval = NC_FILL_DOUBLE;
00825 break;
00826 default:
00827 break;
00828 }
00829 }
00830 if (vardata(&var, vdims, ncid, varid, specp) == -1) {
00831 error("can't output data for variable %s", var.name);
00832 NC_CHECK(
00833 nc_close(ncid) );
00834 if (vlist)
00835 free(vlist);
00836 return;
00837 }
00838 }
00839 }
00840
00841 #ifdef USE_NETCDF4
00842
00843
00844
00845 {
00846 int g, numgrps, *ncids, format;
00847 char group_name[NC_MAX_NAME + 1];
00848
00849
00850 if ((nc_status = nc_inq_format(ncid, &format)))
00851 error("can't get format");
00852
00853 if (format == NC_FORMAT_NETCDF4)
00854 {
00855
00856 if ((nc_status = nc_inq_grps(ncid, &numgrps, NULL)))
00857 error("can't read groups");
00858
00859
00860 if (!(ncids = malloc(numgrps * sizeof(int))))
00861 error("out of memory");
00862
00863
00864 nc_status = nc_inq_grps(ncid, NULL, ncids);
00865
00866
00867 for (g = 0; g < numgrps; g++)
00868 {
00869 if (nc_inq_grpname(ncids[g], group_name))
00870 error("can't find group's name");
00871 Printf ("\ngroup: %s {\n", group_name);
00872 do_ncdump_rec(ncids[g], NULL, specp);
00873 }
00874
00875 free(ncids);
00876 }
00877 }
00878 #endif
00879
00880 Printf ("}\n");
00881 if (vlist)
00882 free(vlist);
00883 }
00884
00885
00886 static void
00887 do_ncdump(const char *path, fspec_t* specp)
00888 {
00889 int nc_status;
00890 int ncid;
00891
00892 nc_status = nc_open(path, NC_NOWRITE, &ncid);
00893 if (nc_status != NC_NOERR) {
00894 error("%s: %s", path, nc_strerror(nc_status));
00895 }
00896
00897 do_ncdump_rec(ncid, path, specp);
00898 NC_CHECK( nc_close(ncid) );
00899 }
00900
00901 static void
00902 do_ncdumpx(const char *path, fspec_t* specp)
00903 {
00904 int ndims;
00905 int nvars;
00906 int ngatts;
00907 int xdimid;
00908 int dimid;
00909 int varid;
00910 ncdim_t dims[NC_MAX_DIMS];
00911 size_t vdims[NC_MAX_DIMS];
00912 ncvar_t var;
00913 ncatt_t att;
00914 int id;
00915 int ia;
00916 int iv;
00917 int ncid;
00918 vnode* vlist = 0;
00919 int nc_status;
00920
00921 nc_status = nc_open(path, NC_NOWRITE, &ncid);
00922 if (nc_status != NC_NOERR) {
00923 error("%s: %s", path, nc_strerror(nc_status));
00924 }
00925
00926
00927
00928
00929 if (specp->nlvars > 0) {
00930 vlist = newvlist();
00931 for (iv=0; iv < specp->nlvars; iv++) {
00932 NC_CHECK( nc_inq_varid(ncid, specp->lvars[iv], &varid) );
00933 varadd(vlist, varid);
00934 }
00935 }
00936
00937
00938 pr_fmtvariantx(ncid, path);
00939
00940
00941
00942
00943
00944 NC_CHECK( nc_inq(ncid, &ndims, &nvars, &ngatts, &xdimid) );
00945
00946 for (dimid = 0; dimid < ndims; dimid++) {
00947 NC_CHECK( nc_inq_dim(ncid, dimid, dims[dimid].name, &dims[dimid].size) );
00948 if (dimid == xdimid)
00949 Printf(" <dimension name=\"%s\" length=\"%d\" isUnlimited=\"true\" />\n",
00950 dims[dimid].name, (int)dims[dimid].size);
00951 else
00952 Printf (" <dimension name=\"%s\" length=\"%d\" />\n",
00953 dims[dimid].name, (int)dims[dimid].size);
00954 }
00955
00956
00957 for (ia = 0; ia < ngatts; ia++)
00958 pr_attx(ncid, NC_GLOBAL, ia);
00959
00960
00961 for (varid = 0; varid < nvars; varid++) {
00962 NC_CHECK( nc_inq_varndims(ncid, varid, &var.ndims) );
00963 var.dims = (int *) emalloc((var.ndims + 1) * sizeof(int));
00964 NC_CHECK( nc_inq_var(ncid, varid, var.name, &var.type, 0,
00965 var.dims, &var.natts) );
00966 Printf (" <variable name=\"%s\"", var.name);
00967 pr_shape(&var, dims);
00968
00969
00970
00971
00972
00973 if (var.natts == 0) {
00974 if (
00975
00976 (specp->header_only) ||
00977
00978 (specp->nlvars > 0 && !varmember(vlist, varid)) ||
00979
00980 (specp->coord_vals && !iscoordvar(ncid, varid)) ||
00981
00982 (isrecvar(ncid,varid) && dims[xdimid].size == 0)
00983 ) {
00984 Printf (" type=\"%s\" />\n", type_name(var.type));
00985 continue;
00986 }
00987 }
00988
00989
00990 Printf (" type=\"%s\">\n", type_name(var.type));
00991
00992
00993 for (ia = 0; ia < var.natts; ia++) {
00994 pr_attx(ncid, varid, ia);
00995 }
00996 if (! specp->header_only) {
00997
00998 if (specp->nlvars > 0 && ! varmember(vlist, varid)) {
00999 continue;
01000 }
01001
01002 if (specp->coord_vals) {
01003
01004 if (!iscoordvar(ncid, varid)) {
01005 continue;
01006 }
01007 }
01008
01009
01010
01011
01012
01013 if (var.ndims == 0
01014 || var.dims[0] != xdimid
01015 || dims[xdimid].size != 0) {
01016
01017
01018 for (id = 0; id < var.ndims; id++)
01019 vdims[id] = dims[var.dims[id]].size;
01020 var.has_fillval = 1;
01021
01022
01023 nc_status = nc_inq_att(ncid,varid,_FillValue,&att.type,&att.len);
01024 if(nc_status == NC_NOERR &&
01025 att.type == var.type && att.len == 1) {
01026 if(var.type == NC_CHAR) {
01027 char fillc;
01028 NC_CHECK( nc_get_att_text(ncid, varid, _FillValue,
01029 &fillc ) );
01030 var.fillval = fillc;
01031 } else {
01032 NC_CHECK( nc_get_att_double(ncid, varid, _FillValue,
01033 &var.fillval) );
01034 }
01035 } else {
01036 switch (var.type) {
01037 case NC_BYTE:
01038
01039 var.has_fillval = 0;
01040 break;
01041 case NC_CHAR:
01042 var.fillval = NC_FILL_CHAR;
01043 break;
01044 case NC_SHORT:
01045 var.fillval = NC_FILL_SHORT;
01046 break;
01047 case NC_INT:
01048 var.fillval = NC_FILL_INT;
01049 break;
01050 case NC_FLOAT:
01051 var.fillval = NC_FILL_FLOAT;
01052 break;
01053 case NC_DOUBLE:
01054 var.fillval = NC_FILL_DOUBLE;
01055 break;
01056 default:
01057 break;
01058 }
01059 }
01060 if (vardatax(&var, vdims, ncid, varid, specp) == -1) {
01061 error("can't output data for variable %s", var.name);
01062 NC_CHECK(nc_close(ncid) );
01063 if (vlist)
01064 free(vlist);
01065 return;
01066 }
01067 }
01068 }
01069 Printf (" </variable>\n");
01070 }
01071
01072 Printf ("</netcdf>\n");
01073 NC_CHECK(
01074 nc_close(ncid) );
01075 if (vlist)
01076 free(vlist);
01077 }
01078
01079
01080 static void
01081 make_lvars(char *optarg, fspec_t* fspecp)
01082 {
01083 char *cp = optarg;
01084 int nvars = 1;
01085 char ** cpp;
01086
01087
01088 fspecp->nlvars = 1;
01089 while (*cp++)
01090 if (*cp == ',')
01091 nvars++;
01092
01093 fspecp->lvars = (char **) emalloc(nvars * sizeof(char*));
01094
01095 cpp = fspecp->lvars;
01096
01097 for (cp = strtok(optarg, ",");
01098 cp != NULL;
01099 cp = strtok((char *) NULL, ",")) {
01100
01101 *cpp = (char *) emalloc(strlen(cp) + 1);
01102 strcpy(*cpp, cp);
01103 cpp++;
01104 }
01105 fspecp->nlvars = nvars;
01106 }
01107
01108
01109
01110
01111
01112
01113 static void
01114 set_sigdigs(const char *optarg)
01115 {
01116 char *ptr1 = 0;
01117 char *ptr2 = 0;
01118 int flt_digits = FLT_DIGITS;
01119 int dbl_digits = DBL_DIGITS;
01120
01121 if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',')
01122 flt_digits = (int)strtol(optarg, &ptr1, 10);
01123
01124 if (flt_digits < 1 || flt_digits > 20) {
01125 error("unreasonable value for float significant digits: %d",
01126 flt_digits);
01127 }
01128 if (*ptr1 == ',')
01129 dbl_digits = (int)strtol(ptr1+1, &ptr2, 10);
01130 if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) {
01131 error("unreasonable value for double significant digits: %d",
01132 dbl_digits);
01133 }
01134 set_formats(flt_digits, dbl_digits);
01135 }
01136
01137
01138
01139
01140
01141
01142
01143 static void
01144 set_precision(const char *optarg)
01145 {
01146 char *ptr1 = 0;
01147 char *ptr2 = 0;
01148 int flt_digits = FLT_DIGITS;
01149 int dbl_digits = DBL_DIGITS;
01150
01151 if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') {
01152 flt_digits = (int)strtol(optarg, &ptr1, 10);
01153 float_precision_specified = 1;
01154 }
01155
01156 if (flt_digits < 1 || flt_digits > 20) {
01157 error("unreasonable value for float significant digits: %d",
01158 flt_digits);
01159 }
01160 if (*ptr1 == ',') {
01161 dbl_digits = (int) strtol(ptr1+1, &ptr2, 10);
01162 double_precision_specified = 1;
01163 }
01164 if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20) {
01165 error("unreasonable value for double significant digits: %d",
01166 dbl_digits);
01167 }
01168 set_formats(flt_digits, dbl_digits);
01169 }
01170
01171
01172 int
01173 main(int argc, char *argv[])
01174 {
01175 extern int optind;
01176 extern int opterr;
01177 extern char *optarg;
01178 static fspec_t fspec =
01179 {
01180 0,
01181 false,
01182 false,
01183 false,
01184 false,
01185 LANG_C,
01186 0,
01187 0
01188 };
01189 int c;
01190 int i;
01191 int max_len = 80;
01192 int nameopt = 0;
01193 boolean xml_out = false;
01194
01195 opterr = 1;
01196 progname = argv[0];
01197 set_formats(FLT_DIGITS, DBL_DIGITS);
01198
01199 while ((c = getopt(argc, argv, "b:cf:hl:n:v:d:p:x")) != EOF)
01200 switch(c) {
01201 case 'h':
01202 fspec.header_only = true;
01203 break;
01204 case 'c':
01205 fspec.coord_vals = true;
01206 break;
01207 case 'n':
01208
01209
01210
01211 fspec.name = optarg;
01212 nameopt = 1;
01213 break;
01214 case 'b':
01215 fspec.brief_data_cmnts = true;
01216 switch (tolower(optarg[0])) {
01217 case 'c':
01218 fspec.data_lang = LANG_C;
01219 break;
01220 case 'f':
01221 fspec.data_lang = LANG_F;
01222 break;
01223 default:
01224 error("invalid value for -b option: %s", optarg);
01225 }
01226 break;
01227 case 'f':
01228 fspec.full_data_cmnts = true;
01229 switch (tolower(optarg[0])) {
01230 case 'c':
01231 fspec.data_lang = LANG_C;
01232 break;
01233 case 'f':
01234 fspec.data_lang = LANG_F;
01235 break;
01236 default:
01237 error("invalid value for -f option: %s", optarg);
01238 }
01239 break;
01240 case 'l':
01241 max_len = (int) strtol(optarg, 0, 0);
01242 if (max_len < 10) {
01243 error("unreasonably small line length specified: %d", max_len);
01244 }
01245 break;
01246 case 'v':
01247
01248 make_lvars (optarg, &fspec);
01249 break;
01250 case 'd':
01251 set_sigdigs(optarg);
01252 break;
01253 case 'p':
01254 set_precision(optarg);
01255 break;
01256 case 'x':
01257 xml_out = true;
01258 break;
01259 case '?':
01260 usage();
01261 break;
01262 }
01263
01264 set_max_len(max_len);
01265
01266 argc -= optind;
01267 argv += optind;
01268
01269 i = 0;
01270
01271 do {
01272 if (!nameopt)
01273 fspec.name = name_path(argv[i]);
01274 if (argc > 0) {
01275 if (xml_out) {
01276 do_ncdumpx(argv[i], &fspec);
01277 } else {
01278 do_ncdump(argv[i], &fspec);
01279 }
01280 }
01281 } while (++i < argc);
01282 #ifdef vms
01283 exit(EXIT_SUCCESS);
01284 #else
01285 return EXIT_SUCCESS;
01286 #endif
01287 }