diff --git a/ChangeLog b/ChangeLog
index e9c44ad794106924d04d6de78a17ec37029c2f1c..1497b64429eb72c8393f9839cc7150a7dbd1db66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,25 @@
-2016-06-??  Uwe Schulzweida
+2016-08-01  Uwe Schulzweida
+
+	* grb, grb2 write: added support for projection CDI_PROJ_RLL
+	* grb, grb2, ieg read: added support for projection CDI_PROJ_RLL
+
+2016-07-30  Uwe Schulzweida
+
+	* ieg write: added support for projection CDI_PROJ_RLL
+
+2016-07-28  Uwe Schulzweida
+
+	* iegWriteVarSliceDP: does not work (bug fix)
+
+2016-07-02  Uwe Schulzweida
+
+	* streamOpenAppend: call to gribContainersNew() missing (bug fix) [Bug #6944]
+
+2016-06-17  Uwe Schulzweida
+
+	* netCDF4: added support for attribute type NC_BYTE, NC_UBYTE, NC_USHORT and NC_UINT
+
+2016-06-10  Uwe Schulzweida
 
 	* Version 1.7.2 released
 
diff --git a/Makefile.in b/Makefile.in
index 2639d34bde9936c847829c430476bf27ba135b48..d48da22c245fd13e195dff256ab8fe4f4f1c3d6b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -293,11 +293,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -321,7 +319,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -403,7 +400,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/Obsolate_functions b/Obsolate_functions
new file mode 100644
index 0000000000000000000000000000000000000000..2ba106352f1d46e9658d4bac7a94a577f5eee149
--- /dev/null
+++ b/Obsolate_functions
@@ -0,0 +1,12 @@
+gridDefXname(gridID, xname)         -> cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname)
+gridDefXlongname(gridID, xlongname) -> cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname)
+gridDefXunits(gridID, xunits)       -> cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits)
+gridDefYname(gridID, yname)         -> cdiGridDefKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname)
+gridDefYlongname(gridID, ylongname) -> cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname)
+gridDefYunits(gridID, yunits)       -> cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits)
+gridInqXname(gridID, xname)         -> cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname)
+gridInqXlongname(gridID, xlongname) -> cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname)
+gridInqXunits(gridID, xunits)       -> cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits)
+gridInqYname(gridID, yname)         -> cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname)
+gridInqYlongname(gridID, ylongname) -> cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname)
+gridInqYunits(gridID, yunits)       -> cdiGridInqKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits)
diff --git a/app/Makefile.in b/app/Makefile.in
index 1c1baf6dae7278d5aaa26172f980308cdf3b6913..bcaa36a56d5f324229b67cdbb6f55ac13656f37b 100644
--- a/app/Makefile.in
+++ b/app/Makefile.in
@@ -266,11 +266,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -294,7 +292,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -376,7 +373,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/app/cdi.c b/app/cdi.c
index 399b9b02ef39eaebce81b7d9c6751cacc10a28fd..b1c3341814a6a757ef9d408560892e3a01f8a0c6 100644
--- a/app/cdi.c
+++ b/app/cdi.c
@@ -66,7 +66,7 @@ static int DefaultFileType  = CDI_UNDEFID;
 static int DefaultDataType  = CDI_UNDEFID;
 static int DefaultByteorder = CDI_UNDEFID;
 
-static int comptype  = COMPRESS_NONE;  // Compression type
+static int comptype  = CDI_COMPRESS_NONE;  // Compression type
 static int complevel = 0;              // Compression level
 
 enum datamode {SP_MODE, DP_MODE};
@@ -277,7 +277,7 @@ void printInfo(int vdate, int vtime, char *varname, double level,
       fprintf(stdout, "  -  (%#12.5g,%#12.5g)  -", arrmean_r, arrmean_i);
     }
 
-  fprintf(stdout, " : %-11s\n", varname);
+  fprintf(stdout, " : %-14s\n", varname);
 
   if ( imiss != nmiss && nmiss > 0 )
     fprintf(stdout, "Found %d of %d missing values!\n", imiss, nmiss);
@@ -435,7 +435,7 @@ void printShortinfo(int streamID, int vlistID, int vardis)
 
 	  fprintf(stdout, " %-3s", pstr);
 
-	  if ( vlistInqVarCompType(vlistID, varID) == COMPRESS_NONE )
+	  if ( vlistInqVarCompType(vlistID, varID) == CDI_COMPRESS_NONE )
 	    fprintf(stdout, "  ");
 	  else
 	    fprintf(stdout, "z ");
@@ -448,10 +448,10 @@ void printShortinfo(int streamID, int vlistID, int vardis)
 	  if (vardis)
             {
               vlistInqVarName(vlistID, varID, varname);
-              fprintf(stdout, "%-11s", varname);
+              fprintf(stdout, "%-14s", varname);
             }
 	  else
-	    fprintf(stdout, "%-11s", paramstr);
+	    fprintf(stdout, "%-14s", paramstr);
 
 	  fprintf(stdout, "\n");
 	}
@@ -712,20 +712,20 @@ void defineCompress(const char *arg)
 
   if      ( strncmp(arg, "szip", len) == 0 )
     {
-      comptype = COMPRESS_SZIP;
+      comptype = CDI_COMPRESS_SZIP;
     }
   else if ( strncmp(arg, "jpeg", len) == 0 )
     {
-      comptype = COMPRESS_JPEG;
+      comptype = CDI_COMPRESS_JPEG;
     }
   else if ( strncmp(arg, "gzip", len) == 0 )
     {
-      comptype = COMPRESS_GZIP;
+      comptype = CDI_COMPRESS_GZIP;
       complevel = 6;
     }
   else if ( strncmp(arg, "zip", 3) == 0 )
     {
-      comptype = COMPRESS_ZIP;
+      comptype = CDI_COMPRESS_ZIP;
       if ( len == 5 && arg[3] == '_' && isdigit(arg[4]) )
 	complevel = atoi(&arg[4]);
       else
@@ -923,7 +923,7 @@ int main(int argc, char *argv[])
 	  if ( DefaultByteorder != CDI_UNDEFID )
 	    streamDefByteorder(streamID2, DefaultByteorder);
 
-	  if ( comptype != COMPRESS_NONE )
+	  if ( comptype != CDI_COMPRESS_NONE )
 	    {
 	      streamDefCompType(streamID2, comptype);
 	      streamDefCompLevel(streamID2, complevel);
diff --git a/app/printinfo.h b/app/printinfo.h
index 3a10ffeb3e90950ada48e81126dc418f3096b84b..f91f37c9e95a008d07f56b6711366878cefd3c1e 100644
--- a/app/printinfo.h
+++ b/app/printinfo.h
@@ -9,6 +9,14 @@
 #define DATE_FORMAT "%5.4d-%2.2d-%2.2d"
 #define TIME_FORMAT "%2.2d:%2.2d:%2.2d"
 
+void my_reset_text_color(FILE *fp)
+{
+  (void)fp;
+#ifdef CDO
+  reset_text_color(fp);
+#endif
+}
+
 void datetime2str(int date, int time, char *datetimestr, int maxlen)
 {
   int year, month, day;
@@ -107,9 +115,9 @@ void printFiletype(int streamID, int vlistID)
 	  comptype = vlistInqVarCompType(vlistID, varID);
 	  if ( comptype )
 	    {
-	      if ( comptype == COMPRESS_SZIP )
+	      if ( comptype == CDI_COMPRESS_SZIP )
 		printf(" SZIP");
-	      else if ( comptype == COMPRESS_ZIP )
+	      else if ( comptype == CDI_COMPRESS_ZIP )
 		printf(" ZIP");
 
 	      break;
@@ -126,7 +134,7 @@ void printFiletype(int streamID, int vlistID)
 	  comptype = vlistInqVarCompType(vlistID, varID);
 	  if ( comptype )
 	    {
-	      if ( comptype == COMPRESS_JPEG )
+	      if ( comptype == CDI_COMPRESS_JPEG )
 		printf(" JPEG");
 
 	      break;
@@ -138,246 +146,373 @@ void printFiletype(int streamID, int vlistID)
 }
 
 static
-void printGridInfo(int vlistID)
+void print_xvals(int gridID, int dig)
 {
-  char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
-  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
+  int xsize = gridInqXsize(gridID);
+  if ( xsize > 0 && gridInqXvals(gridID, NULL) )
+    {
+      char xname[CDI_MAX_NAME], xunits[CDI_MAX_NAME];
+      gridInqXname(gridID, xname);
+      gridInqXunits(gridID, xunits);
 
-  int ngrids = vlistNgrids(vlistID);
-  for ( int index = 0; index < ngrids; index++ )
+      double xfirst = gridInqXval(gridID, 0);
+      double xlast  = gridInqXval(gridID, xsize-1);
+      double xinc   = gridInqXinc(gridID);
+      fprintf(stdout, "%33s : %.*g", xname, dig, xfirst);
+      if ( xsize > 1 )
+        {
+          fprintf(stdout, " to %.*g", dig, xlast);
+          if ( IS_NOT_EQUAL(xinc, 0) )
+            fprintf(stdout, " by %.*g", dig, xinc);
+        }
+      fprintf(stdout, " %s", xunits);
+      if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
+      fprintf(stdout, "\n");
+    }
+}
+
+static
+void print_yvals(int gridID, int dig)
+{
+  int ysize = gridInqYsize(gridID);
+  if ( ysize > 0 && gridInqYvals(gridID, NULL) )
     {
-      int gridID   = vlistGrid(vlistID, index);
-      int gridtype = gridInqType(gridID);
-      int trunc    = gridInqTrunc(gridID);
-      int gridsize = gridInqSize(gridID);
-      int xsize    = gridInqXsize(gridID);
-      int ysize    = gridInqYsize(gridID);
-      int xysize   = xsize*ysize;
-      int prec     = gridInqPrec(gridID);
+      char yname[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
+      gridInqYname(gridID, yname);
+      gridInqYunits(gridID, yunits);
 
-      int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+      double yfirst = gridInqYval(gridID, 0);
+      double ylast  = gridInqYval(gridID, ysize-1);
+      double yinc   = gridInqYinc(gridID);
+      fprintf(stdout, "%33s : %.*g", yname, dig, yfirst);
+      if ( ysize > 1 )
+        {
+          int gridtype = gridInqType(gridID);
+          fprintf(stdout, " to %.*g", dig, ylast);
+          if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED )
+            fprintf(stdout, " by %.*g", dig, yinc);
+        }
+      fprintf(stdout, " %s", yunits);
+      fprintf(stdout, "\n");
+    }
+}
 
+static
+void print_xyvals2D(int gridID, int dig)
+{
+  if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+    {
+      char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
       gridInqXname(gridID, xname);
       gridInqYname(gridID, yname);
       gridInqXunits(gridID, xunits);
       gridInqYunits(gridID, yunits);
 
-      fprintf(stdout, "  %4d : %-24s", index+1, gridNamePtr(gridtype));
+      int gridsize = gridInqSize(gridID);
+      double *xvals2D = (double*) malloc((size_t)gridsize*sizeof(double));
+      double *yvals2D = (double*) malloc((size_t)gridsize*sizeof(double));
 
-      if ( gridtype == GRID_LONLAT   ||
-	   gridtype == GRID_LCC2 ||
-	   gridtype == GRID_LAEA ||
-	   gridtype == GRID_SINUSOIDAL ||
-	   gridtype == GRID_GENERIC ||
-	   gridtype == GRID_GAUSSIAN ||
-	   gridtype == GRID_GAUSSIAN_REDUCED )
-	{
-	  double yfirst = gridInqYval(gridID, 0);
-	  double ylast  = gridInqYval(gridID, ysize-1);
-	  double yinc   = gridInqYinc(gridID);
+      gridInqXvals(gridID, xvals2D);
+      gridInqYvals(gridID, yvals2D);
 
-          fprintf(stdout, " : points=%d", gridsize);
-	  if ( gridtype == GRID_GAUSSIAN_REDUCED )
-	    fprintf(stdout, "  nlat=%d", ysize);
-	  else if ( xysize )
-	    fprintf(stdout, " (%dx%d)", xsize, ysize);
+      double xfirst = xvals2D[0];
+      double xlast  = xvals2D[0];
+      double yfirst = yvals2D[0];
+      double ylast  = yvals2D[0];
+      for ( int i = 1; i < gridsize; i++ )
+        {
+          if ( xvals2D[i] < xfirst ) xfirst = xvals2D[i];
+          if ( xvals2D[i] > xlast  ) xlast  = xvals2D[i];
+          if ( yvals2D[i] < yfirst ) yfirst = yvals2D[i];
+          if ( yvals2D[i] > ylast  ) ylast  = yvals2D[i];
+        }
 
-	  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
-	    fprintf(stdout, "  np=%d", gridInqNP(gridID));
+      double xinc = 0;
+      double yinc = 0;
+      int gridtype = gridInqType(gridID);
+      if ( gridtype == GRID_CURVILINEAR )
+        {
+          int xsize = gridInqXsize(gridID);
+          if ( xsize > 1 )
+            {
+              double *xvals = (double*) malloc(xsize*sizeof(double));
+              for ( int i = 0; i < xsize; ++i ) xvals[i] = xvals2D[i];
+              xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
+              for ( int i = 2; i < xsize; i++ )
+                if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc ) { xinc = 0; break; }
+              free(xvals);
+            }
+          int ysize = gridInqYsize(gridID);
+          if ( ysize > 1 )
+            {
+              double *yvals = (double*) malloc(ysize*sizeof(double));
+              for ( int i = 0; i < ysize; ++i ) yvals[i] = yvals2D[i*xsize];
+              yinc = fabs(yvals[ysize-1] - yvals[0])/(ysize-1);
+              for ( int i = 2; i < ysize; i++ )
+                if ( fabs(fabs(yvals[i-1] - yvals[i]) - yinc) > 0.01*yinc ) { yinc = 0; break; }
+              free(yvals);
+            }
+        }
 
-	  fprintf(stdout, "\n");
+      fprintf(stdout, "%33s : %.*g to %.*g", xname, dig, xfirst, dig, xlast);
+      if ( IS_NOT_EQUAL(xinc, 0) )
+        fprintf(stdout, " by %.*g", dig, xinc);
+      fprintf(stdout, " %s", xunits);
+      if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
+      fprintf(stdout, "\n");
+      fprintf(stdout, "%33s : %.*g to %.*g", yname, dig, yfirst, dig, ylast);
+      if ( IS_NOT_EQUAL(yinc, 0) )
+        fprintf(stdout, " by %.*g", dig, yinc);
+      fprintf(stdout, " %s", xunits);
+      fprintf(stdout, "\n");
 
-          bool lxcoord = true, lycoord = true;
-          if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = false;
-          if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = false;
+      free(xvals2D);
+      free(yvals2D);
+    }
+}
 
-	  if ( xsize > 0 && lxcoord )
-	    {
-              double xfirst = gridInqXval(gridID, 0);
-              double xlast  = gridInqXval(gridID, xsize-1);
-              double xinc   = gridInqXinc(gridID);
-              fprintf(stdout, "%33s : %.*g", xname, dig, xfirst);
-              if ( xsize > 1 )
-                {
-                  fprintf(stdout, " to %.*g", dig, xlast);
-                  if ( IS_NOT_EQUAL(xinc, 0) )
-                    fprintf(stdout, " by %.*g", dig, xinc);
-                }
-              fprintf(stdout, " %s", xunits);
-              if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
-              fprintf(stdout, "\n");
-	    }
+static
+void printGridInfoKernel(int gridID, int index, bool lproj)
+{
+  int gridtype = gridInqType(gridID);
 
-	  if ( ysize > 0 && lycoord )
-	    {
-	      fprintf(stdout, "%33s : %.*g", yname, dig, yfirst);
-	      if ( ysize > 1 )
-                {
-                  fprintf(stdout, " to %.*g", dig, ylast);
-                  if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED )
-                    fprintf(stdout, " by %.*g", dig, yinc);
-                }
-              fprintf(stdout, " %s", yunits);
-	      fprintf(stdout, "\n");
-	    }
+  if ( lproj && gridtype != GRID_PROJECTION )
+    fprintf(stderr, "Internal problem (%s): sub grid not equal GRID_PROJECTION!\n", __func__);
 
-	  if ( gridIsRotated(gridID) )
-	    {
-	      double lonpole = gridInqXpole(gridID);
-	      double latpole = gridInqYpole(gridID);
-	      double angle   = gridInqAngle(gridID);
-	      fprintf(stdout, "%33s : lon=%.*g  lat=%.*g", "northpole", dig, lonpole, dig, latpole);
-	      if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%.*g", dig, angle);
-	      fprintf(stdout, "\n");
-	    }
+  int trunc    = gridInqTrunc(gridID);
+  int gridsize = gridInqSize(gridID);
+  int xsize    = gridInqXsize(gridID);
+  int ysize    = gridInqYsize(gridID);
+  int xysize   = xsize*ysize;
 
-	  if ( gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
-	    {
-	      fprintf(stdout, "%33s :", "available");
-	      if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds");
-	      if ( gridHasArea(gridID) )          fprintf(stdout, " area");
-	      if ( gridInqMask(gridID, NULL) )    fprintf(stdout, " mask");
-	      fprintf(stdout, "\n");
-	    }
+  // int prec     = gridInqPrec(gridID);
+  // int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
+  int dig = 7;
 
-	  if ( gridtype == GRID_LAEA )
-	    {
-	      double a, lon_0, lat_0;
-	      gridInqLaea(gridID, &a, &lon_0, &lat_0);
-	      fprintf(stdout, "%33s : a=%g  lon_0=%g  lat_0=%g\n", "projpar", a, lon_0, lat_0);
-	    }
+  if ( !lproj )
+    {
+      fprintf(stdout, "  %4d : ", index+1);
+#ifdef CDO
+      set_text_color(stdout, RESET, BLUE);
+#endif
+      fprintf(stdout, "%-24s", gridNamePtr(gridtype));
+      my_reset_text_color(stdout);
+      fprintf(stdout, " : ");
+    }
 
-	  if ( gridtype == GRID_LCC2 )
-	    {
-	      double a, lon_0, lat_0, lat_1, lat_2;
-	      gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2);
-	      fprintf(stdout, "%33s : a=%7.0f  lon_0=%g  lat_0=%g  lat_1=%g  lat_2=%g\n",
-                      "projpar", a, lon_0, lat_0, lat_1, lat_2);
-	    }
-	}
-      else if ( gridtype == GRID_SPECTRAL )
-	{
-	  fprintf(stdout, " : points=%d  nsp=%d  truncation=%d", gridsize, gridsize/2, trunc);
-          if ( gridInqComplexPacking(gridID) ) fprintf(stdout, "  complexPacking");
-          fprintf(stdout, "\n");
-	}
-      else if ( gridtype == GRID_FOURIER )
-	{
-	  fprintf(stdout, " : points=%d  nfc=%d  truncation=%d\n", gridsize, gridsize/2, trunc);
-	}
-      else if ( gridtype == GRID_GME )
-	{
-	  int ni = gridInqGMEni(gridID);
-	  int nd = gridInqGMEnd(gridID);
-	  fprintf(stdout, " : points=%d  nd=%d  ni=%d\n", gridsize, nd, ni);
-	}
-      else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	{
-	  if ( gridtype == GRID_CURVILINEAR )
-	    fprintf(stdout, " : points=%d (%dx%d)", gridsize, xsize, ysize);
-	  else
-	    fprintf(stdout, " : points=%d", gridsize);
+  if ( gridtype == GRID_LONLAT     ||
+       gridtype == GRID_LCC2       ||
+       gridtype == GRID_LAEA       ||
+       gridtype == GRID_SINUSOIDAL ||
+       gridtype == GRID_PROJECTION ||
+       gridtype == GRID_GENERIC    ||
+       gridtype == GRID_GAUSSIAN   ||
+       gridtype == GRID_GAUSSIAN_REDUCED )
+    {
+      if ( !lproj )
+        {
+#ifdef CDO
+          set_text_color(stdout, RESET, GREEN);
+#endif
+          fprintf(stdout, "points=%d", gridsize);
+          if ( gridtype == GRID_GAUSSIAN_REDUCED )
+            fprintf(stdout, "  nlat=%d", ysize);
+          else if ( xysize )
+            fprintf(stdout, " (%dx%d)", xsize, ysize);
 
-          if ( gridtype == GRID_UNSTRUCTURED && gridInqNvertex(gridID) > 0 )
-	    fprintf(stdout, "  nvertex=%d", gridInqNvertex(gridID));
+          if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
+            fprintf(stdout, "  np=%d", gridInqNP(gridID));
+          my_reset_text_color(stdout);
 
           fprintf(stdout, "\n");
+        }
 
-          if ( gridtype == GRID_UNSTRUCTURED )
-            {
-              int number   = gridInqNumber(gridID);
-              int position = gridInqPosition(gridID);
+      char name[CDI_MAX_NAME]; name[0] = 0;
+      cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, name);
+      if ( gridtype == GRID_PROJECTION || name[0] )
+        {
+          if ( name[0] == 0 ) strcpy(name, "undefined");
+#ifdef CDO
+          set_text_color(stdout, RESET, BLUE);
+#endif
+          fprintf(stdout, "         %24s", "mapping");
+          my_reset_text_color(stdout);
+          fprintf(stdout, " : ");
+#ifdef CDO
+          set_text_color(stdout, RESET, GREEN);
+#endif
+          fprintf(stdout, "%s\n", name);
+          my_reset_text_color(stdout);
+        }
 
-              if ( number > 0 )
-                {
-                  fprintf(stdout, "%33s : number=%d  position=%d\n", "grid", number, position);
-                }
+      print_xvals(gridID, dig);
+      print_yvals(gridID, dig);
 
-              if ( gridInqReference(gridID, NULL) )
-                {
-                  char reference_link[8192];
-                  gridInqReference(gridID, reference_link);
-                  fprintf(stdout, "%33s : %s\n", "uri", reference_link);
-                }
-            }
+      if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+        {
+          double lonpole = gridInqXpole(gridID);
+          double latpole = gridInqYpole(gridID);
+          double angle   = gridInqAngle(gridID);
+          fprintf(stdout, "%33s : lon=%.*g  lat=%.*g", "northpole", dig, lonpole, dig, latpole);
+          if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, "  angle=%.*g", dig, angle);
+          fprintf(stdout, "\n");
+        }
 
-	  if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
-	    {
-	      double *xvals = (double*) malloc((size_t)gridsize*sizeof(double));
-	      double *yvals = (double*) malloc((size_t)gridsize*sizeof(double));
-
-	      gridInqXvals(gridID, xvals);
-	      gridInqYvals(gridID, yvals);
-
-	      double xfirst = xvals[0];
-	      double xlast  = xvals[0];
-	      double yfirst = yvals[0];
-	      double ylast  = yvals[0];
-	      for ( int i = 1; i < gridsize; i++ )
-		{
-		  if ( xvals[i] < xfirst ) xfirst = xvals[i];
-		  if ( xvals[i] > xlast  ) xlast  = xvals[i];
-		  if ( yvals[i] < yfirst ) yfirst = yvals[i];
-		  if ( yvals[i] > ylast  ) ylast  = yvals[i];
-		}
-
-	      fprintf(stdout, "%33s : %.*g to %.*g %s", xname, dig, xfirst, dig, xlast, xunits);
-	      if ( gridIsCircular(gridID) ) fprintf(stdout, "  circular");
-	      fprintf(stdout, "\n");
-	      fprintf(stdout, "%33s : %.*g to %.*g %s\n", yname, dig, yfirst, dig, ylast, yunits);
-
-	      free(xvals);
-	      free(yvals);
-	    }
-	}
-      else if ( gridtype == GRID_LCC )
-	{
-	  double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
-	  int projflag, scanflag;
+      if ( gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
+        {
+          fprintf(stdout, "%33s :", "available");
+          if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds");
+          if ( gridHasArea(gridID) )          fprintf(stdout, " area");
+          if ( gridInqMask(gridID, NULL) )    fprintf(stdout, " mask");
+          fprintf(stdout, "\n");
+        }
 
-	  gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-		     &projflag, &scanflag);
+      if ( gridtype == GRID_LAEA )
+        {
+          double a, lon_0, lat_0;
+          gridInqLaea(gridID, &a, &lon_0, &lat_0);
+          fprintf(stdout, "%33s : a=%g  lon_0=%g  lat_0=%g\n", "projpar", a, lon_0, lat_0);
+        }
 
-	  fprintf(stdout, " : points=%d (%dx%d)  ", gridsize, xsize, ysize);
-	  if ( (projflag&128) == 0 )
-	    fprintf(stdout, "North Pole\n");
-	  else
-	    fprintf(stdout, "South Pole\n");
+      if ( gridtype == GRID_LCC2 )
+        {
+          double a, lon_0, lat_0, lat_1, lat_2;
+          gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2);
+          fprintf(stdout, "%33s : a=%7.0f  lon_0=%g  lat_0=%g  lat_1=%g  lat_2=%g\n",
+                  "projpar", a, lon_0, lat_0, lat_1, lat_2);
+        }
+    }
+  else if ( gridtype == GRID_SPECTRAL )
+    {
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      fprintf(stdout, "points=%d  nsp=%d  truncation=%d", gridsize, gridsize/2, trunc);
+      if ( gridInqComplexPacking(gridID) ) fprintf(stdout, "  complexPacking");
+      my_reset_text_color(stdout);
+      fprintf(stdout, "\n");
+    }
+  else if ( gridtype == GRID_FOURIER )
+    {
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      fprintf(stdout, "points=%d  nfc=%d  truncation=%d\n", gridsize, gridsize/2, trunc);
+      my_reset_text_color(stdout);
+    }
+  else if ( gridtype == GRID_GME )
+    {
+      int ni = gridInqGMEni(gridID);
+      int nd = gridInqGMEnd(gridID);
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      fprintf(stdout, "points=%d  nd=%d  ni=%d\n", gridsize, nd, ni);
+      my_reset_text_color(stdout);
+    }
+  else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
+    {
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      if ( gridtype == GRID_CURVILINEAR )
+        fprintf(stdout, "points=%d (%dx%d)", gridsize, xsize, ysize);
+      else
+        fprintf(stdout, "points=%d", gridsize);
 
-	  fprintf(stdout, "%33s : originLon=%g  originLat=%g  lonParY=%g\n", " ", originLon, originLat, lonParY);
-	  fprintf(stdout, "%33s : lat1=%g  lat2=%g  xinc=%g m  yinc=%g m\n", " ", lat1, lat2, xincm, yincm);
-	}
-      else /* if ( gridtype == GRID_GENERIC ) */
-	{
-	  if ( ysize == 0 )
-	    fprintf(stdout, " : points=%d\n", gridsize);
-	  else
-            fprintf(stdout, " : points=%d (%dx%d)\n", gridsize, xsize, ysize);
-	}
+      if ( gridtype == GRID_UNSTRUCTURED && gridInqNvertex(gridID) > 0 )
+        fprintf(stdout, "  nvertex=%d", gridInqNvertex(gridID));
+      my_reset_text_color(stdout);
 
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC )
-	{
-	  if ( gridHasArea(gridID) ||
-	       gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
-	    {
-	      fprintf(stdout, "%33s :", "available");
-	      if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds");
-	      if ( gridHasArea(gridID) )          fprintf(stdout, " area");
-	      if ( gridInqMask(gridID, NULL) )    fprintf(stdout, " mask");
-	      fprintf(stdout, "\n");
-	    }
-	}
+      fprintf(stdout, "\n");
 
-      gridInqUUID(gridID, uuidOfHGrid);
-      if ( !cdiUUIDIsNull(uuidOfHGrid) )
+      if ( gridtype == GRID_UNSTRUCTURED )
         {
-          char uuidOfHGridStr[37];
-          cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
-          if ( uuidOfHGridStr[0] != 0  && strlen(uuidOfHGridStr) == 36 )
+          int number   = gridInqNumber(gridID);
+          int position = gridInqPosition(gridID);
+          if ( number > 0 )
+            fprintf(stdout, "%33s : number=%d  position=%d\n", "grid", number, position);
+
+          if ( gridInqReference(gridID, NULL) )
             {
-	      fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr);
+              char reference_link[8192];
+              gridInqReference(gridID, reference_link);
+              fprintf(stdout, "%33s : %s\n", "uri", reference_link);
             }
         }
+
+      print_xyvals2D(gridID, dig);
+    }
+  else if ( gridtype == GRID_LCC )
+    {
+      double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
+      int projflag, scanflag;
+
+      gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
+                 &projflag, &scanflag);
+
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      fprintf(stdout, "points=%d (%dx%d)  ", gridsize, xsize, ysize);
+      if ( (projflag&128) == 0 )
+        fprintf(stdout, "North Pole\n");
+      else
+        fprintf(stdout, "South Pole\n");
+      my_reset_text_color(stdout);
+
+      fprintf(stdout, "%33s : originLon=%g  originLat=%g  lonParY=%g\n", " ", originLon, originLat, lonParY);
+      fprintf(stdout, "%33s : lat1=%g  lat2=%g  xinc=%g m  yinc=%g m\n", " ", lat1, lat2, xincm, yincm);
+    }
+  else /* if ( gridtype == GRID_GENERIC ) */
+    {
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
+      if ( ysize == 0 )
+        fprintf(stdout, "points=%d\n", gridsize);
+      else
+        fprintf(stdout, "points=%d (%dx%d)\n", gridsize, xsize, ysize);
+      my_reset_text_color(stdout);
+    }
+
+  if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC )
+    {
+      if ( gridHasArea(gridID) ||
+           gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
+        {
+          fprintf(stdout, "%33s :", "available");
+          if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds");
+          if ( gridHasArea(gridID) )          fprintf(stdout, " area");
+          if ( gridInqMask(gridID, NULL) )    fprintf(stdout, " mask");
+          fprintf(stdout, "\n");
+        }
+    }
+
+  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
+  gridInqUUID(gridID, uuidOfHGrid);
+  if ( !cdiUUIDIsNull(uuidOfHGrid) )
+    {
+      char uuidOfHGridStr[37];
+      cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
+      if ( uuidOfHGridStr[0] != 0  && strlen(uuidOfHGridStr) == 36 )
+        {
+          fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr);
+        }
+    }
+}
+
+static
+void printGridInfo(int vlistID)
+{
+  int ngrids = vlistNgrids(vlistID);
+  for ( int index = 0; index < ngrids; index++ )
+    {
+      int gridID = vlistGrid(vlistID, index);
+      printGridInfoKernel(gridID, index, false);
+      int projID = gridInqProj(gridID);
+      if ( projID != CDI_UNDEFID )
+        printGridInfoKernel(projID, index, true);
     }
 }
 
@@ -403,12 +538,23 @@ void printZaxisInfo(int vlistID)
       zaxisInqUnits(zaxisID, zunits);
       zunits[12] = 0;
 
+      fprintf(stdout, "  %4d : ", vlistZaxisIndex(vlistID, zaxisID)+1);
+#ifdef CDO
+      set_text_color(stdout, RESET, BLUE);
+#endif
       if ( zaxistype == ZAXIS_GENERIC && ltype != 0 )
-        fprintf(stdout, "  %4d : %-12s (ltype=%3d) :", vlistZaxisIndex(vlistID, zaxisID)+1, zaxisname, ltype);
+        fprintf(stdout, "%-12s (ltype=%3d) :", zaxisname, ltype);
       else
-        fprintf(stdout, "  %4d : %-24s :", vlistZaxisIndex(vlistID, zaxisID)+1, zaxisname);
+        fprintf(stdout, "%-24s", zaxisname);
+      my_reset_text_color(stdout);
+
+      fprintf(stdout, " :");
 
+#ifdef CDO
+      set_text_color(stdout, RESET, GREEN);
+#endif
       fprintf(stdout, " levels=%d", levelsize);
+      my_reset_text_color(stdout);
       fprintf(stdout, "\n");
 
       double *levels = (double*) malloc((size_t)levelsize*sizeof(double));
diff --git a/configure b/configure
index b3db107b05b85416c2ff4217e35cb2a3e43b0094..a56e2e2134edc353bc4d2556895c6e465f8dcdfb 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for cdi 1.7.2.
+# Generated by GNU Autoconf 2.68 for cdi 1.8.0rc1.
 #
 # Report bugs to <http://mpimet.mpg.de/cdi>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdi'
 PACKAGE_TARNAME='cdi'
-PACKAGE_VERSION='1.7.2'
-PACKAGE_STRING='cdi 1.7.2'
+PACKAGE_VERSION='1.8.0rc1'
+PACKAGE_STRING='cdi 1.8.0rc1'
 PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdi'
 PACKAGE_URL=''
 
@@ -688,10 +688,6 @@ HAVE_LIBGRIB_API_FALSE
 HAVE_LIBGRIB_API_TRUE
 GRIB_API_LIBS
 GRIB_API_INCLUDE
-LIBPNG_LIBS
-OPENJPEG_LIBS
-openjpeg_LIBS
-JASPER_LIBS
 NETCDF_LIBS
 NETCDF_INCLUDE
 NETCDF_ROOT
@@ -862,9 +858,6 @@ enable_largefile
 with_threads
 with_szlib
 with_netcdf
-with_jasper
-with_openjpeg
-with_libpng
 with_grib_api
 enable_grib
 enable_cgribex
@@ -1467,7 +1460,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures cdi 1.7.2 to adapt to many kinds of systems.
+\`configure' configures cdi 1.8.0rc1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1537,7 +1530,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdi 1.7.2:";;
+     short | recursive ) echo "Configuration of cdi 1.8.0rc1:";;
    esac
   cat <<\_ACEOF
 
@@ -1592,16 +1585,6 @@ Optional Packages:
                           NETCDF4 compression
   --with-netcdf=<yes|no|directory> (default=no)
                           location of NetCDF library (lib and include subdirs)
-  --with-jasper=<directory>
-                          Specify location of JASPER library. You must specify
-                          its location if GRIB_API was built with JASPER.
-  --with-openjpeg=<directory>
-                          Specify location of openjpeg library. You must
-                          specify its location if GRIB_API was built with
-                          openjpeg.
-  --with-libpng=<directory>
-                          Specify location of LIBPNG library. You must specify
-                          its location if GRIB_API was built with LIBPNG.
   --with-grib_api=<yes|no|directory>
                           library for grib2 compression; if a directory is
                           given, it will be used as a value for
@@ -1740,7 +1723,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdi configure 1.7.2
+cdi configure 1.8.0rc1
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2585,7 +2568,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by cdi $as_me 1.7.2, which was
+It was created by cdi $as_me 1.8.0rc1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3537,7 +3520,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdi'
- VERSION='1.7.2'
+ VERSION='1.8.0rc1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -23406,7 +23389,7 @@ Usage: $0 [OPTIONS]
 Report bugs to <bug-libtool@gnu.org>."
 
 lt_cl_version="\
-cdi config.lt 1.7.2
+cdi config.lt 1.8.0rc1
 configured by $0, generated by GNU Autoconf 2.68.
 
 Copyright (C) 2011 Free Software Foundation, Inc.
@@ -27528,507 +27511,6 @@ fi
 
 
 
-#  ----------------------------------------------------------------------
-#  Link application with JASPER library (needed for GRIB2 compression)
-JASPER_LIBS=''
-
-# Check whether --with-jasper was given.
-if test "${with_jasper+set}" = set; then :
-  withval=$with_jasper; case "$with_jasper" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jasper library" >&5
-$as_echo_n "checking for jasper library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in jasper.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "jasper.h" "ac_cv_header_jasper_h" "$ac_includes_default"
-if test "x$ac_cv_header_jasper_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_JASPER_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing jas_init" >&5
-$as_echo_n "checking for library containing jas_init... " >&6; }
-if ${ac_cv_search_jas_init+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char jas_init ();
-int
-main ()
-{
-return jas_init ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' jasper; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_jas_init=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_jas_init+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_jas_init+:} false; then :
-
-else
-  ac_cv_search_jas_init=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_jas_init" >&5
-$as_echo "$ac_cv_search_jas_init" >&6; }
-ac_res=$ac_cv_search_jas_init
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBJASPER 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to jasper library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                            JASPER_LIBS=" -ljasper"
- ;; #(
-  *) :
-    JASPER_ROOT=$with_jasper
-                          if test -d "$JASPER_ROOT"; then :
-  LDFLAGS="$LDFLAGS -L$JASPER_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$JASPER_ROOT/include"
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing jas_stream_memopen" >&5
-$as_echo_n "checking for library containing jas_stream_memopen... " >&6; }
-if ${ac_cv_search_jas_stream_memopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char jas_stream_memopen ();
-int
-main ()
-{
-return jas_stream_memopen ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' jasper; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_jas_stream_memopen=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_jas_stream_memopen+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_jas_stream_memopen+:} false; then :
-
-else
-  ac_cv_search_jas_stream_memopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_jas_stream_memopen" >&5
-$as_echo "$ac_cv_search_jas_stream_memopen" >&6; }
-ac_res=$ac_cv_search_jas_stream_memopen
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBJASPER 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to jasper library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                                 JASPER_LIBS=" -L$JASPER_ROOT/lib -ljasper"
-else
-  as_fn_error $? "$JASPER_ROOT is not a directory! JASPER suppressed" "$LINENO" 5
-fi ;; #(
-  *) :
-     ;;
-esac
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the JASPER library" >&5
-$as_echo_n "checking for the JASPER library... " >&6; }
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; }
-fi
-
-
-#  ----------------------------------------------------------------------
-#  Link application with openjpeg library (needed for GRIB2 compression)
-OPENJPEG_LIBS=''
-
-# Check whether --with-openjpeg was given.
-if test "${with_openjpeg+set}" = set; then :
-  withval=$with_openjpeg; case "$with_openjpeg" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openjpeg library" >&5
-$as_echo_n "checking for openjpeg library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in openjpeg.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "openjpeg.h" "ac_cv_header_openjpeg_h" "$ac_includes_default"
-if test "x$ac_cv_header_openjpeg_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENJPEG_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opj_image_create" >&5
-$as_echo_n "checking for library containing opj_image_create... " >&6; }
-if ${ac_cv_search_opj_image_create+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char opj_image_create ();
-int
-main ()
-{
-return opj_image_create ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' openjpeg; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_opj_image_create=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_opj_image_create+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_opj_image_create+:} false; then :
-
-else
-  ac_cv_search_opj_image_create=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opj_image_create" >&5
-$as_echo "$ac_cv_search_opj_image_create" >&6; }
-ac_res=$ac_cv_search_opj_image_create
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBOPENJPEG 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to openjpeg library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                            openjpeg_LIBS=" -lopenjpeg"
- ;; #(
-  *) :
-    OPENJPEG_ROOT=$with_openjpeg
-                          if test -d "$OPENJPEG_ROOT"; then :
-  LDFLAGS="$LDFLAGS -L$OPENJPEG_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$OPENJPEG_ROOT/include"
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opj_image_create" >&5
-$as_echo_n "checking for library containing opj_image_create... " >&6; }
-if ${ac_cv_search_opj_image_create+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char opj_image_create ();
-int
-main ()
-{
-return opj_image_create ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' openjpeg; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_opj_image_create=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_opj_image_create+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_opj_image_create+:} false; then :
-
-else
-  ac_cv_search_opj_image_create=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opj_image_create" >&5
-$as_echo "$ac_cv_search_opj_image_create" >&6; }
-ac_res=$ac_cv_search_opj_image_create
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBOPENJPEG 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to openjpeg library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                                 OPENJPEG_LIBS=" -L$OPENJPEG_ROOT/lib -lopenjpeg"
-else
-  as_fn_error $? "$OPENJPEG_ROOT is not a directory! openjpeg suppressed" "$LINENO" 5
-fi ;; #(
-  *) :
-     ;;
-esac
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the openjpeg library" >&5
-$as_echo_n "checking for the openjpeg library... " >&6; }
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; }
-fi
-
-
-#  ----------------------------------------------------------------------
-#  Link application with LIBPNG library (needed for GRIB2 compression)
-LIBPNG_LIBS=''
-
-# Check whether --with-libpng was given.
-if test "${with_libpng+set}" = set; then :
-  withval=$with_libpng; case "$with_libpng" in #(
-  no) :
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng library" >&5
-$as_echo_n "checking for libpng library... " >&6; }
-                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; } ;; #(
-  yes) :
-    for ac_header in png.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default"
-if test "x$ac_cv_header_png_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_PNG_H 1
-_ACEOF
-
-fi
-
-done
-
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing png_warning" >&5
-$as_echo_n "checking for library containing png_warning... " >&6; }
-if ${ac_cv_search_png_warning+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char png_warning ();
-int
-main ()
-{
-return png_warning ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' png; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_png_warning=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_png_warning+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_png_warning+:} false; then :
-
-else
-  ac_cv_search_png_warning=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_png_warning" >&5
-$as_echo "$ac_cv_search_png_warning" >&6; }
-ac_res=$ac_cv_search_png_warning
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBLIBPNG 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to libpng library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                            LIBPNG_LIBS=" -lpng"
- ;; #(
-  *) :
-    LIBPNG_ROOT=$with_libpng
-                          if test -d "$LIBPNG_ROOT"; then :
-  LDFLAGS="$LDFLAGS -L$LIBPNG_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$LIBPNG_ROOT/include"
-                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing png_warning" >&5
-$as_echo_n "checking for library containing png_warning... " >&6; }
-if ${ac_cv_search_png_warning+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char png_warning ();
-int
-main ()
-{
-return png_warning ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' png; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_png_warning=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_png_warning+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_png_warning+:} false; then :
-
-else
-  ac_cv_search_png_warning=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_png_warning" >&5
-$as_echo "$ac_cv_search_png_warning" >&6; }
-ac_res=$ac_cv_search_png_warning
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_LIBLIBPNG 1" >>confdefs.h
-
-else
-  as_fn_error $? "Could not link to libpng library! Required for GRIB_API" "$LINENO" 5
-fi
-
-                                 LIBPNG_LIBS=" -L$LIBPNG_ROOT/lib -lpng"
-else
-  as_fn_error $? "$LIBPNG_ROOT is not a directory! LIBPNG suppressed" "$LINENO" 5
-fi ;; #(
-  *) :
-     ;;
-esac
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the LIBPNG library" >&5
-$as_echo_n "checking for the LIBPNG library... " >&6; }
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5
-$as_echo "suppressed" >&6; }
-fi
-
-
 #  ----------------------------------------------------------------------
 #  Compile application with GRIB_API library (for GRIB2 support)
 GRIB_API_INCLUDE=''
@@ -31040,7 +30522,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by cdi $as_me 1.7.2, which was
+This file was extended by cdi $as_me 1.8.0rc1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -31106,7 +30588,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-cdi config.status 1.7.2
+cdi config.status 1.8.0rc1
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 578f31c9db39a617be87130a87fffdcf210f37db..aefe783d596fb66cda50b5afac4b8e810ddca27f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdi], [1.7.2], [http://mpimet.mpg.de/cdi])
+AC_INIT([cdi], [1.8.0rc1], [http://mpimet.mpg.de/cdi])
 
 AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
 
diff --git a/doc/Gridmapping b/doc/Gridmapping
new file mode 100644
index 0000000000000000000000000000000000000000..f6015886b1fef92c8bdb4b509a1e7bdf4ef08a53
--- /dev/null
+++ b/doc/Gridmapping
@@ -0,0 +1,151 @@
+
+=======================================
+Example 1: rotated_latitude_longitude
+=======================================
+
+	rlon = 106 ;
+	rlat = 111 ;
+	float lon(rlat, rlon) ;
+		lon:long_name = "longitude" ;
+		lon:units = "degrees_east" ;
+		lon:standard_name = "grid_longitude" ;
+	float lat(rlat, rlon) ;
+		lat:long_name = "latitude" ;
+		lat:units = "degrees_north" ;
+		lat:standard_name = "grid_latitude" ;
+        float rlat(rlat) ;
+		rlat:standard_name = "grid_latitude" ;
+		rlat:long_name = "rotated latitude" ;
+		rlat:units = "degrees" ;
+	float rlon(rlon) ;
+		rlon:standard_name = "grid_longitude" ;
+		rlon:long_name = "rotated longitude" ;
+		rlon:units = "degrees" ;
+	char rotated_pole ;
+		rotated_pole:long_name = "coordinates of the rotated North Pole" ;
+		rotated_pole:grid_mapping_name = "rotated_latitude_longitude" ;
+		rotated_pole:grid_north_pole_latitude = 39.25f ;
+		rotated_pole:grid_north_pole_longitude = -162.f ;
+	float T_2M_AV(time, height_2m, rlat, rlon) ;
+		T_2M_AV:standard_name = "air_temperature" ;
+		T_2M_AV:units = "K" ;
+		T_2M_AV:coordinates = "lon lat" ;
+
+gridtype = GRIB_CURVILINEAR
+xsize = 106
+ysize = 111
+xname = lon
+xvals = ...
+yname = lat
+yvals = ...
+xdimname = rlon
+ydimname = rlat
+projection = rotated_latitude_longitude
+pname  = rotated_pole
+pxvals = ....
+pyvals = ....
+grid_north_pole_latitude = 39.25f
+grid_north_pole_longitude = -162.f
+long_name = "coordinates of the rotated North Pole"
+
+gridID = gridCreate(GRID_CURVILINEAR, size)
+gridDefXsize(gridID, xsize)
+gridDefYsize(gridID, ysize)
+gridDefXvals(gridID, xvals)
+gridDefYvals(gridID, yvals)
+....
+projID = gridCreate(GRIB_PROJECTION, size)
+gridDefKeyStr(projID, CDI_KEY_MAPPINGNAME, len, string)
+gridDefKeyStr(projID, CDI_KEY_PNAME, len, string)
+gridDefXsize(projID, xsize)
+gridDefYsize(projID, ysize)
+gridDefXvals(projID, xvals)
+gridDefYvals(projID, yvals)
+gridDefAttStr(projID, NAME, len, string);
+gridDefAttFlt(projID, NAME, len, array);
+....
+gridDefProjection(gridID, projID);
+
+=======================================
+Example 2: lambert_azimuthal_equal_area
+=======================================
+
+        x = 334 ;
+	y = 334 ;
+
+        double x(x) ;
+		x:standard_name = "projection_x_coordinate" ;
+		x:units = "m" ;
+		x:axis = "X" ;
+	double y(y) ;
+		y:standard_name = "projection_y_coordinate" ;
+		y:units = "m" ;
+		y:axis = "Y" ;
+	char laea ;
+		laea:grid_mapping_name = "lambert_azimuthal_equal_area" ;
+		laea:earth_radius = 6370997. ;
+		laea:longitude_of_projection_origin = 0. ;
+		laea:latitude_of_projection_origin = 90. ;
+	float CFC_FC_F(time, y, x) ;
+		CFC_FC_F:grid_mapping = "laea" ;
+
+gridtype = GRIB_CURVILINEAR
+xsize = 334
+ysize = 334
+projection = lambert_azimuthal_equal_area
+pxvals = ....
+pyvals = ....
+earth_radius = 6370997.
+longitude_of_projection_origin = 0.
+latitude_of_projection_origin = 90.
+
+cdo gen_geoloc ifile ofile
+//cdo del_geoloc ifile ofile
+
+gridtype = GRIB_CURVILINEAR
+xsize = 334
+ysize = 334
+xvals = ....
+yvals = ....
+xbounds = ....
+ybounds = ....
+projection = lambert_azimuthal_equal_area
+pxvals = ....
+pyvals = ....
+earth_radius = 6370997.
+longitude_of_projection_origin = 0.
+latitude_of_projection_origin = 90.
+
+cdo del_proj ifile ofile
+
+gridtype = GRIB_CURVILINEAR
+xsize = 334
+ysize = 334
+xvals = ....
+yvals = ....
+xbounds = ....
+ybounds = ....
+
+=======================================
+Example 3: Latitude and longitude on a spherical Earth
+=======================================
+
+dimensions:
+  lat = 18 ;
+  lon = 36 ;
+variables:
+  double lat(lat) ;
+  double lon(lon) ;
+  float temp(lat, lon) ;
+    temp:long_name = "temperature" ;
+    temp:units = "K" ;
+    temp:grid_mapping = "crs" ;
+  int crs ;
+    crs:grid_mapping_name = "latitude_longitude"
+    crs:semi_major_axis = 6371000.0 ;
+    crs:inverse_flattening = 0 ;
+
+LONLAT grid with projection parameter
+GENERIC grid        "
+CURVILINEAR grid      "
+UNSTRUCTURED grid        "
diff --git a/doc/tex/FUNCTIONS b/doc/tex/FUNCTIONS
index c82c852cf5c571b40674b65f34ecf7d9b60f3bd8..c8cbc9f36b28e8f6ae5d804c193a08f60cf56efb 100644
--- a/doc/tex/FUNCTIONS
+++ b/doc/tex/FUNCTIONS
@@ -71,16 +71,16 @@ Function catalog:
    vlistDefVarMissval   Define the missing value of a Variable
    vlistInqVarMissval   Get the missing value of a Variable
 -------------------------------------------------------------
-   vlist_att
--------------------------------------------------------------
-   vlistInqNatts        Get number of variable attributes
-   vlistInqAtt          Get information about an attribute
-   vlistDefAttInt       Define an integer attribute
-   vlistInqAttInt       Get the value(s) of an integer attribute
-   vlistDefAttFlt       Define a floating point attribute
-   vlistInqAttFlt       Get the value(s) of a floating point attribute
-   vlistDefAttTxt       Define a text attribute
-   vlistInqAttTxt       Get the value(s) of a text attribute
+   cdi_att
+-------------------------------------------------------------
+   cdiInqNatts          Get number of attributes
+   cdiInqAtt            Get information about an attribute
+   cdiDefAttInt         Define an integer attribute
+   cdiInqAttInt         Get the value(s) of an integer attribute
+   cdiDefAttFlt         Define a floating point attribute
+   cdiInqAttFlt         Get the value(s) of a floating point attribute
+   cdiDefAttTxt         Define a text attribute
+   cdiInqAttTxt         Get the value(s) of a text attribute
 -------------------------------------------------------------
    grid
 -------------------------------------------------------------
diff --git a/doc/tex/Modules b/doc/tex/Modules
index 61e3fb93137feb700c7effc66778c75a5d8a1aa9..1c1577b721fb30b0a2f08e57c59473fe7344ac33 100644
--- a/doc/tex/Modules
+++ b/doc/tex/Modules
@@ -50,15 +50,15 @@ vlistDefVarDatatype   vlist_var
 vlistInqVarDatatype   vlist_var
 vlistDefVarMissval    vlist_var
 vlistInqVarMissval    vlist_var
-vlistInqNatts         vlist_att
-vlistInqAtt           vlist_att
-vlistDelAtt           vlist_att
-vlistDefAttInt        vlist_att
-vlistInqAttInt        vlist_att
-vlistDefAttFlt        vlist_att
-vlistInqAttFlt        vlist_att
-vlistDefAttTxt        vlist_att
-vlistInqAttTxt        vlist_att
+cdiInqNatts           cdi_att
+cdiInqAtt             cdi_att
+cdiDelAtt             cdi_att
+cdiDefAttInt          cdi_att
+cdiInqAttInt          cdi_att
+cdiDefAttFlt          cdi_att
+cdiInqAttFlt          cdi_att
+cdiDefAttTxt          cdi_att
+cdiInqAttTxt          cdi_att
 gridCreate            grid
 gridDestroy           grid
 gridDuplicate         grid
diff --git a/doc/tex/c_cdi_att.tex b/doc/tex/c_cdi_att.tex
new file mode 100644
index 0000000000000000000000000000000000000000..51b93783cc226c4c6bfb73cc110e210efabc81b3
--- /dev/null
+++ b/doc/tex/c_cdi_att.tex
@@ -0,0 +1,238 @@
+
+
+\subsection{Get number of attributes: {\tt cdiInqNatts}}
+\index{cdiInqNatts}
+\label{cdiInqNatts}
+
+The function {\tt cdiInqNatts} gets the number of attributes assigned to this variable.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiInqNatts(int cdiID, int varID, int *nattsp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt nattsp\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt nattsp}]
+Pointer to location for returned number of attributes.
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Get information about an attribute: {\tt cdiInqAtt}}
+\index{cdiInqAtt}
+\label{cdiInqAtt}
+
+The function {\tt cdiInqAtt} gets information about an attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt attnum\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt attnum}]
+Attribute number (from 0 to natts-1).
+\item[{\tt name}]
+Pointer to the location for the returned attribute name. The caller must allocate space for the
+                    returned string. The maximum possible length, in characters, of
+                    the string is given by the predefined constant {\tt CDI\_MAX\_NAME}.
+\item[{\tt typep}]
+Pointer to location for returned attribute type.
+\item[{\tt lenp}]
+Pointer to location for returned attribute number.
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Define an integer attribute: {\tt cdiDefAttInt}}
+\index{cdiDefAttInt}
+\label{cdiDefAttInt}
+
+The function {\tt cdiDefAttInt} defines an integer attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, 
+                     const int *ip);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt type}]
+External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}).
+\item[{\tt len}]
+Number of values provided for the attribute.
+\item[{\tt ip}]
+Pointer to one or more integer values.
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Get the value(s) of an integer attribute: {\tt cdiInqAttInt}}
+\index{cdiInqAttInt}
+\label{cdiInqAttInt}
+
+The function {\tt cdiInqAttInt} gets the values(s) of an integer attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt mlen}]
+Number of allocated values provided for the attribute.
+\item[{\tt ip}]
+Pointer location for returned integer attribute value(s).
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Define a floating point attribute: {\tt cdiDefAttFlt}}
+\index{cdiDefAttFlt}
+\label{cdiDefAttFlt}
+
+The function {\tt cdiDefAttFlt} defines a floating point attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, 
+                     const double *dp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt type}]
+External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}).
+\item[{\tt len}]
+Number of values provided for the attribute.
+\item[{\tt dp}]
+Pointer to one or more floating point values.
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Get the value(s) of a floating point attribute: {\tt cdiInqAttFlt}}
+\index{cdiInqAttFlt}
+\label{cdiInqAttFlt}
+
+The function {\tt cdiInqAttFlt} gets the values(s) of a floating point attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt mlen}]
+Number of allocated values provided for the attribute.
+\item[{\tt dp}]
+Pointer location for returned floating point attribute value(s).
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Define a text attribute: {\tt cdiDefAttTxt}}
+\index{cdiDefAttTxt}
+\label{cdiDefAttTxt}
+
+The function {\tt cdiDefAttTxt} defines a text attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt len}]
+Number of values provided for the attribute.
+\item[{\tt tp}]
+Pointer to one or more character values.
+
+\end{deflist}
+\end{minipage}
+
+
+\subsection{Get the value(s) of a text attribute: {\tt cdiInqAttTxt}}
+\index{cdiInqAttTxt}
+\label{cdiInqAttTxt}
+
+The function {\tt cdiInqAttTxt} gets the values(s) of a text attribute.
+
+\subsubsection*{Usage}
+
+\begin{verbatim}
+    int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp);
+\end{verbatim}
+
+\hspace*{4mm}\begin{minipage}[]{15cm}
+\begin{deflist}{\tt cdiID\ }
+\item[{\tt cdiID}]
+CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
+\item[{\tt varID}]
+Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
+\item[{\tt name}]
+Attribute name.
+\item[{\tt mlen}]
+Number of allocated values provided for the attribute.
+\item[{\tt tp}]
+Pointer location for returned text attribute value(s).
+
+\end{deflist}
+\end{minipage}
diff --git a/doc/tex/c_quick_ref.tex b/doc/tex/c_quick_ref.tex
index 343bd5b7621048088b6bb455c59ea74d90048fd5..3b7eb8f4b248ece1b9f3ccdfe69cd30b25e1cae9 100644
--- a/doc/tex/c_quick_ref.tex
+++ b/doc/tex/c_quick_ref.tex
@@ -22,6 +22,83 @@ Clear the list of additional GRIB keys..
 Register an additional GRIB key which is read when file is opened..
 
 
+\section*{\tt \htmlref{cdiDefAttFlt}{cdiDefAttFlt}}
+
+\begin{verbatim}
+    int cdiDefAttFlt (int cdiID, int varID, const char *name, int type, int len,
+                      const double dp[]);
+\end{verbatim}
+
+Define a floating point attribute.
+
+
+\section*{\tt \htmlref{cdiDefAttInt}{cdiDefAttInt}}
+
+\begin{verbatim}
+    int cdiDefAttInt (int cdiID, int varID, const char *name, int type, int len,
+                      const int ip[]);
+\end{verbatim}
+
+Define an integer attribute.
+
+
+\section*{\tt \htmlref{cdiDefAttTxt}{cdiDefAttTxt}}
+
+\begin{verbatim}
+    int cdiDefAttTxt (int cdiID, int varID, const char *name, int len,
+                      const char *tp_cbuf);
+\end{verbatim}
+
+Define a text attribute.
+
+
+\section*{\tt \htmlref{cdiInqAtt}{cdiInqAtt}}
+
+\begin{verbatim}
+    int cdiInqAtt (int cdiID, int varID, int attrnum, char *name, int *typep,
+                   int *lenp);
+\end{verbatim}
+
+Get information about an attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttFlt}{cdiInqAttFlt}}
+
+\begin{verbatim}
+    int cdiInqAttFlt (int cdiID, int varID, const char *name, int mlen, double dp[]);
+\end{verbatim}
+
+Get the value(s) of a floating point attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttInt}{cdiInqAttInt}}
+
+\begin{verbatim}
+    int cdiInqAttInt (int cdiID, int varID, const char *name, int mlen, int ip[]);
+\end{verbatim}
+
+Get the value(s) of an integer attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttTxt}{cdiInqAttTxt}}
+
+\begin{verbatim}
+    int cdiInqAttTxt (int cdiID, int varID, const char *name, int mlen,
+                      char *tp_cbuf);
+\end{verbatim}
+
+Get the value(s) of a text attribute.
+
+
+\section*{\tt \htmlref{cdiInqNatts}{cdiInqNatts}}
+
+\begin{verbatim}
+    int cdiInqNatts (int cdiID, int varID, int *nattsp);
+\end{verbatim}
+
+Get number of attributes assigned to this variable.
+
+
 \section*{\tt \htmlref{gridCreate}{gridCreate}}
 
 \begin{verbatim}
@@ -76,6 +153,24 @@ Define the position of grid in the reference file.
 Define the precision of a Grid.
 
 
+\section*{\tt \htmlref{gridDefProj}{gridDefProj}}
+
+\begin{verbatim}
+    void gridDefProj (int gridID, int projID);
+\end{verbatim}
+
+Define the projection ID of a Grid.
+
+
+\section*{\tt \htmlref{gridDefProjType}{gridDefProjType}}
+
+\begin{verbatim}
+    void gridDefProjType (int gridID, int projtype);
+\end{verbatim}
+
+Define the projection type.
+
+
 \section*{\tt \htmlref{gridDefReference}{gridDefReference}}
 
 \begin{verbatim}
@@ -265,6 +360,24 @@ Get the position of grid in the reference file.
 Get the precision of a Grid.
 
 
+\section*{\tt \htmlref{gridInqProj}{gridInqProj}}
+
+\begin{verbatim}
+    int gridInqProj (int gridID);
+\end{verbatim}
+
+Get the projection ID of a Grid.
+
+
+\section*{\tt \htmlref{gridInqProjType}{gridInqProjType}}
+
+\begin{verbatim}
+    int gridInqProjType (int gridID);
+\end{verbatim}
+
+Get the projection type.
+
+
 \section*{\tt \htmlref{gridInqReference}{gridInqReference}}
 
 \begin{verbatim}
@@ -889,36 +1002,6 @@ Safe and convenient version of vlistInqVarName.
 Create a variable list.
 
 
-\section*{\tt \htmlref{vlistDefAttFlt}{vlistDefAttFlt}}
-
-\begin{verbatim}
-    int vlistDefAttFlt (int vlistID, int varID, const char *name, int type, int len,
-                        const double dp[]);
-\end{verbatim}
-
-Define a floating point attribute.
-
-
-\section*{\tt \htmlref{vlistDefAttInt}{vlistDefAttInt}}
-
-\begin{verbatim}
-    int vlistDefAttInt (int vlistID, int varID, const char *name, int type, int len,
-                        const int ip[]);
-\end{verbatim}
-
-Define an integer attribute.
-
-
-\section*{\tt \htmlref{vlistDefAttTxt}{vlistDefAttTxt}}
-
-\begin{verbatim}
-    int vlistDefAttTxt (int vlistID, int varID, const char *name, int len,
-                        const char *tp_cbuf);
-\end{verbatim}
-
-Define a text attribute.
-
-
 \section*{\tt \htmlref{vlistDefTaxis}{vlistDefTaxis}}
 
 \begin{verbatim}
@@ -1073,54 +1156,6 @@ Duplicate a variable list.
 returns 1 if meta-data key was read, 0 otherwise..
 
 
-\section*{\tt \htmlref{vlistInqAtt}{vlistInqAtt}}
-
-\begin{verbatim}
-    int vlistInqAtt (int vlistID, int varID, int attrnum, char *name, int *typep,
-                     int *lenp);
-\end{verbatim}
-
-Get information about an attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttFlt}{vlistInqAttFlt}}
-
-\begin{verbatim}
-    int vlistInqAttFlt (int vlistID, int varID, const char *name, int mlen,
-                        double dp[]);
-\end{verbatim}
-
-Get the value(s) of a floating point attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttInt}{vlistInqAttInt}}
-
-\begin{verbatim}
-    int vlistInqAttInt (int vlistID, int varID, const char *name, int mlen, int ip[]);
-\end{verbatim}
-
-Get the value(s) of an integer attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttTxt}{vlistInqAttTxt}}
-
-\begin{verbatim}
-    int vlistInqAttTxt (int vlistID, int varID, const char *name, int mlen,
-                        char *tp_cbuf);
-\end{verbatim}
-
-Get the value(s) of a text attribute.
-
-
-\section*{\tt \htmlref{vlistInqNatts}{vlistInqNatts}}
-
-\begin{verbatim}
-    int vlistInqNatts (int vlistID, int varID, int *nattsp);
-\end{verbatim}
-
-Get number of variable attributes assigned to this variable.
-
-
 \section*{\tt \htmlref{vlistInqTaxis}{vlistInqTaxis}}
 
 \begin{verbatim}
diff --git a/doc/tex/c_ref.tex b/doc/tex/c_ref.tex
index d2f2700719da5658f18555e21576236753a57f70..1eeceb6017d33f66c478528794ab8687cc3cf36d 100644
--- a/doc/tex/c_ref.tex
+++ b/doc/tex/c_ref.tex
@@ -1,5 +1,127 @@
 
 
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttFlt]{cdiDefAttFlt}
+\else
+cdiDefAttFlt
+\fi
+}
+\begin{verbatim}
+    int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, 
+                     const double *dp);
+\end{verbatim}
+
+Define a floating point attribute
+\ifpdfoutput{}{(\ref{cdiDefAttFlt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttInt]{cdiDefAttInt}
+\else
+cdiDefAttInt
+\fi
+}
+\begin{verbatim}
+    int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, 
+                     const int *ip);
+\end{verbatim}
+
+Define an integer attribute
+\ifpdfoutput{}{(\ref{cdiDefAttInt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttTxt]{cdiDefAttTxt}
+\else
+cdiDefAttTxt
+\fi
+}
+\begin{verbatim}
+    int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp);
+\end{verbatim}
+
+Define a text attribute
+\ifpdfoutput{}{(\ref{cdiDefAttTxt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAtt]{cdiInqAtt}
+\else
+cdiInqAtt
+\fi
+}
+\begin{verbatim}
+    int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp);
+\end{verbatim}
+
+Get information about an attribute
+\ifpdfoutput{}{(\ref{cdiInqAtt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttFlt]{cdiInqAttFlt}
+\else
+cdiInqAttFlt
+\fi
+}
+\begin{verbatim}
+    int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp);
+\end{verbatim}
+
+Get the value(s) of a floating point attribute
+\ifpdfoutput{}{(\ref{cdiInqAttFlt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttInt]{cdiInqAttInt}
+\else
+cdiInqAttInt
+\fi
+}
+\begin{verbatim}
+    int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip);
+\end{verbatim}
+
+Get the value(s) of an integer attribute
+\ifpdfoutput{}{(\ref{cdiInqAttInt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttTxt]{cdiInqAttTxt}
+\else
+cdiInqAttTxt
+\fi
+}
+\begin{verbatim}
+    int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp);
+\end{verbatim}
+
+Get the value(s) of a text attribute
+\ifpdfoutput{}{(\ref{cdiInqAttTxt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqNatts]{cdiInqNatts}
+\else
+cdiInqNatts
+\fi
+}
+\begin{verbatim}
+    int cdiInqNatts(int cdiID, int varID, int *nattsp);
+\end{verbatim}
+
+Get number of attributes
+\ifpdfoutput{}{(\ref{cdiInqNatts})}
+
+
 \section*{\tt 
 \ifpdf
 \hyperref[gridCreate]{gridCreate}
@@ -1114,53 +1236,6 @@ Create a variable list
 \ifpdfoutput{}{(\ref{vlistCreate})}
 
 
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttFlt]{vlistDefAttFlt}
-\else
-vlistDefAttFlt
-\fi
-}
-\begin{verbatim}
-    int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, 
-                       const double *dp);
-\end{verbatim}
-
-Define a floating point attribute
-\ifpdfoutput{}{(\ref{vlistDefAttFlt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttInt]{vlistDefAttInt}
-\else
-vlistDefAttInt
-\fi
-}
-\begin{verbatim}
-    int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, 
-                       const int *ip);
-\end{verbatim}
-
-Define an integer attribute
-\ifpdfoutput{}{(\ref{vlistDefAttInt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttTxt]{vlistDefAttTxt}
-\else
-vlistDefAttTxt
-\fi
-}
-\begin{verbatim}
-    int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp);
-\end{verbatim}
-
-Define a text attribute
-\ifpdfoutput{}{(\ref{vlistDefAttTxt})}
-
-
 \section*{\tt 
 \ifpdf
 \hyperref[vlistDefTaxis]{vlistDefTaxis}
@@ -1326,81 +1401,6 @@ Duplicate a variable list
 \ifpdfoutput{}{(\ref{vlistDuplicate})}
 
 
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAtt]{vlistInqAtt}
-\else
-vlistInqAtt
-\fi
-}
-\begin{verbatim}
-    int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp);
-\end{verbatim}
-
-Get information about an attribute
-\ifpdfoutput{}{(\ref{vlistInqAtt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttFlt]{vlistInqAttFlt}
-\else
-vlistInqAttFlt
-\fi
-}
-\begin{verbatim}
-    int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp);
-\end{verbatim}
-
-Get the value(s) of a floating point attribute
-\ifpdfoutput{}{(\ref{vlistInqAttFlt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttInt]{vlistInqAttInt}
-\else
-vlistInqAttInt
-\fi
-}
-\begin{verbatim}
-    int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip);
-\end{verbatim}
-
-Get the value(s) of an integer attribute
-\ifpdfoutput{}{(\ref{vlistInqAttInt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttTxt]{vlistInqAttTxt}
-\else
-vlistInqAttTxt
-\fi
-}
-\begin{verbatim}
-    int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp);
-\end{verbatim}
-
-Get the value(s) of a text attribute
-\ifpdfoutput{}{(\ref{vlistInqAttTxt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqNatts]{vlistInqNatts}
-\else
-vlistInqNatts
-\fi
-}
-\begin{verbatim}
-    int vlistInqNatts(int vlistID, int varID, int *nattsp);
-\end{verbatim}
-
-Get number of variable attributes
-\ifpdfoutput{}{(\ref{vlistInqNatts})}
-
-
 \section*{\tt 
 \ifpdf
 \hyperref[vlistInqTaxis]{vlistInqTaxis}
diff --git a/doc/tex/c_vlist_att.tex b/doc/tex/c_vlist_att.tex
deleted file mode 100644
index ab6ac2793929e10bb50cb55cf49ee20695784968..0000000000000000000000000000000000000000
--- a/doc/tex/c_vlist_att.tex
+++ /dev/null
@@ -1,238 +0,0 @@
-
-
-\subsection{Get number of variable attributes: {\tt vlistInqNatts}}
-\index{vlistInqNatts}
-\label{vlistInqNatts}
-
-The function {\tt vlistInqNatts} gets the number of variable attributes assigned to this variable.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistInqNatts(int vlistID, int varID, int *nattsp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt nattsp}]
-Pointer to location for returned number of variable attributes.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get information about an attribute: {\tt vlistInqAtt}}
-\index{vlistInqAtt}
-\label{vlistInqAtt}
-
-The function {\tt vlistInqAtt} gets information about an attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt attnum}]
-Attribute number (from 0 to natts-1).
-\item[{\tt name}]
-Pointer to the location for the returned attribute name. The caller must allocate space for the
-                    returned string. The maximum possible length, in characters, of
-                    the string is given by the predefined constant {\tt CDI\_MAX\_NAME}.
-\item[{\tt typep}]
-Pointer to location for returned attribute type.
-\item[{\tt lenp}]
-Pointer to location for returned attribute number.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define an integer attribute: {\tt vlistDefAttInt}}
-\index{vlistDefAttInt}
-\label{vlistDefAttInt}
-
-The function {\tt vlistDefAttInt} defines an integer attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, 
-                       const int *ip);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt type}]
-External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}).
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt ip}]
-Pointer to one or more integer values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of an integer attribute: {\tt vlistInqAttInt}}
-\index{vlistInqAttInt}
-\label{vlistInqAttInt}
-
-The function {\tt vlistInqAttInt} gets the values(s) of an integer attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt ip}]
-Pointer location for returned integer attribute value(s).
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define a floating point attribute: {\tt vlistDefAttFlt}}
-\index{vlistDefAttFlt}
-\label{vlistDefAttFlt}
-
-The function {\tt vlistDefAttFlt} defines a floating point attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, 
-                       const double *dp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt type}]
-External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}).
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt dp}]
-Pointer to one or more floating point values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of a floating point attribute: {\tt vlistInqAttFlt}}
-\index{vlistInqAttFlt}
-\label{vlistInqAttFlt}
-
-The function {\tt vlistInqAttFlt} gets the values(s) of a floating point attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt dp}]
-Pointer location for returned floating point attribute value(s).
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define a text attribute: {\tt vlistDefAttTxt}}
-\index{vlistDefAttTxt}
-\label{vlistDefAttTxt}
-
-The function {\tt vlistDefAttTxt} defines a text attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt tp}]
-Pointer to one or more character values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of a text attribute: {\tt vlistInqAttTxt}}
-\index{vlistInqAttTxt}
-\label{vlistInqAttTxt}
-
-The function {\tt vlistInqAttTxt} gets the values(s) of a text attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp);
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt tp}]
-Pointer location for returned text attribute value(s).
-
-\end{deflist}
-\end{minipage}
diff --git a/doc/tex/cdi_cman.tex b/doc/tex/cdi_cman.tex
index f319228a45c9377d41db8c9dea145b2cca783a62..31c8bdabe96a367d42775d367c87b988d1b1f379 100644
--- a/doc/tex/cdi_cman.tex
+++ b/doc/tex/cdi_cman.tex
@@ -135,7 +135,7 @@
 \end{picture}
 
 \begin{flushright}
-{\large\bfseries Climate Data Interface \\ Version 1.7.1 \\ February 2016}
+{\large\bfseries Climate Data Interface \\ Version 1.8.0 \\ October 2016}
 \end{flushright}
 
 \vfill
@@ -193,7 +193,7 @@
 \newpage
 \section{Attributes}
 \input{attribute}
-\input{c_vlist_att}
+\input{c_cdi_att}
 
 
 \newpage
diff --git a/doc/tex/cdi_fman.tex b/doc/tex/cdi_fman.tex
index 31b030028a1c06be8f098a6f1c152b55e4163bcb..d3735879dc068711871136641f1f17e23fc4f976 100644
--- a/doc/tex/cdi_fman.tex
+++ b/doc/tex/cdi_fman.tex
@@ -132,7 +132,7 @@
 \end{picture}
 
 \begin{flushright}
-{\large\bfseries Climate Data Interface \\ Version 1.7.1 \\ February 2016}
+{\large\bfseries Climate Data Interface \\ Version 1.8.0 \\ October 2016}
 \end{flushright}
 
 \vfill
@@ -190,7 +190,7 @@
 \newpage
 \section{Attributes}
 \input{attribute}
-\input{f_vlist_att}
+\input{f_cdi_att}
 
 
 \newpage
diff --git a/doc/tex/f_quick_ref.tex b/doc/tex/f_quick_ref.tex
index f4fb0987db509f6408c2a246c1de432f5996d0ff..641ba5fa7920622142758b24b4a0e1fb81b98e30 100644
--- a/doc/tex/f_quick_ref.tex
+++ b/doc/tex/f_quick_ref.tex
@@ -22,6 +22,85 @@ Clear the list of additional GRIB keys..
 Register an additional GRIB key which is read when file is opened..
 
 
+\section*{\tt \htmlref{cdiDefAttFlt}{cdiDefAttFlt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttFlt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER type, INTEGER len, DOUBLEPRECISION dp(*))
+\end{verbatim}
+
+Define a floating point attribute.
+
+
+\section*{\tt \htmlref{cdiDefAttInt}{cdiDefAttInt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttInt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER type, INTEGER len, INTEGER ip(*))
+\end{verbatim}
+
+Define an integer attribute.
+
+
+\section*{\tt \htmlref{cdiDefAttTxt}{cdiDefAttTxt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttTxt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER len, CHARACTER*(*) tp_cbuf)
+\end{verbatim}
+
+Define a text attribute.
+
+
+\section*{\tt \htmlref{cdiInqAtt}{cdiInqAtt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAtt (INTEGER cdiID, INTEGER varID, INTEGER attrnum,
+                                CHARACTER*(*) name, INTEGER typep, INTEGER lenp)
+\end{verbatim}
+
+Get information about an attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttFlt}{cdiInqAttFlt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttFlt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER mlen, DOUBLEPRECISION dp(*))
+\end{verbatim}
+
+Get the value(s) of a floating point attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttInt}{cdiInqAttInt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttInt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER mlen, INTEGER ip(*))
+\end{verbatim}
+
+Get the value(s) of an integer attribute.
+
+
+\section*{\tt \htmlref{cdiInqAttTxt}{cdiInqAttTxt}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttTxt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name,
+                                   INTEGER mlen, CHARACTER*(*) tp_cbuf)
+\end{verbatim}
+
+Get the value(s) of a text attribute.
+
+
+\section*{\tt \htmlref{cdiInqNatts}{cdiInqNatts}}
+
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqNatts (INTEGER cdiID, INTEGER varID, INTEGER nattsp)
+\end{verbatim}
+
+Get number of attributes assigned to this variable.
+
+
 \section*{\tt \htmlref{gridCreate}{gridCreate}}
 
 \begin{verbatim}
@@ -76,6 +155,24 @@ Define the position of grid in the reference file.
 Define the precision of a Grid.
 
 
+\section*{\tt \htmlref{gridDefProj}{gridDefProj}}
+
+\begin{verbatim}
+    SUBROUTINE gridDefProj (INTEGER gridID, INTEGER projID)
+\end{verbatim}
+
+Define the projection ID of a Grid.
+
+
+\section*{\tt \htmlref{gridDefProjType}{gridDefProjType}}
+
+\begin{verbatim}
+    SUBROUTINE gridDefProjType (INTEGER gridID, INTEGER projtype)
+\end{verbatim}
+
+Define the projection type.
+
+
 \section*{\tt \htmlref{gridDefReference}{gridDefReference}}
 
 \begin{verbatim}
@@ -265,6 +362,24 @@ Get the position of grid in the reference file.
 Get the precision of a Grid.
 
 
+\section*{\tt \htmlref{gridInqProj}{gridInqProj}}
+
+\begin{verbatim}
+    INTEGER FUNCTION gridInqProj (INTEGER gridID)
+\end{verbatim}
+
+Get the projection ID of a Grid.
+
+
+\section*{\tt \htmlref{gridInqProjType}{gridInqProjType}}
+
+\begin{verbatim}
+    INTEGER FUNCTION gridInqProjType (INTEGER gridID)
+\end{verbatim}
+
+Get the projection type.
+
+
 \section*{\tt \htmlref{gridInqReference}{gridInqReference}}
 
 \begin{verbatim}
@@ -892,39 +1007,6 @@ Safe and convenient version of vlistInqVarName.
 Create a variable list.
 
 
-\section*{\tt \htmlref{vlistDefAttFlt}{vlistDefAttFlt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttFlt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER type, INTEGER len,
-                                     DOUBLEPRECISION dp(*))
-\end{verbatim}
-
-Define a floating point attribute.
-
-
-\section*{\tt \htmlref{vlistDefAttInt}{vlistDefAttInt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttInt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER type, INTEGER len,
-                                     INTEGER ip(*))
-\end{verbatim}
-
-Define an integer attribute.
-
-
-\section*{\tt \htmlref{vlistDefAttTxt}{vlistDefAttTxt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttTxt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER len,
-                                     CHARACTER*(*) tp_cbuf)
-\end{verbatim}
-
-Define a text attribute.
-
-
 \section*{\tt \htmlref{vlistDefTaxis}{vlistDefTaxis}}
 
 \begin{verbatim}
@@ -1087,57 +1169,6 @@ Duplicate a variable list.
 returns 1 if meta-data key was read, 0 otherwise..
 
 
-\section*{\tt \htmlref{vlistInqAtt}{vlistInqAtt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAtt (INTEGER vlistID, INTEGER varID, INTEGER attrnum,
-                                  CHARACTER*(*) name, INTEGER typep, INTEGER lenp)
-\end{verbatim}
-
-Get information about an attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttFlt}{vlistInqAttFlt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttFlt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER mlen,
-                                     DOUBLEPRECISION dp(*))
-\end{verbatim}
-
-Get the value(s) of a floating point attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttInt}{vlistInqAttInt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttInt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER mlen, INTEGER ip(*))
-\end{verbatim}
-
-Get the value(s) of an integer attribute.
-
-
-\section*{\tt \htmlref{vlistInqAttTxt}{vlistInqAttTxt}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttTxt (INTEGER vlistID, INTEGER varID,
-                                     CHARACTER*(*) name, INTEGER mlen,
-                                     CHARACTER*(*) tp_cbuf)
-\end{verbatim}
-
-Get the value(s) of a text attribute.
-
-
-\section*{\tt \htmlref{vlistInqNatts}{vlistInqNatts}}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqNatts (INTEGER vlistID, INTEGER varID, INTEGER nattsp)
-\end{verbatim}
-
-Get number of variable attributes assigned to this variable.
-
-
 \section*{\tt \htmlref{vlistInqTaxis}{vlistInqTaxis}}
 
 \begin{verbatim}
diff --git a/doc/tex/f_ref.tex b/doc/tex/f_ref.tex
index aa39d317df9aa237c2c95f9205f879d96d110ffa..6ab0656612e84621b380050b538227c82fe7fd92 100644
--- a/doc/tex/f_ref.tex
+++ b/doc/tex/f_ref.tex
@@ -1,5 +1,132 @@
 
 
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttFlt]{cdiDefAttFlt}
+\else
+cdiDefAttFlt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttFlt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER type, INTEGER len, REAL*8 dp)
+\end{verbatim}
+
+Define a floating point attribute
+\ifpdfoutput{}{(\ref{cdiDefAttFlt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttInt]{cdiDefAttInt}
+\else
+cdiDefAttInt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttInt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER type, INTEGER len, INTEGER ip)
+\end{verbatim}
+
+Define an integer attribute
+\ifpdfoutput{}{(\ref{cdiDefAttInt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiDefAttTxt]{cdiDefAttTxt}
+\else
+cdiDefAttTxt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiDefAttTxt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER len, CHARACTER*(*) tp)
+\end{verbatim}
+
+Define a text attribute
+\ifpdfoutput{}{(\ref{cdiDefAttTxt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAtt]{cdiInqAtt}
+\else
+cdiInqAtt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAtt(INTEGER cdiID, INTEGER varID, INTEGER attnum, 
+                               CHARACTER*(*) name, INTEGER typep, INTEGER lenp)
+\end{verbatim}
+
+Get information about an attribute
+\ifpdfoutput{}{(\ref{cdiInqAtt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttFlt]{cdiInqAttFlt}
+\else
+cdiInqAttFlt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttFlt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER mlen, REAL*8 dp)
+\end{verbatim}
+
+Get the value(s) of a floating point attribute
+\ifpdfoutput{}{(\ref{cdiInqAttFlt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttInt]{cdiInqAttInt}
+\else
+cdiInqAttInt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttInt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER mlen, INTEGER ip)
+\end{verbatim}
+
+Get the value(s) of an integer attribute
+\ifpdfoutput{}{(\ref{cdiInqAttInt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqAttTxt]{cdiInqAttTxt}
+\else
+cdiInqAttTxt
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqAttTxt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, 
+                                  INTEGER mlen, CHARACTER*(*) tp)
+\end{verbatim}
+
+Get the value(s) of a text attribute
+\ifpdfoutput{}{(\ref{cdiInqAttTxt})}
+
+
+\section*{\tt 
+\ifpdf
+\hyperref[cdiInqNatts]{cdiInqNatts}
+\else
+cdiInqNatts
+\fi
+}
+\begin{verbatim}
+    INTEGER FUNCTION cdiInqNatts(INTEGER cdiID, INTEGER varID, INTEGER nattsp)
+\end{verbatim}
+
+Get number of attributes
+\ifpdfoutput{}{(\ref{cdiInqNatts})}
+
+
 \section*{\tt 
 \ifpdf
 \hyperref[gridCreate]{gridCreate}
@@ -1118,57 +1245,6 @@ Create a variable list
 \ifpdfoutput{}{(\ref{vlistCreate})}
 
 
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttFlt]{vlistDefAttFlt}
-\else
-vlistDefAttFlt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttFlt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER type, INTEGER len, 
-                                    REAL*8 dp)
-\end{verbatim}
-
-Define a floating point attribute
-\ifpdfoutput{}{(\ref{vlistDefAttFlt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttInt]{vlistDefAttInt}
-\else
-vlistDefAttInt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttInt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER type, INTEGER len, 
-                                    INTEGER ip)
-\end{verbatim}
-
-Define an integer attribute
-\ifpdfoutput{}{(\ref{vlistDefAttInt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistDefAttTxt]{vlistDefAttTxt}
-\else
-vlistDefAttTxt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttTxt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER len, 
-                                    CHARACTER*(*) tp)
-\end{verbatim}
-
-Define a text attribute
-\ifpdfoutput{}{(\ref{vlistDefAttTxt})}
-
-
 \section*{\tt 
 \ifpdf
 \hyperref[vlistDefTaxis]{vlistDefTaxis}
@@ -1337,86 +1413,6 @@ Duplicate a variable list
 \ifpdfoutput{}{(\ref{vlistDuplicate})}
 
 
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAtt]{vlistInqAtt}
-\else
-vlistInqAtt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAtt(INTEGER vlistID, INTEGER varID, INTEGER attnum, 
-                                 CHARACTER*(*) name, INTEGER typep, INTEGER lenp)
-\end{verbatim}
-
-Get information about an attribute
-\ifpdfoutput{}{(\ref{vlistInqAtt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttFlt]{vlistInqAttFlt}
-\else
-vlistInqAttFlt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttFlt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, REAL*8 dp)
-\end{verbatim}
-
-Get the value(s) of a floating point attribute
-\ifpdfoutput{}{(\ref{vlistInqAttFlt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttInt]{vlistInqAttInt}
-\else
-vlistInqAttInt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttInt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, INTEGER ip)
-\end{verbatim}
-
-Get the value(s) of an integer attribute
-\ifpdfoutput{}{(\ref{vlistInqAttInt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqAttTxt]{vlistInqAttTxt}
-\else
-vlistInqAttTxt
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttTxt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, 
-                                    CHARACTER*(*) tp)
-\end{verbatim}
-
-Get the value(s) of a text attribute
-\ifpdfoutput{}{(\ref{vlistInqAttTxt})}
-
-
-\section*{\tt 
-\ifpdf
-\hyperref[vlistInqNatts]{vlistInqNatts}
-\else
-vlistInqNatts
-\fi
-}
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqNatts(INTEGER vlistID, INTEGER varID, INTEGER nattsp)
-\end{verbatim}
-
-Get number of variable attributes
-\ifpdfoutput{}{(\ref{vlistInqNatts})}
-
-
 \section*{\tt 
 \ifpdf
 \hyperref[vlistInqTaxis]{vlistInqTaxis}
diff --git a/doc/tex/f_vlist_att.tex b/doc/tex/f_vlist_att.tex
deleted file mode 100644
index c60a032d416cd620ffa69d0b5e7ef3e7b2ba8365..0000000000000000000000000000000000000000
--- a/doc/tex/f_vlist_att.tex
+++ /dev/null
@@ -1,247 +0,0 @@
-
-
-\subsection{Get number of variable attributes: {\tt vlistInqNatts}}
-\index{vlistInqNatts}
-\label{vlistInqNatts}
-
-The function {\tt vlistInqNatts} gets the number of variable attributes assigned to this variable.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqNatts(INTEGER vlistID, INTEGER varID, INTEGER nattsp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt nattsp}]
-Pointer to location for returned number of variable attributes.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get information about an attribute: {\tt vlistInqAtt}}
-\index{vlistInqAtt}
-\label{vlistInqAtt}
-
-The function {\tt vlistInqAtt} gets information about an attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAtt(INTEGER vlistID, INTEGER varID, INTEGER attnum, 
-                                 CHARACTER*(*) name, INTEGER typep, INTEGER lenp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt attnum}]
-Attribute number (from 0 to natts-1).
-\item[{\tt name}]
-Pointer to the location for the returned attribute name. The caller must allocate space for the
-                    returned string. The maximum possible length, in characters, of
-                    the string is given by the predefined constant {\tt CDI\_MAX\_NAME}.
-\item[{\tt typep}]
-Pointer to location for returned attribute type.
-\item[{\tt lenp}]
-Pointer to location for returned attribute number.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define an integer attribute: {\tt vlistDefAttInt}}
-\index{vlistDefAttInt}
-\label{vlistDefAttInt}
-
-The function {\tt vlistDefAttInt} defines an integer attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttInt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER type, INTEGER len, 
-                                    INTEGER ip)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt type}]
-External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}).
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt ip}]
-Pointer to one or more integer values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of an integer attribute: {\tt vlistInqAttInt}}
-\index{vlistInqAttInt}
-\label{vlistInqAttInt}
-
-The function {\tt vlistInqAttInt} gets the values(s) of an integer attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttInt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, INTEGER ip)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt ip}]
-Pointer location for returned integer attribute value(s).
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define a floating point attribute: {\tt vlistDefAttFlt}}
-\index{vlistDefAttFlt}
-\label{vlistDefAttFlt}
-
-The function {\tt vlistDefAttFlt} defines a floating point attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttFlt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER type, INTEGER len, 
-                                    REAL*8 dp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt type}]
-External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}).
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt dp}]
-Pointer to one or more floating point values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of a floating point attribute: {\tt vlistInqAttFlt}}
-\index{vlistInqAttFlt}
-\label{vlistInqAttFlt}
-
-The function {\tt vlistInqAttFlt} gets the values(s) of a floating point attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttFlt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, REAL*8 dp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt dp}]
-Pointer location for returned floating point attribute value(s).
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Define a text attribute: {\tt vlistDefAttTxt}}
-\index{vlistDefAttTxt}
-\label{vlistDefAttTxt}
-
-The function {\tt vlistDefAttTxt} defines a text attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistDefAttTxt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER len, 
-                                    CHARACTER*(*) tp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt len}]
-Number of values provided for the attribute.
-\item[{\tt tp}]
-Pointer to one or more character values.
-
-\end{deflist}
-\end{minipage}
-
-
-\subsection{Get the value(s) of a text attribute: {\tt vlistInqAttTxt}}
-\index{vlistInqAttTxt}
-\label{vlistInqAttTxt}
-
-The function {\tt vlistInqAttTxt} gets the values(s) of a text attribute.
-
-\subsubsection*{Usage}
-
-\begin{verbatim}
-    INTEGER FUNCTION vlistInqAttTxt(INTEGER vlistID, INTEGER varID, 
-                                    CHARACTER*(*) name, INTEGER mlen, 
-                                    CHARACTER*(*) tp)
-\end{verbatim}
-
-\hspace*{4mm}\begin{minipage}[]{15cm}
-\begin{deflist}{\tt vlistID\ }
-\item[{\tt vlistID}]
-Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}.
-\item[{\tt varID}]
-Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute.
-\item[{\tt name}]
-Attribute name.
-\item[{\tt mlen}]
-Number of allocated values provided for the attribute.
-\item[{\tt tp}]
-Pointer location for returned text attribute value(s).
-
-\end{deflist}
-\end{minipage}
diff --git a/examples/Makefile.in b/examples/Makefile.in
index 49afd2628e9024792dce33f2cc98053c4b8396bb..906edcab0bf34d1fd73a267b897047155ffe2e73 100644
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -314,11 +314,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -342,7 +340,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -424,7 +421,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/examples/pio/Makefile.in b/examples/pio/Makefile.in
index 1536458295266d33fa2ed9d9b5715fdcc9080852..5f27b589a10f670eec89094c1ad771d9a3278b13 100644
--- a/examples/pio/Makefile.in
+++ b/examples/pio/Makefile.in
@@ -308,11 +308,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -336,7 +334,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -418,7 +415,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/interfaces/Makefile.in b/interfaces/Makefile.in
index a7c5b60d9147d558d4a54ba07aa76f80ef61197c..49bc17892e09fdd44e4e509b88fd988c54a02bd0 100644
--- a/interfaces/Makefile.in
+++ b/interfaces/Makefile.in
@@ -292,11 +292,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -320,7 +318,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -402,7 +399,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/m4/acx_options.m4 b/m4/acx_options.m4
index 8782e5893883b0c57738dbc5c76303fd15394c35..ed3ebb4548ecac6acbc9e6fd9f9da85891bd1938 100644
--- a/m4/acx_options.m4
+++ b/m4/acx_options.m4
@@ -151,84 +151,6 @@ AC_SUBST([NETCDF_ROOT])
 AC_SUBST([NETCDF_INCLUDE])
 AC_SUBST([NETCDF_LIBS])
 #  ----------------------------------------------------------------------
-#  Link application with JASPER library (needed for GRIB2 compression)
-JASPER_LIBS=''
-AC_ARG_WITH([jasper],
-            [AS_HELP_STRING([--with-jasper=<directory>],
-                            [Specify location of JASPER library. You must specify its location if GRIB_API was built with JASPER.])],
-            [AS_CASE(["$with_jasper"],
-                     [no],[AC_MSG_CHECKING([for jasper library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS([jasper.h])
-                            AC_SEARCH_LIBS([jas_init],[jasper],[AC_DEFINE([HAVE_LIBJASPER],[1],[Define to 1 for JPEG compression for GRIB2])],
-                                           [AC_MSG_ERROR([Could not link to jasper library! Required for GRIB_API])])
-                            AC_SUBST([JASPER_LIBS],[" -ljasper"])],
-                     [*],[JASPER_ROOT=$with_jasper
-                          AS_IF([test -d "$JASPER_ROOT"],
-                                [LDFLAGS="$LDFLAGS -L$JASPER_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$JASPER_ROOT/include"
-                                 AC_SEARCH_LIBS([jas_stream_memopen],
-                                                [jasper],
-                                                [AC_DEFINE([HAVE_LIBJASPER],[1],[Define to 1 for JPEG compression for GRIB2])],
-                                                [AC_MSG_ERROR([Could not link to jasper library! Required for GRIB_API])])
-                                 JASPER_LIBS=" -L$JASPER_ROOT/lib -ljasper"],
-                                [AC_MSG_ERROR([$JASPER_ROOT is not a directory! JASPER suppressed])])])],
-            [AC_MSG_CHECKING([for the JASPER library])
-             AC_MSG_RESULT([suppressed])])
-AC_SUBST([JASPER_LIBS])
-#  ----------------------------------------------------------------------
-#  Link application with openjpeg library (needed for GRIB2 compression)
-OPENJPEG_LIBS=''
-AC_ARG_WITH([openjpeg],
-            [AS_HELP_STRING([--with-openjpeg=<directory>],
-                            [Specify location of openjpeg library. You must specify its location if GRIB_API was built with openjpeg.])],
-            [AS_CASE(["$with_openjpeg"],
-                     [no],[AC_MSG_CHECKING([for openjpeg library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS([openjpeg.h])
-                            AC_SEARCH_LIBS([opj_image_create],[openjpeg],[AC_DEFINE([HAVE_LIBOPENJPEG],[1],[Define to 1 for JPEG compression for GRIB2])],
-                                           [AC_MSG_ERROR([Could not link to openjpeg library! Required for GRIB_API])])
-                            AC_SUBST([openjpeg_LIBS],[" -lopenjpeg"])],
-                     [*],[OPENJPEG_ROOT=$with_openjpeg
-                          AS_IF([test -d "$OPENJPEG_ROOT"],
-                                [LDFLAGS="$LDFLAGS -L$OPENJPEG_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$OPENJPEG_ROOT/include"
-                                 AC_SEARCH_LIBS([opj_image_create],
-                                                [openjpeg],
-                                                [AC_DEFINE([HAVE_LIBOPENJPEG],[1],[Define to 1 for JPEG compression for GRIB2])],
-                                                [AC_MSG_ERROR([Could not link to openjpeg library! Required for GRIB_API])])
-                                 OPENJPEG_LIBS=" -L$OPENJPEG_ROOT/lib -lopenjpeg"],
-                                [AC_MSG_ERROR([$OPENJPEG_ROOT is not a directory! openjpeg suppressed])])])],
-            [AC_MSG_CHECKING([for the openjpeg library])
-             AC_MSG_RESULT([suppressed])])
-AC_SUBST([OPENJPEG_LIBS])
-#  ----------------------------------------------------------------------
-#  Link application with LIBPNG library (needed for GRIB2 compression)
-LIBPNG_LIBS=''
-AC_ARG_WITH([libpng],
-            [AS_HELP_STRING([--with-libpng=<directory>],
-                            [Specify location of LIBPNG library. You must specify its location if GRIB_API was built with LIBPNG.])],
-            [AS_CASE(["$with_libpng"],
-                     [no],[AC_MSG_CHECKING([for libpng library])
-                           AC_MSG_RESULT([suppressed])],
-                     [yes],[AC_CHECK_HEADERS([png.h])
-                            AC_SEARCH_LIBS([png_warning],[png],[AC_DEFINE([HAVE_LIBLIBPNG],[1],[Define to 1 for PNG compression for GRIB2])],
-                                           [AC_MSG_ERROR([Could not link to libpng library! Required for GRIB_API])])
-                            AC_SUBST([LIBPNG_LIBS],[" -lpng"])],
-                     [*],[LIBPNG_ROOT=$with_libpng
-                          AS_IF([test -d "$LIBPNG_ROOT"],
-                                [LDFLAGS="$LDFLAGS -L$LIBPNG_ROOT/lib"
-                                 CPPFLAGS="$CPPFLAGS -I$LIBPNG_ROOT/include"
-                                 AC_SEARCH_LIBS([png_warning],
-                                                [png],
-                                                [AC_DEFINE([HAVE_LIBLIBPNG],[1],[Define to 1 for PNG compression for GRIB2])],
-                                                [AC_MSG_ERROR([Could not link to libpng library! Required for GRIB_API])])
-                                 LIBPNG_LIBS=" -L$LIBPNG_ROOT/lib -lpng"],
-                                [AC_MSG_ERROR([$LIBPNG_ROOT is not a directory! LIBPNG suppressed])])])],
-            [AC_MSG_CHECKING([for the LIBPNG library])
-             AC_MSG_RESULT([suppressed])])
-AC_SUBST([LIBPNG_LIBS])
-#  ----------------------------------------------------------------------
 #  Compile application with GRIB_API library (for GRIB2 support)
 GRIB_API_INCLUDE=''
 GRIB_API_LIBS=''
diff --git a/src/Makefile.am b/src/Makefile.am
index bc78a1e965687f6810074ff676b09db9f3bb966d..0bdb6c46247208c9b485f72b221b5208ba493c64 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,6 +24,8 @@ libcdi_la_SOURCES = 	 \
 	cdf.h	 	 \
 	cdf_int.c	 \
 	cdf_int.h	 \
+	cdf_util.c	 \
+	cdf_util.h	 \
 	cdi.h	 	 \
 	cdi_error.c      \
 	cdi_limits.h	 \
@@ -71,7 +73,8 @@ libcdi_la_SOURCES = 	 \
 	resource_handle.h\
 	service.h	 \
 	servicelib.c     \
-	stream_cdf.c     \
+	stream_cdf_i.c   \
+	stream_cdf_o.c   \
 	stream_cdf.h	 \
 	stream_cgribex.c \
 	stream_cgribex.h \
@@ -83,8 +86,6 @@ libcdi_la_SOURCES = 	 \
 	stream_history.c \
 	stream_ieg.c     \
 	stream_ieg.h	 \
-	stream_fcommon.c \
-	stream_fcommon.h \
 	cdi_int.c        \
 	cdi_int.h	 \
 	stream_record.c  \
@@ -95,6 +96,8 @@ libcdi_la_SOURCES = 	 \
         grb_read.c       \
         cdf_write.c      \
         cdf_read.c       \
+        cdf_lazy_grid.c  \
+        cdf_lazy_grid.h  \
         subtype.c        \
         subtype.h        \
 	swap.h	 	 \
@@ -112,8 +115,8 @@ libcdi_la_SOURCES = 	 \
 	version.c      	 \
 	vlist.c 	 \
 	vlist.h	         \
-	vlist_att.c 	 \
-	vlist_att.h 	 \
+	cdi_att.c 	 \
+	cdi_att.h 	 \
 	vlist_var.c 	 \
 	vlist_var.h	 \
 	zaxis.c		 \
diff --git a/src/Makefile.in b/src/Makefile.in
index ec0a5dfcc0832e90f2e27022889cb27b0372b949..234a5d46f45d3ac46d56f25594a163057b0e4ff5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -168,26 +168,27 @@ LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libcdi_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
 am__libcdi_la_SOURCES_DIST = basetime.c basetime.h binary.c binary.h \
-	calendar.c calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h \
-	cdi_error.c cdi_limits.h cdi_util.c cgribex.h cgribexlib.c \
-	datetime.h dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c \
-	cdi_cksum.h cdi_uuid.h dtypes.h error.c error.h exse.h extra.h \
-	extralib.c file.c file.h gaussgrid.c gaussgrid.h gribapi.c \
-	gribapi.h gribapi_utilities.h grid.c grid.h ieg.h ieglib.c \
-	input_file.c input_file.h institution.c institution.h model.c \
-	model.h namespace.c namespace.h serialize.h serialize.c \
+	calendar.c calendar.h cdf.c cdf.h cdf_int.c cdf_int.h \
+	cdf_util.c cdf_util.h cdi.h cdi_error.c cdi_limits.h \
+	cdi_util.c cgribex.h cgribexlib.c datetime.h dmemory.c \
+	dmemory.h cksum.c cksum.h cdi_cksum.c cdi_cksum.h cdi_uuid.h \
+	dtypes.h error.c error.h exse.h extra.h extralib.c file.c \
+	file.h gaussgrid.c gaussgrid.h gribapi.c gribapi.h \
+	gribapi_utilities.h grid.c grid.h ieg.h ieglib.c input_file.c \
+	input_file.h institution.c institution.h model.c model.h \
+	namespace.c namespace.h serialize.h serialize.c \
 	referenceCounting.c referenceCounting.h resource_handle.c \
-	resource_handle.h service.h servicelib.c stream_cdf.c \
-	stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \
-	stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \
-	stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \
-	stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \
-	stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \
-	cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \
-	table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \
-	tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \
-	vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \
-	zaxis.h stream.c stream_write.c stream_read.c swap.c \
+	resource_handle.h service.h servicelib.c stream_cdf_i.c \
+	stream_cdf_o.c stream_cdf.h stream_cgribex.c stream_cgribex.h \
+	stream_ext.c stream_ext.h stream_grb.c stream_grb.h \
+	stream_gribapi.h stream_history.c stream_ieg.c stream_ieg.h \
+	cdi_int.c cdi_int.h stream_record.c stream_srv.c stream_srv.h \
+	stream_var.c grb_write.c grb_read.c cdf_write.c cdf_read.c \
+	cdf_lazy_grid.c cdf_lazy_grid.h subtype.c subtype.h swap.h \
+	table.c table.h tablepar.h taxis.c taxis.h timebase.c \
+	timebase.h tsteps.c util.c varscan.c varscan.h version.c \
+	vlist.c vlist.h cdi_att.c cdi_att.h vlist_var.c vlist_var.h \
+	zaxis.c zaxis.h stream.c stream_write.c stream_read.c swap.c \
 	iterator.c iterator.h iterator_fallback.c iterator_fallback.h \
 	iterator_grib.c iterator_grib.h cfortran.h cdiFortran.c \
 	gribapi_utilities.c stream_gribapi.c
@@ -196,20 +197,20 @@ am__objects_1 = cdiFortran.lo
 am__objects_3 = gribapi_utilities.lo stream_gribapi.lo
 @HAVE_LIBGRIB_API_TRUE@am__objects_4 = $(am__objects_3)
 am_libcdi_la_OBJECTS = basetime.lo binary.lo calendar.lo cdf.lo \
-	cdf_int.lo cdi_error.lo cdi_util.lo cgribexlib.lo dmemory.lo \
-	cksum.lo cdi_cksum.lo error.lo extralib.lo file.lo \
+	cdf_int.lo cdf_util.lo cdi_error.lo cdi_util.lo cgribexlib.lo \
+	dmemory.lo cksum.lo cdi_cksum.lo error.lo extralib.lo file.lo \
 	gaussgrid.lo gribapi.lo grid.lo ieglib.lo input_file.lo \
 	institution.lo model.lo namespace.lo serialize.lo \
 	referenceCounting.lo resource_handle.lo servicelib.lo \
-	stream_cdf.lo stream_cgribex.lo stream_ext.lo stream_grb.lo \
-	stream_history.lo stream_ieg.lo stream_fcommon.lo cdi_int.lo \
-	stream_record.lo stream_srv.lo stream_var.lo grb_write.lo \
-	grb_read.lo cdf_write.lo cdf_read.lo subtype.lo table.lo \
-	taxis.lo timebase.lo tsteps.lo util.lo varscan.lo version.lo \
-	vlist.lo vlist_att.lo vlist_var.lo zaxis.lo stream.lo \
-	stream_write.lo stream_read.lo swap.lo iterator.lo \
-	iterator_fallback.lo iterator_grib.lo $(am__objects_2) \
-	$(am__objects_4)
+	stream_cdf_i.lo stream_cdf_o.lo stream_cgribex.lo \
+	stream_ext.lo stream_grb.lo stream_history.lo stream_ieg.lo \
+	cdi_int.lo stream_record.lo stream_srv.lo stream_var.lo \
+	grb_write.lo grb_read.lo cdf_write.lo cdf_read.lo \
+	cdf_lazy_grid.lo subtype.lo table.lo taxis.lo timebase.lo \
+	tsteps.lo util.lo varscan.lo version.lo vlist.lo cdi_att.lo \
+	vlist_var.lo zaxis.lo stream.lo stream_write.lo stream_read.lo \
+	swap.lo iterator.lo iterator_fallback.lo iterator_grib.lo \
+	$(am__objects_2) $(am__objects_4)
 libcdi_la_OBJECTS = $(am_libcdi_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -377,11 +378,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -405,7 +404,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -487,7 +485,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
@@ -511,29 +508,29 @@ noinst_LTLIBRARIES = libcdiresunpack.la $(am__append_1) \
 @ENABLE_CDI_LIB_TRUE@include_HEADERS = cdi.h cdi.inc $(am__append_5)
 AM_CFLAGS = $(PPM_CORE_CFLAGS) $(YAXT_CFLAGS) $(MPI_C_INCLUDE)
 libcdi_la_SOURCES = basetime.c basetime.h binary.c binary.h calendar.c \
-	calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h cdi_error.c \
-	cdi_limits.h cdi_util.c cgribex.h cgribexlib.c datetime.h \
-	dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c cdi_cksum.h \
-	cdi_uuid.h dtypes.h error.c error.h exse.h extra.h extralib.c \
-	file.c file.h gaussgrid.c gaussgrid.h gribapi.c gribapi.h \
-	gribapi_utilities.h grid.c grid.h ieg.h ieglib.c input_file.c \
-	input_file.h institution.c institution.h model.c model.h \
-	namespace.c namespace.h serialize.h serialize.c \
-	referenceCounting.c referenceCounting.h resource_handle.c \
-	resource_handle.h service.h servicelib.c stream_cdf.c \
+	calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdf_util.c \
+	cdf_util.h cdi.h cdi_error.c cdi_limits.h cdi_util.c cgribex.h \
+	cgribexlib.c datetime.h dmemory.c dmemory.h cksum.c cksum.h \
+	cdi_cksum.c cdi_cksum.h cdi_uuid.h dtypes.h error.c error.h \
+	exse.h extra.h extralib.c file.c file.h gaussgrid.c \
+	gaussgrid.h gribapi.c gribapi.h gribapi_utilities.h grid.c \
+	grid.h ieg.h ieglib.c input_file.c input_file.h institution.c \
+	institution.h model.c model.h namespace.c namespace.h \
+	serialize.h serialize.c referenceCounting.c \
+	referenceCounting.h resource_handle.c resource_handle.h \
+	service.h servicelib.c stream_cdf_i.c stream_cdf_o.c \
 	stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \
 	stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \
-	stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \
-	stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \
-	stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \
-	cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \
-	table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \
-	tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \
-	vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \
-	zaxis.h stream.c stream_write.c stream_read.c swap.c \
-	iterator.c iterator.h iterator_fallback.c iterator_fallback.h \
-	iterator_grib.c iterator_grib.h $(am__append_2) \
-	$(am__append_3)
+	stream_history.c stream_ieg.c stream_ieg.h cdi_int.c cdi_int.h \
+	stream_record.c stream_srv.c stream_srv.h stream_var.c \
+	grb_write.c grb_read.c cdf_write.c cdf_read.c cdf_lazy_grid.c \
+	cdf_lazy_grid.h subtype.c subtype.h swap.h table.c table.h \
+	tablepar.h taxis.c taxis.h timebase.c timebase.h tsteps.c \
+	util.c varscan.c varscan.h version.c vlist.c vlist.h cdi_att.c \
+	cdi_att.h vlist_var.c vlist_var.h zaxis.c zaxis.h stream.c \
+	stream_write.c stream_read.c swap.c iterator.c iterator.h \
+	iterator_fallback.c iterator_fallback.h iterator_grib.c \
+	iterator_grib.h $(am__append_2) $(am__append_3)
 
 # cfortran.h is an optional part of libcdi
 libcdi_la_USE_FC_extra_sources = \
@@ -692,9 +689,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calendar.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_int.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_lazy_grid.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_read.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_write.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdiFortran.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_att.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_cksum.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_error.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_int.Plo@am__quote@
@@ -747,10 +747,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialize.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/servicelib.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf_i.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf_o.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cgribex.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_ext.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_fcommon.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_grb.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_gribapi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_history.Plo@am__quote@
@@ -770,7 +770,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varscan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist_att.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist_var.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zaxis.Plo@am__quote@
 
diff --git a/src/basetime.c b/src/basetime.c
index 3d4d5e3661934d471ff905ef30ed5c41a3e6f4e0..ff4cd8aad7fb405d0cd3e736f4671007a9fae9b8 100644
--- a/src/basetime.c
+++ b/src/basetime.c
@@ -3,6 +3,7 @@
 #endif
 
 #include <stdio.h>
+#include <stdbool.h>
 
 #include "error.h"
 #include "cdi.h"
@@ -20,7 +21,7 @@ void basetimeInit(basetime_t *basetime)
   basetime->ncdimid       = UNDEFID;
   basetime->ncvarboundsid = UNDEFID;
   basetime->leadtimeid    = UNDEFID;
-  basetime->lwrf          = 0;
+  basetime->lwrf          = false;
   basetime->timevar_cache = NULL;
 }
 /*
diff --git a/src/basetime.h b/src/basetime.h
index 8a56f5a7e88761ea68306a61db147ff078913b8c..a5a96316fe01d2bd47dd2ac2a48e8a843d2a2c9b 100644
--- a/src/basetime.h
+++ b/src/basetime.h
@@ -1,6 +1,8 @@
 #ifndef _BASETIME_H
 #define _BASETIME_H
 
+#include <stdbool.h>
+
 //#define USE_TIMECACHE 1
 #define MAX_TIMECACHE_SIZE 1024
 
@@ -17,7 +19,7 @@ typedef struct {
   int   ncdimid;
   int   ncvarboundsid;
   int   leadtimeid;
-  int   lwrf;     /* TRUE for time axis in WRF format */
+  bool  lwrf;     /* true for time axis in WRF format */
   timecache_t *timevar_cache;
 }
 basetime_t;
diff --git a/src/cdf.c b/src/cdf.c
index 6fb0a85528b16425f3164919830fe574ccf99373..ce640b9e84dc69eeeb2c8efb7b175aca78d89db4 100644
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -129,7 +129,7 @@ static int cdfOpenFile(const char *filename, const char *mode, int *filetype)
 #endif
 	  cdf_create(filename, writemode, &ncid);
 	  if ( CDI_Version_Info ) cdfComment(ncid);
-          cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.4");
+          cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.6");
 	  break;
 	case 'a':
 	  cdf_open(filename, NC_WRITE, &ncid);
diff --git a/src/cdf_lazy_grid.c b/src/cdf_lazy_grid.c
new file mode 100644
index 0000000000000000000000000000000000000000..41d26bf32eb5dd752b74b684be91353631b14bbf
--- /dev/null
+++ b/src/cdf_lazy_grid.c
@@ -0,0 +1,528 @@
+#include "stream_cdf.h"
+#include "cdf_lazy_grid.h"
+
+
+static struct gridVirtTable cdfLazyGridVtable;
+double *cdfPendingLoad;
+#ifdef HAVE_LIBPTHREAD
+static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT;
+#else
+static bool cdfLazyInitialized;
+#endif
+
+
+#ifdef HAVE_LIBPTHREAD
+#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize))
+#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize))
+#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize))
+#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL)
+#else
+#define lock_lazy_load(plGrid)
+#define unlock_lazy_load(plGrid)
+#define destroy_lazy_load_lock(plGrid)
+#define init_lazy_load_lock(plGrid)
+#endif
+
+
+void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid)
+{
+  if (lazyGrid->base.area == cdfPendingLoad)  lazyGrid->base.area = NULL;
+  if (lazyGrid->base.x.vals == cdfPendingLoad) lazyGrid->base.x.vals = NULL;
+  if (lazyGrid->base.y.vals == cdfPendingLoad) lazyGrid->base.y.vals = NULL;
+  if (lazyGrid->base.x.bounds == cdfPendingLoad) lazyGrid->base.x.bounds = NULL;
+  if (lazyGrid->base.y.bounds == cdfPendingLoad) lazyGrid->base.y.bounds = NULL;
+  destroy_lazy_load_lock(lazyGrid);
+}
+
+static void cdfLazyGridDelete(grid_t *grid)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy;
+  cdfLazyGridDestroy(cdfGrid);
+  baseDestroy(grid);
+}
+
+static void cdfLazyGridDestroyOnce(void)
+{
+  /*
+#ifdef HAVE_MMAP
+  size_t pgSize = cdiGetPageSize(false);
+  munmap(cdfPendingLoad, pgSize);
+#endif
+  */
+}
+
+static void
+cdfLazyGridDefArea(grid_t *grid, const double *area)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(cdfGrid);
+  if (grid->area == cdfPendingLoad)
+    grid->area = NULL;
+  cdfGrid->cellAreaGet.datasetNCId = -1;
+  cdfGrid->cellAreaGet.varNCId = -1;
+  cdfGrid->baseVtable->defArea(grid, area);
+  unlock_lazy_load(cdfGrid);
+}
+
+
+static const double *
+cdfLazyGridInqAreaPtr(grid_t *grid)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  if (grid->area == cdfPendingLoad)
+    {
+      grid->area = (double *)Malloc((size_t)grid->size * sizeof(double));
+      cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId,
+                         lazyGrid->cellAreaGet.varNCId, grid->area);
+    }
+  unlock_lazy_load(lazyGrid);
+  return lazyGrid->baseVtable->inqAreaPtr(grid);
+}
+
+static void
+cdfLazyGridInqArea(grid_t *grid, double *area)
+{
+  grid->vtable->inqAreaPtr(grid);
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lazyGrid->baseVtable->inqArea(grid, area);
+}
+
+
+static void
+cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp)
+{
+  double *grid_vals
+    = (double *)Malloc(valsGet->size * sizeof (double));
+  *valsp = grid_vals;
+  if ( valsGet->ndims == 3 )
+    cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId,
+                        valsGet->start, valsGet->count, grid_vals);
+  else
+    cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals);
+  cdf_scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor);
+}
+
+static const double *
+cdfLazyGridInqXValsPtr(grid_t *grid)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  if (grid->x.vals == cdfPendingLoad)
+    cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->x.vals);
+  unlock_lazy_load(lazyGrid);
+  return lazyGrid->baseVtable->inqXValsPtr(grid);
+}
+
+static const double *
+cdfLazyGridInqYValsPtr(grid_t *grid)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  if (grid->y.vals == cdfPendingLoad)
+    cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->y.vals);
+  unlock_lazy_load(lazyGrid);
+  return lazyGrid->baseVtable->inqYValsPtr(grid);
+}
+
+static double
+cdfLazyGridInqXYVal(grid_t *grid, size_t index,
+                    const struct xyValGet *valsGet, double *vals,
+                    const double *(*inqValsPtr)(grid_t *gridptr))
+{
+  size_t size = valsGet->size;
+  double v;
+  if ( vals == cdfPendingLoad )
+    {
+      /* prevent full load if only first/last values get inspected */
+      if ( index == 0 || index == size - 1 )
+        {
+          size_t indexND[3];
+          if ( valsGet->ndims == 3 )
+            {
+              indexND[0] = 0;
+              indexND[1] = index / valsGet->count[2];
+              indexND[2] = index % valsGet->count[2];
+            }
+          else if ( valsGet->ndims == 2)
+            {
+              indexND[0] = index / (size_t)grid->x.size;
+              indexND[1] = index % (size_t)grid->x.size;
+            }
+          else
+            indexND[0] = index;
+          cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId, indexND, &v);
+        }
+      else
+        {
+          const double *grid_vals = inqValsPtr(grid);
+          v = grid_vals[index];
+        }
+    }
+  else if ( vals )
+    v = vals[index];
+  else
+    v = 0.0;
+  return v;
+}
+
+static void
+cdfLazyGridDefXVals(grid_t *grid, const double *vals)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(cdfGrid);
+  if (grid->x.vals == cdfPendingLoad)
+    grid->x.vals = NULL;
+  cdfGrid->xValsGet.datasetNCId = -1;
+  cdfGrid->xValsGet.varNCId = -1;
+  cdfGrid->baseVtable->defXVals(grid, vals);
+  unlock_lazy_load(cdfGrid);
+}
+
+static void
+cdfLazyGridDefYVals(grid_t *grid, const double *vals)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(cdfGrid);
+  if (grid->y.vals == cdfPendingLoad)
+    grid->y.vals = NULL;
+  cdfGrid->yValsGet.datasetNCId = -1;
+  cdfGrid->yValsGet.varNCId = -1;
+  cdfGrid->baseVtable->defYVals(grid, vals);
+  unlock_lazy_load(cdfGrid);
+}
+
+static double
+cdfLazyGridInqXVal(grid_t *grid, int index)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet,
+                                  grid->x.vals, grid->vtable->inqXValsPtr);
+  unlock_lazy_load(lazyGrid);
+  return rv;
+}
+
+static double
+cdfLazyGridInqYVal(grid_t *grid, int index)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet,
+                                  grid->y.vals, grid->vtable->inqYValsPtr);
+  unlock_lazy_load(lazyGrid);
+  return rv;
+}
+
+static bool
+cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
+                       struct cdfLazyGrid *lazyGridTest)
+{
+  struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet,
+    *valsGetYRef = &lazyGridRef->yValsGet,
+    *valsGetXTest = &lazyGridTest->xValsGet,
+    *valsGetYTest = &lazyGridTest->yValsGet;
+  if (valsGetXRef->datasetNCId == -1
+      || valsGetXTest->datasetNCId == -1
+      || valsGetYRef->datasetNCId == -1
+      || valsGetYTest->datasetNCId == -1)
+    return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base,
+                                                  &lazyGridTest->base);
+  return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId
+    ||   valsGetXRef->varNCId     != valsGetXTest->varNCId
+    ||   valsGetYRef->datasetNCId != valsGetYTest->datasetNCId
+    ||   valsGetYRef->varNCId     != valsGetYTest->varNCId;
+}
+
+static bool
+cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
+{
+  bool diff;
+  struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+  if (gridTest->vtable == &cdfLazyGridVtable)
+    diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+  else
+    diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest);
+  return diff;
+}
+
+static bool
+cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest)
+{
+  bool diff;
+  struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+  if (gridTest->vtable == &cdfLazyGridVtable)
+    diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+  else
+    diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest);
+  return diff;
+}
+
+
+static const double *
+cdfLazyGridInqXBoundsPtr(grid_t *grid)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  if (grid->x.bounds == cdfPendingLoad)
+    {
+      grid->x.bounds = (double *)Malloc((size_t)grid->nvertex
+                                       * (size_t)grid->size * sizeof(double));
+      cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId,
+                         lazyGrid->xBoundsGet.varNCId, grid->x.bounds);
+    }
+  unlock_lazy_load(lazyGrid);
+  return lazyGrid->baseVtable->inqXBoundsPtr(grid);
+}
+
+static void
+cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(cdfGrid);
+  if (grid->x.bounds == cdfPendingLoad)
+    grid->x.bounds = NULL;
+  cdfGrid->xBoundsGet.datasetNCId = -1;
+  cdfGrid->xBoundsGet.varNCId = -1;
+  cdfGrid->baseVtable->defXBounds(grid, xbounds);
+  unlock_lazy_load(cdfGrid);
+}
+
+static void
+cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds)
+{
+  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(cdfGrid);
+  if (grid->y.bounds == cdfPendingLoad)
+    grid->y.bounds = NULL;
+  cdfGrid->yBoundsGet.datasetNCId = -1;
+  cdfGrid->yBoundsGet.varNCId = -1;
+  cdfGrid->baseVtable->defYBounds(grid, ybounds);
+  unlock_lazy_load(cdfGrid);
+}
+
+static const double *
+cdfLazyGridInqYBoundsPtr(grid_t *grid)
+{
+  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+  lock_lazy_load(lazyGrid);
+  if (grid->y.bounds == cdfPendingLoad)
+    {
+      grid->y.bounds = (double *)Malloc((size_t)grid->nvertex
+                                       * (size_t)grid->size * sizeof(double));
+      cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId,
+                         lazyGrid->yBoundsGet.varNCId, grid->y.bounds);
+    }
+  unlock_lazy_load(lazyGrid);
+  return lazyGrid->baseVtable->inqYBoundsPtr(grid);
+}
+
+static void
+cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+  struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup,
+    *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig;
+  lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+  lazyGridDup->baseVtable = lazyGridOrig->baseVtable;
+  lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet;
+  lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet;
+  lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet;
+  lazyGridDup->xValsGet = lazyGridOrig->xValsGet;
+  lazyGridDup->yValsGet = lazyGridOrig->yValsGet;
+  init_lazy_load_lock(lazyGridDup);
+}
+
+static void
+cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+  size_t nrowlon = (size_t)gridptrOrig->nrowlon;
+  size_t gridsize = (size_t)gridptrOrig->size;
+  int gridtype = gridptrOrig->type;
+  int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
+  if ( nrowlon )
+    {
+      gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+      memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
+    }
+
+  if ( gridptrOrig->x.vals != NULL && gridptrOrig->x.vals != cdfPendingLoad )
+    {
+      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->x.size;
+
+      gridptrDup->x.vals = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->x.vals, gridptrOrig->x.vals, size * sizeof (double));
+    }
+
+  if ( gridptrOrig->y.vals != NULL && gridptrOrig->y.vals != cdfPendingLoad )
+    {
+      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->y.size;
+
+      gridptrDup->y.vals = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->y.vals, gridptrOrig->y.vals, size * sizeof (double));
+    }
+
+  if ( gridptrOrig->x.bounds != NULL && gridptrOrig->x.bounds != cdfPendingLoad )
+    {
+      size_t size  = (irregular ? gridsize : (size_t)gridptrOrig->x.size)
+        * (size_t)gridptrOrig->nvertex;
+
+      gridptrDup->x.bounds = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->x.bounds, gridptrOrig->x.bounds, size * sizeof (double));
+    }
+
+  if ( gridptrOrig->y.bounds != NULL && gridptrOrig->y.bounds != cdfPendingLoad )
+    {
+      size_t size = (irregular ? gridsize : (size_t)gridptrOrig->y.size)
+        * (size_t)gridptrOrig->nvertex;
+
+      gridptrDup->y.bounds = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->y.bounds, gridptrOrig->y.bounds, size * sizeof (double));
+    }
+
+  {
+    if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad )
+      {
+        size_t size = gridsize;
+
+        gridptrDup->area = (double *)Malloc(size * sizeof (double));
+        memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double));
+      }
+  }
+
+  if ( gridptrOrig->mask != NULL )
+    {
+      size_t size = gridsize;
+
+      gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
+      memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
+    }
+
+  if ( gridptrOrig->mask_gme != NULL )
+    {
+      size_t size = gridsize;
+
+      gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
+      memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
+    }
+}
+
+static grid_t *
+cdfLazyGridCopy(grid_t *gridptrOrig)
+{
+  struct cdfLazyGrid *lazyGridDup
+    = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup));
+  gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+  gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base);
+  return &lazyGridDup->base;
+}
+
+static void
+cdfLazyGridInitOnce(void)
+{
+  cdfLazyGridVtable = cdiGridVtable;
+  cdfLazyGridVtable.destroy = cdfLazyGridDelete;
+  cdfLazyGridVtable.copy = cdfLazyGridCopy;
+  cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields;
+  cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields;
+  cdfLazyGridVtable.defArea = cdfLazyGridDefArea;
+  cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr;
+  cdfLazyGridVtable.inqArea = cdfLazyGridInqArea;
+  cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr;
+  cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr;
+  cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal;
+  cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal;
+  cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals;
+  cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals;
+  cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull;
+  cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO;
+  cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds;
+  cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds;
+  cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr;
+  cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr;
+  /* create inaccessible memory area, if possible, this serves as
+   * dummy value for pointers to data not yet loaded */
+  /*
+#ifdef HAVE_MMAP
+  {
+    size_t pgSize = cdiGetPageSize(false);
+    static const char devZero[] = "/dev/zero";
+    int fd = open(devZero, O_RDWR);
+    if (fd == -1)
+      SysError("Could not open %s to map anonymous memory", devZero);
+    void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0);
+    if (cdfInvalid == MAP_FAILED)
+      SysError("Could not mmap anonymous memory");
+    cdfPendingLoad = cdfInvalid;
+    int rc = close(fd);
+    if (rc == -1)
+      SysError("Could not close %s file handle %d after mapping anonymous"
+               " memory", devZero, fd);
+  }
+#else
+  */
+  cdfPendingLoad = (double *)&cdfPendingLoad;
+  //#endif
+  atexit(cdfLazyGridDestroyOnce);
+#ifndef HAVE_LIBPTHREAD
+  cdfLazyInitialized = true;
+#endif
+}
+
+static void
+cdfBaseGridInit(grid_t *grid, int gridtype)
+{
+  grid_init(grid);
+  cdiGridTypeInit(grid, gridtype, 0);
+}
+
+static void
+cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype)
+{
+#ifdef HAVE_LIBPTHREAD
+  pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce);
+#else
+  if (cdfLazyInitialized) ; else cdfLazyGridInitOnce();
+#endif
+  cdfBaseGridInit(&grid->base, gridtype);
+  grid->baseVtable = grid->base.vtable;
+  grid->cellAreaGet.datasetNCId = -1;
+  grid->cellAreaGet.varNCId = -1;
+  grid->xValsGet.datasetNCId = -1;
+  grid->xValsGet.varNCId = -1;
+  grid->yValsGet.datasetNCId = -1;
+  grid->yValsGet.varNCId = -1;
+  grid->xBoundsGet.datasetNCId = -1;
+  grid->xBoundsGet.varNCId = -1;
+  grid->yBoundsGet.datasetNCId = -1;
+  grid->yBoundsGet.varNCId = -1;
+  grid->base.vtable = &cdfLazyGridVtable;
+  init_lazy_load_lock(grid);
+}
+
+
+void cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+  struct cdfLazyGrid *restrict grid = *gridpptr;
+  if (!grid)
+    *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid));
+  cdfLazyGridInit(grid, gridtype);
+}
+
+
+void cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+  struct cdfLazyGrid *restrict grid = *gridpptr;
+  if (!grid)
+    *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t));
+  cdfBaseGridInit((grid_t*)grid, gridtype);
+}
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/cdf_lazy_grid.h b/src/cdf_lazy_grid.h
new file mode 100644
index 0000000000000000000000000000000000000000..3da5ca0d791edb6c455a63b8e193a7213aedd1b6
--- /dev/null
+++ b/src/cdf_lazy_grid.h
@@ -0,0 +1,60 @@
+#ifndef  CDF_LAZY_GRID_H_
+#define  CDF_LAZY_GRID_H_
+
+#if defined (HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#ifdef HAVE_MMAP
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+#endif
+
+#include <string.h>
+
+#include "dmemory.h"
+#include "cdf_int.h"
+#include "grid.h"
+
+struct cdfLazyGrid
+{
+  grid_t base;
+  const struct gridVirtTable *baseVtable;
+  struct cdfLazyGridIds {
+    int datasetNCId, varNCId;
+  } cellAreaGet, xBoundsGet, yBoundsGet;
+  struct xyValGet {
+    double scalefactor, addoffset;
+    size_t start[3], count[3], size, dimsize;
+    int datasetNCId, varNCId;
+    short ndims;
+  } xValsGet, yValsGet;
+#ifdef HAVE_LIBPTHREAD
+  pthread_mutex_t loadSerialize;
+#endif
+};
+
+
+extern double *cdfPendingLoad;
+
+void cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype);
+void cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype);
+
+void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid);
+
+#endif
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/cdf_util.c b/src/cdf_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..43ac749898b2339880e81b2f4d4179f2189aa429
--- /dev/null
+++ b/src/cdf_util.c
@@ -0,0 +1,332 @@
+#include <string.h>
+#include <ctype.h>
+#include "dmemory.h"
+#include "cdi.h"
+#include "cdf_util.h"
+#include "error.h"
+
+
+void str_tolower(char *str)
+{
+  if ( str )
+    for ( size_t i = 0; str[i]; ++i )
+      str[i] = (char)tolower((int)str[i]);
+}
+
+
+int get_timeunit(size_t len, const char *ptu)
+{
+  int timeunit = -1;
+
+  if ( len > 2 )
+    {
+      if      ( memcmp(ptu, "sec",    3) == 0 )          timeunit = TUNIT_SECOND;
+      else if ( memcmp(ptu, "minute", 6) == 0 )          timeunit = TUNIT_MINUTE;
+      else if ( memcmp(ptu, "hour",   4) == 0 )          timeunit = TUNIT_HOUR;
+      else if ( memcmp(ptu, "day",    3) == 0 )          timeunit = TUNIT_DAY;
+      else if ( memcmp(ptu, "month",  5) == 0 )          timeunit = TUNIT_MONTH;
+      else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH;
+      else if ( memcmp(ptu, "year",   4) == 0 )          timeunit = TUNIT_YEAR;
+    }
+  else if ( len == 1 )
+    {
+      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
+    }
+
+  return timeunit;
+}
+
+
+bool is_time_units(const char *timeunits)
+{
+  bool status = strncmp(timeunits, "sec",    3) == 0
+             || strncmp(timeunits, "minute", 6) == 0
+             || strncmp(timeunits, "hour",   4) == 0
+             || strncmp(timeunits, "day",    3) == 0
+             || strncmp(timeunits, "month",  5) == 0;
+
+  return status;
+}
+
+
+bool is_timeaxis_units(const char *timeunits)
+{
+  bool status = false;
+
+  size_t len = strlen(timeunits);
+  char *tu = (char *) Malloc((len+1)*sizeof(char));
+  memcpy(tu, timeunits, (len+1) * sizeof(char));
+  char *ptu = tu;
+
+  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
+
+  int timeunit = get_timeunit(len, ptu);
+  if ( timeunit != -1 )
+    {
+      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+      if ( *ptu )
+        {
+          while ( isspace(*ptu) ) ptu++;
+
+          int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE :
+            memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1;
+
+          status = timetype != -1;
+        }
+    }
+
+  Free(tu);
+
+  return status;
+}
+
+
+bool is_height_units(const char *units)
+{
+  bool status = false;
+  int u0 = units[0];
+
+  if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) ||
+       (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) )
+    {
+      status = true;
+    }
+
+  return status;
+}
+
+
+bool is_pressure_units(const char *units)
+{
+  bool status = false;
+
+  if ( strncmp(units, "millibar", 8) == 0 ||
+       strncmp(units, "mb", 2)       == 0 ||
+       strncmp(units, "hectopas", 8) == 0 ||
+       strncmp(units, "hPa", 3)      == 0 ||
+       strncmp(units, "Pa", 2)       == 0 )
+    {
+      status = true;
+    }
+
+  return status;
+}
+
+
+bool is_DBL_axis(/*const char *units,*/ const char *longname)
+{
+  bool status = false;
+
+  if ( strcmp(longname, "depth below land")         == 0 ||
+       strcmp(longname, "depth_below_land")         == 0 ||
+       strcmp(longname, "levels below the surface") == 0 )
+    {
+      /*
+      if ( strcmp(ncvars[ncvarid].units, "cm") == 0 ||
+           strcmp(ncvars[ncvarid].units, "dm") == 0 ||
+           strcmp(ncvars[ncvarid].units, "m")  == 0 )
+      */
+        status = true;
+    }
+
+  return status;
+}
+
+
+bool is_depth_axis(const char *stdname, const char *longname)
+{
+  bool status = false;
+
+  if ( strcmp(stdname, "depth") == 0 )
+    status = true;
+  else
+    if ( strcmp(longname, "depth_below_sea") == 0 ||
+         strcmp(longname, "depth below sea") == 0 )
+      {
+        status = true;
+      }
+
+  return status;
+}
+
+
+bool is_height_axis(const char *stdname, const char *longname)
+{
+  bool status = false;
+
+  if ( strcmp(stdname, "height") == 0 )
+    status = true;
+  else
+    if ( strcmp(longname, "height") == 0 ||
+         strcmp(longname, "height above the surface") == 0 )
+      {
+        status = true;
+      }
+
+  return status;
+}
+
+
+bool is_lon_axis(const char *units, const char *stdname)
+{
+  bool status = false;
+  char lc_units[16];
+
+  memcpy(lc_units, units, 15);
+  lc_units[15] = 0;
+  str_tolower(lc_units);
+
+  if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
+        (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) )
+    {
+      status = true;
+    }
+
+  if ( status == false &&
+       memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) &&
+       memcmp(lc_units, "degree", 6) == 0 )
+    {
+      int ioff = 6;
+      if ( lc_units[ioff] == 's' ) ioff++;
+      if ( lc_units[ioff] == '_' ) ioff++;
+      if ( lc_units[ioff] == 'e' ) status = true;
+    }
+
+  return status;
+}
+
+
+bool is_lat_axis(const char *units, const char *stdname)
+{
+  bool status = false;
+  char lc_units[16];
+
+  memcpy(lc_units, units, 15);
+  lc_units[15] = 0;
+  str_tolower(lc_units);
+
+  if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
+        (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) )
+    {
+      status = true;
+    }
+
+  if ( status == false &&
+       memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) &&
+       memcmp(lc_units, "degree", 6) == 0 )
+    {
+      int ioff = 6;
+      if ( lc_units[ioff] == 's' ) ioff++;
+      if ( lc_units[ioff] == '_' ) ioff++;
+      if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true;
+    }
+
+  return status;
+}
+
+
+bool is_x_axis(const char *units, const char *stdname)
+{
+  bool status = false;
+
+  if ( strcmp(stdname, "projection_x_coordinate") == 0  ) status = true;
+
+  return status;
+}
+
+
+bool is_y_axis(const char *units, const char *stdname)
+{
+  bool status = false;
+
+  if ( strcmp(stdname, "projection_y_coordinate") == 0  ) status = true;
+
+  return status;
+}
+
+
+void set_gridtype(const char *attstring, int *gridtype)
+{
+  if      ( strcmp(attstring, "gaussian reduced") == 0 )
+    *gridtype = GRID_GAUSSIAN_REDUCED;
+  else if ( strcmp(attstring, "gaussian") == 0 )
+    *gridtype = GRID_GAUSSIAN;
+  else if ( strncmp(attstring, "spectral", 8) == 0 )
+    *gridtype = GRID_SPECTRAL;
+  else if ( strncmp(attstring, "fourier", 7) == 0 )
+    *gridtype = GRID_FOURIER;
+  else if ( strcmp(attstring, "trajectory") == 0 )
+    *gridtype = GRID_TRAJECTORY;
+  else if ( strcmp(attstring, "generic") == 0 )
+    *gridtype = GRID_GENERIC;
+  else if ( strcmp(attstring, "cell") == 0 )
+    *gridtype = GRID_UNSTRUCTURED;
+  else if ( strcmp(attstring, "unstructured") == 0 )
+    *gridtype = GRID_UNSTRUCTURED;
+  else if ( strcmp(attstring, "curvilinear") == 0 )
+    *gridtype = GRID_CURVILINEAR;
+  else if ( strcmp(attstring, "sinusoidal") == 0 )
+    ;
+  else if ( strcmp(attstring, "laea") == 0 )
+    ;
+  else if ( strcmp(attstring, "lcc2") == 0 )
+    ;
+  else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear
+    ;
+  else
+    {
+      static bool warn = true;
+      if ( warn )
+        {
+          warn = false;
+          Warning("NetCDF attribute grid_type='%s' unsupported!", attstring);
+        }
+    }
+}
+
+
+void set_zaxistype(const char *attstring, int *zaxistype)
+{
+  if      ( strcmp(attstring, "toa") == 0 ) *zaxistype = ZAXIS_TOA;
+  else if ( strcmp(attstring, "cloudbase") == 0 ) *zaxistype = ZAXIS_CLOUD_BASE;
+  else if ( strcmp(attstring, "cloudtop") == 0 ) *zaxistype = ZAXIS_CLOUD_TOP;
+  else if ( strcmp(attstring, "isotherm0") == 0 ) *zaxistype = ZAXIS_ISOTHERM_ZERO;
+  else if ( strcmp(attstring, "seabottom") == 0 ) *zaxistype = ZAXIS_SEA_BOTTOM;
+  else if ( strcmp(attstring, "lakebottom") == 0 ) *zaxistype = ZAXIS_LAKE_BOTTOM;
+  else if ( strcmp(attstring, "sedimentbottom") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM;
+  else if ( strcmp(attstring, "sedimentbottomta") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;
+  else if ( strcmp(attstring, "sedimentbottomtw") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;
+  else if ( strcmp(attstring, "mixlayer") == 0 ) *zaxistype = ZAXIS_MIX_LAYER;
+  else if ( strcmp(attstring, "atmosphere") == 0 ) *zaxistype = ZAXIS_ATMOSPHERE;
+  else
+    {
+      static bool warn = true;
+      if ( warn )
+        {
+          warn = false;
+          Warning("NetCDF attribute level_type='%s' unsupported!", attstring);
+        }
+    }  
+}
+
+
+void set_calendar(const char *attstring, int *calendar)
+{
+  if ( memcmp(attstring, "standard", 8)  == 0 ||
+       memcmp(attstring, "gregorian", 9) == 0 )
+    *calendar = CALENDAR_STANDARD;
+  else if ( memcmp(attstring, "none", 4) == 0 )
+    *calendar = CALENDAR_NONE;
+  else if ( memcmp(attstring, "proleptic", 9) == 0 )
+    *calendar = CALENDAR_PROLEPTIC;
+  else if ( memcmp(attstring, "360", 3) == 0 )
+    *calendar = CALENDAR_360DAYS;
+  else if ( memcmp(attstring, "365", 3) == 0 ||
+            memcmp(attstring, "noleap", 6)  == 0 )
+    *calendar = CALENDAR_365DAYS;
+  else if ( memcmp(attstring, "366", 3)  == 0 ||
+            memcmp(attstring, "all_leap", 8) == 0 )
+    *calendar = CALENDAR_366DAYS;
+  else
+    Warning("calendar >%s< unsupported!", attstring);
+}
diff --git a/src/cdf_util.h b/src/cdf_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab9473c374177de53084bb39eba335dc49fffc6e
--- /dev/null
+++ b/src/cdf_util.h
@@ -0,0 +1,29 @@
+#ifndef  CDF_UTIL_H_
+#define  CDF_UTIL_H_
+
+#include <stdbool.h>
+
+void str_tolower(char *str);
+
+int get_timeunit(size_t len, const char *ptu);
+
+bool is_time_units(const char *timeunits);
+bool is_timeaxis_units(const char *timeunits);
+
+bool is_height_units(const char *units);
+bool is_pressure_units(const char *units);
+bool is_DBL_axis(/*const char *units,*/ const char *longname);
+bool is_depth_axis(const char *stdname, const char *longname);
+bool is_height_axis(const char *stdname, const char *longname);
+
+bool is_lon_axis(const char *units, const char *stdname);
+bool is_lat_axis(const char *units, const char *stdname);
+
+bool is_x_axis(const char *units, const char *stdname);
+bool is_y_axis(const char *units, const char *stdname);
+
+void set_gridtype(const char *attstring, int *gridtype);
+void set_zaxistype(const char *attstring, int *zaxistype);
+void set_calendar(const char *attstring, int *calendar);
+
+#endif
diff --git a/src/cdf_write.c b/src/cdf_write.c
index 942f0c7e4cbf10e9d7ef83e7558d98494cda803a..32ce625fb68a646e50bcc15fe970441da50401a5 100644
--- a/src/cdf_write.c
+++ b/src/cdf_write.c
@@ -32,7 +32,6 @@ void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
       Error("nc_def_var_deflate failed, status = %d", retval);
     }
 #else
-  
   static int lwarn = TRUE;
   if ( lwarn )
     {
@@ -164,8 +163,8 @@ void *resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
   return *buf;
 }
 
-static
-void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
+
+void cdfDefineAttributes(int cdiID, int varID, int fileID, int ncvarID)
 {
   int atttype, attlen;
   size_t len;
@@ -174,11 +173,11 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
   size_t attBufSize = 0;
 
   int natts;
-  vlistInqNatts(vlistID, varID, &natts);
+  cdiInqNatts(cdiID, varID, &natts);
 
-  for ( int iatt = 0; iatt < natts; iatt++ )
+  for ( int iatt = 0; iatt < natts; ++iatt )
     {
-      vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
+      cdiInqAtt(cdiID, varID, iatt, attname, &atttype, &attlen);
 
       if ( attlen == 0 ) continue;
 
@@ -186,23 +185,33 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
         {
           size_t attSize = (size_t)attlen*sizeof(char);
           char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
-          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
+          cdiInqAttTxt(cdiID, varID, attname, attlen, atttxt);
           len = (size_t)attlen;
           cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
         }
-      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
+      else if ( atttype == DATATYPE_INT8  || atttype == DATATYPE_UINT8  ||
+                atttype == DATATYPE_INT16 || atttype == DATATYPE_UINT16 ||
+                atttype == DATATYPE_INT32 || atttype == DATATYPE_UINT32 )
         {
           size_t attSize = (size_t)attlen*sizeof(int);
           int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
-          vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
+          cdiInqAttInt(cdiID, varID, attname, attlen, &attint[0]);
           len = (size_t)attlen;
-          cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
+          nc_type xtype = (atttype == DATATYPE_INT8)  ? NC_BYTE :
+                          (atttype == DATATYPE_INT16) ? NC_SHORT :
+#if  defined  (HAVE_NETCDF4)
+                          (atttype == DATATYPE_UINT8)  ? NC_UBYTE :
+                          (atttype == DATATYPE_UINT16) ? NC_USHORT :
+                          (atttype == DATATYPE_UINT32) ? NC_UINT :
+#endif
+                          NC_INT;
+          cdf_put_att_int(fileID, ncvarID, attname, xtype, len, attint);
         }
       else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
         {
           size_t attSize = (size_t)attlen * sizeof(double);
           double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
-          vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
+          cdiInqAttFlt(cdiID, varID, attname, attlen, attflt);
           len = (size_t)attlen;
           if ( atttype == DATATYPE_FLT32 )
             {
@@ -214,7 +223,7 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
             cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
         }
     }
-  
+
   Free(attBuf);
 }
 
@@ -230,7 +239,7 @@ void cdfDefGlobalAtts(stream_t *streamptr)
   cdfDefInstitut(streamptr);
 
   int natts;
-  vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
+  cdiInqNatts(vlistID, CDI_GLOBAL, &natts);
 
   if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID);
 
@@ -272,6 +281,41 @@ void cdfDefLocalAtts(stream_t *streamptr)
   if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
 }
 
+static
+void cdf_get_gmapvarname(int gridID, char *gmapvarname)
+{
+  int pgridID = gridID;
+  char mapping[CDI_MAX_NAME]; mapping[0] = 0;
+  cdiGridInqKeyStr(pgridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+
+  if ( !mapping[0] )
+    {
+      int projID = gridInqProj(gridID);
+      if ( projID != CDI_UNDEFID )
+        {
+          pgridID = projID;
+          cdiGridInqKeyStr(pgridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+        }
+    }
+
+  if ( mapping[0] )
+    cdiGridInqKeyStr(pgridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, gmapvarname);
+}
+
+static
+int nc_grid_index(stream_t *streamptr, int gridID)
+{
+  int index = 0;
+  int vlistID = streamptr->vlistID;
+  int ngrids = vlistNgrids(vlistID);
+  for ( index = 0; index < ngrids; ++index )
+    if ( streamptr->ncgrid[index].gridID == gridID ) break;
+
+  assert(index < ngrids);
+
+  return index;
+}
+
 static
 int cdfDefVar(stream_t *streamptr, int varID)
 {
@@ -314,19 +358,19 @@ int cdfDefVar(stream_t *streamptr, int varID)
   int gridsize  = gridInqSize(gridID);
   if ( gridsize > 1 ) lchunk = TRUE;
   int gridtype  = gridInqType(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
+  int gridindex = nc_grid_index(streamptr, gridID);
   if ( gridtype != GRID_TRAJECTORY )
     {
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      xid = streamptr->ncgrid[gridindex].xdimID;
+      yid = streamptr->ncgrid[gridindex].ydimID;
       if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize);
       if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize);
     }
 
   int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
   int zid = streamptr->zaxisID[zaxisindex];
-  int zaxis_is_scalar = FALSE;
-  if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID);
+  bool zaxis_is_scalar = false;
+  if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID) > 0;
 
   if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
 
@@ -367,7 +411,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
         }
       else if ( dimorder[id] == 2 && yid != UNDEFID )
         {
-          if ( chunktype == CHUNK_LINES )
+          if ( chunktype == CDI_CHUNK_LINES )
             chunks[ndims] = 1;
           else
             chunks[ndims] = ysize;
@@ -473,7 +517,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 #if  defined  (HAVE_NETCDF4)
   if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
     {
-      if ( chunktype == CHUNK_AUTO )
+      if ( chunktype == CDI_CHUNK_AUTO )
         retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
       else
         retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
@@ -482,7 +526,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
     }
 #endif
 
-  if ( streamptr->comptype == COMPRESS_ZIP )
+  if ( streamptr->comptype == CDI_COMPRESS_ZIP )
     {
       if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
         {
@@ -503,7 +547,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
         }
     }
 
-  if ( streamptr->comptype == COMPRESS_SZIP )
+  if ( streamptr->comptype == CDI_COMPRESS_SZIP )
     {
       if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
         {
@@ -557,8 +601,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
         cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum);
     }
 
-  char coordinates[CDI_MAX_NAME];
-  coordinates[0] = 0;
+  char coordinates[CDI_MAX_NAME]; coordinates[0] = 0;
 
   if ( zaxis_is_scalar )
     {
@@ -571,42 +614,32 @@ int cdfDefVar(stream_t *streamptr, int varID)
         }
     }
 
-  if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT  && gridtype != GRID_CURVILINEAR )
+  if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT &&
+       gridtype != GRID_PROJECTION && gridtype != GRID_CURVILINEAR )
     {
       size_t len = strlen(gridNamePtr(gridtype));
       if ( len > 0 )
         cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
     }
 
-  if ( gridIsRotated(gridID) )
-    {
-      char mapping[] = "rotated_pole";
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
-    }
+  char gmapvarname[CDI_MAX_NAME]; gmapvarname[0] = 0;
 
-  if ( gridtype == GRID_SINUSOIDAL )
-    {
-      char mapping[] = "sinusoidal";
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
-    }
-  else if ( gridtype == GRID_LAEA )
-    {
-      char mapping[] = "laea";
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
-    }
-  else if ( gridtype == GRID_LCC2 )
-    {
-      char mapping[] = "Lambert_Conformal";
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
-    }
-  else if ( gridtype == GRID_TRAJECTORY )
+  if      ( gridtype == GRID_SINUSOIDAL ) strcpy(gmapvarname, "Sinusoidal");
+  else if ( gridtype == GRID_LAEA )       strcpy(gmapvarname, "Lambert_AEA");
+  else if ( gridtype == GRID_LCC2 )       strcpy(gmapvarname, "Lambert_CC");
+  else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) ) strcpy(gmapvarname, "rotated_pole");
+  else  cdf_get_gmapvarname(gridID, gmapvarname);
+
+  if ( gmapvarname[0] ) cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(gmapvarname), gmapvarname);
+
+  if ( gridtype == GRID_TRAJECTORY )
     {
       cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" );
     }
   else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 )
     {
-      int ncxvarID = streamptr->ncxvarID[gridindex];
-      int ncyvarID = streamptr->ncyvarID[gridindex];
+      int ncxvarID = streamptr->ncgrid[gridindex].xvarID;
+      int ncyvarID = streamptr->ncgrid[gridindex].yvarID;
       if ( ncyvarID != CDI_UNDEFID )
         {
           size_t len = strlen(coordinates);
@@ -623,9 +656,9 @@ int cdfDefVar(stream_t *streamptr, int varID)
   else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
     {
       char cellarea[CDI_MAX_NAME] = "area: ";
-      int ncxvarID = streamptr->ncxvarID[gridindex];
-      int ncyvarID = streamptr->ncyvarID[gridindex];
-      int ncavarID = streamptr->ncavarID[gridindex];
+      int ncxvarID = streamptr->ncgrid[gridindex].xvarID;
+      int ncyvarID = streamptr->ncgrid[gridindex].yvarID;
+      int ncavarID = streamptr->ncgrid[gridindex].avarID;
       if ( ncyvarID != CDI_UNDEFID )
         {
           size_t len = strlen(coordinates);
@@ -731,14 +764,6 @@ int cdfDefVar(stream_t *streamptr, int varID)
 	cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID);
 	cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount);
 	cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type);
-
-#ifdef DBG
-	if( DBG )
-	  {
-	    fprintf( stderr, "cdfDefVar :\n EnsID  %d\n Enscount %d\n Forecast init type %d\n",  ensID,
-		     ensCount,  forecast_type );
-	  }
-#endif
     }
 
   /* Attributes */
@@ -779,18 +804,16 @@ void cdfEndDef(stream_t *streamptr)
 static
 void cdfWriteGridTraj(stream_t *streamptr, int gridID)
 {
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  int lonID = streamptr->xdimID[gridindex];
-  int latID = streamptr->ydimID[gridindex];
+  int gridindex = nc_grid_index(streamptr, gridID);
+  int lonID = streamptr->ncgrid[gridindex].xdimID;
+  int latID = streamptr->ncgrid[gridindex].ydimID;
 
   double xlon = gridInqXval(gridID, 0);
   double xlat = gridInqYval(gridID, 0);
   int tsID = streamptr->curTsID;
   size_t index = (size_t)tsID;
 
+  int fileID = streamptr->fileID;
   cdf_put_var1_double(fileID, lonID, &index, &xlon);
   cdf_put_var1_double(fileID, latID, &index, &xlat);
 }
@@ -941,7 +964,7 @@ void cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dty
         }
     }
 
-  if ( swapxy ) // implemented only for cdf_write_var_slice() 
+  if ( swapxy ) // implemented only for cdf_write_var_slice()
     {
       size_t gridsize = xsize*ysize;
       if ( memtype == MEMTYPE_FLOAT )
@@ -1009,9 +1032,9 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
     }
   else
     {
-      int gridindex = vlistGridIndex(vlistID, gridID);
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      int gridindex = nc_grid_index(streamptr, gridID);
+      xid = streamptr->ncgrid[gridindex].xdimID;
+      yid = streamptr->ncgrid[gridindex].ydimID;
     }
 
   int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
@@ -1107,9 +1130,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
     }
   else
     {
-      int gridindex = vlistGridIndex(vlistID, gridID);
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      int gridindex = nc_grid_index(streamptr, gridID);
+      xid = streamptr->ncgrid[gridindex].xdimID;
+      yid = streamptr->ncgrid[gridindex].ydimID;
     }
 
   int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
@@ -1205,9 +1228,9 @@ void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp
     }
   else
     {
-      int gridindex = vlistGridIndex(vlistID, gridID);
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      int gridindex = nc_grid_index(streamptr, gridID);
+      xid = streamptr->ncgrid[gridindex].xdimID;
+      yid = streamptr->ncgrid[gridindex].ydimID;
     }
 
   int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
@@ -1270,3 +1293,13 @@ void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nm
 }
 
 #endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/cdi.h b/src/cdi.h
index 69b253d8ad0ae5879c89d32aeeb7885644cc7aea..8496fe9e007365962a3e15ef4324a82f3a73ea3a 100644
--- a/src/cdi.h
+++ b/src/cdi.h
@@ -57,12 +57,12 @@ extern "C" {
 
 /* Compress types */
 
-#define  COMPRESS_NONE            0
-#define  COMPRESS_SZIP            1
-#define  COMPRESS_GZIP            2
-#define  COMPRESS_BZIP2           3
-#define  COMPRESS_ZIP             4
-#define  COMPRESS_JPEG            5
+#define  CDI_COMPRESS_NONE          0
+#define  CDI_COMPRESS_SZIP          1
+#define  CDI_COMPRESS_GZIP          2
+#define  CDI_COMPRESS_BZIP2         3
+#define  CDI_COMPRESS_ZIP           4
+#define  CDI_COMPRESS_JPEG          5
 
 /* external data types */
 
@@ -120,9 +120,9 @@ extern "C" {
 
 /* Chunks */
 
-#define  CHUNK_AUTO                 1  /* use default chunk size                                */
-#define  CHUNK_GRID                 2
-#define  CHUNK_LINES                3
+#define  CDI_CHUNK_AUTO             1  /* use default chunk size                                */
+#define  CDI_CHUNK_GRID             2
+#define  CDI_CHUNK_LINES            3
 
 /* GRID types */
 
@@ -140,7 +140,12 @@ extern "C" {
 #define  GRID_LCC2                 12  /* Lambert Conformal Conic (PROJ)                        */
 #define  GRID_LAEA                 13  /* Lambert Azimuthal Equal Area                          */
 #define  GRID_SINUSOIDAL           14  /* Sinusoidal                                            */
-#define  GRID_PROJECTION           15  /* Projected coordiantes                                 */
+#define  GRID_PROJECTION           15  /* Projected coordinates                                 */
+
+#define  CDI_PROJ_RLL              21  /* Rotated Latitude Longitude                            */
+#define  CDI_PROJ_LCC              22  /* Lambert Conformal Conic                               */
+#define  CDI_PROJ_LAEA             23  /* Lambert Azimuthal Equal Area                          */
+#define  CDI_PROJ_SINU             24  /* Sinusoidal                                            */
 
 /* ZAXIS types */
 
@@ -673,27 +678,27 @@ const char *vlistInqVarNamePtr(int vlistID, int varID);
 const char *vlistInqVarLongnamePtr(int vlistID, int varID);
 const char *vlistInqVarUnitsPtr(int vlistID, int varID);
 
-/* VLIST attributes */
+/* CDI attributes */
 
-/*      vlistInqNatts: Get number of variable attributes assigned to this variable */
-int     vlistInqNatts(int vlistID, int varID, int *nattsp);
-/*      vlistInqAtt: Get information about an attribute */
-int     vlistInqAtt(int vlistID, int varID, int attrnum, char *name, int *typep, int *lenp);
-int     vlistDelAtt(int vlistID, int varID, const char *name);
+/*      cdiInqNatts: Get number of attributes assigned to this variable */
+int     cdiInqNatts(int cdiID, int varID, int *nattsp);
+/*      cdiInqAtt: Get information about an attribute */
+int     cdiInqAtt(int cdiID, int varID, int attrnum, char *name, int *typep, int *lenp);
+int     cdiDelAtt(int cdiID, int varID, const char *name);
 
-/*      vlistDefAttInt: Define an integer attribute */
-int     vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int ip[]);
-/*      vlistDefAttFlt: Define a floating point attribute */
-int     vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double dp[]);
-/*      vlistDefAttTxt: Define a text attribute */
-int     vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp_cbuf);
+/*      cdiDefAttInt: Define an integer attribute */
+int     cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int ip[]);
+/*      cdiDefAttFlt: Define a floating point attribute */
+int     cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double dp[]);
+/*      cdiDefAttTxt: Define a text attribute */
+int     cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp_cbuf);
 
-/*      vlistInqAttInt: Get the value(s) of an integer attribute */
-int     vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int ip[]);
-/*      vlistInqAttFlt: Get the value(s) of a floating point attribute */
-int     vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double dp[]);
-/*      vlistInqAttTxt: Get the value(s) of a text attribute */
-int     vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp_cbuf);
+/*      cdiInqAttInt: Get the value(s) of an integer attribute */
+int     cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int ip[]);
+/*      cdiInqAttFlt: Get the value(s) of a floating point attribute */
+int     cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double dp[]);
+/*      cdiInqAttTxt: Get the value(s) of a text attribute */
+int     cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp_cbuf);
 
 
 /* GRID routines */
@@ -720,6 +725,18 @@ void    gridDestroy(int gridID);
 /*      gridDuplicate: Duplicate a Grid */
 int     gridDuplicate(int gridID);
 
+/*      gridDefProj: Define the projection ID of a Grid */
+void    gridDefProj(int gridID, int projID);
+
+/*      gridInqProj: Get the projection ID of a Grid */
+int     gridInqProj(int gridID);
+
+/*      gridDefProjType: Define the projection type */
+void    gridDefProjType(int gridID, int projtype);
+
+/*      gridInqProjType: Get the projection type */
+int     gridInqProjType(int gridID);
+
 /*      gridInqType: Get the type of a Grid */
 int     gridInqType(int gridID);
 
@@ -757,21 +774,23 @@ void    gridDefYvals(int gridID, const double yvals[]);
 int     gridInqYvals(int gridID, double yvals[]);
 
 /* CDI grid string key values */
-#define  CDI_GRID_XNAME      901  // X-axis name
-#define  CDI_GRID_YNAME      902  // Y-axis name
-#define  CDI_GRID_XDIMNAME   903  // X-axis dimension name
-#define  CDI_GRID_YDIMNAME   904  // Y-axis dimension name
-#define  CDI_GRID_VDIMNAME   905  // Vertex dimension name
-#define  CDI_GRID_XLONGNAME  906  // X-axis longname
-#define  CDI_GRID_YLONGNAME  907  // Y-axis longname
-#define  CDI_GRID_XUNITS     908  // X-axis units
-#define  CDI_GRID_YUNITS     909  // Y-axis units
-
-//      cdiGridDefString: Define a CDI grid string value from a key
-int     cdiGridDefString(int gridID, int key, int size, const char *mesg);
-
-//      cdiGridInqString: Get a CDI grid string value from a key
-int     cdiGridInqString(int gridID, int key, int size, char *mesg);
+#define  CDI_KEY_XNAME      901  // X-axis name
+#define  CDI_KEY_YNAME      902  // Y-axis name
+#define  CDI_KEY_XDIMNAME   903  // X-axis dimension name
+#define  CDI_KEY_YDIMNAME   904  // Y-axis dimension name
+#define  CDI_KEY_VDIMNAME   905  // Vertex dimension name
+#define  CDI_KEY_XLONGNAME  906  // X-axis longname
+#define  CDI_KEY_YLONGNAME  907  // Y-axis longname
+#define  CDI_KEY_XUNITS     908  // X-axis units
+#define  CDI_KEY_YUNITS     909  // Y-axis units
+#define  CDI_KEY_MAPNAME    920  // Grid mapping var name
+#define  CDI_KEY_MAPPING    921  // Grid mapping name
+
+//      cdiGridDefKeyStr: Define a CDI grid string value from a key
+int     cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg);
+
+//      cdiGridInqKeyStr: Get a CDI grid string value from a key
+int     cdiGridInqKeyStr(int gridID, int key, int size, char *mesg);
 
 /*      gridDefXname: Define the name of a X-axis */
 void    gridDefXname(int gridID, const char *xname);
@@ -832,6 +851,10 @@ double  gridInqYinc(int gridID);
 
 int     gridIsCircular(int gridID);
 int     gridIsRotated(int gridID);
+
+void    gridInqProjParamRLL(int gridID, double *xpole, double *ypole, double *angle);
+void    gridDefProjParamRLL(int gridID, double xpole, double ypole, double angle);
+
 void    gridDefXpole(int gridID, double xpole);
 double  gridInqXpole(int gridID);
 void    gridDefYpole(int gridID, double ypole);
diff --git a/src/cdi.inc b/src/cdi.inc
index 333e1e2b7462425d6039b4d0da41e13e6963fff4..5dcb37032584fcdcd6b116fe2b0357232a6c11db 100644
--- a/src/cdi.inc
+++ b/src/cdi.inc
@@ -1,10 +1,10 @@
 ! This file was automatically generated, don't edit!
 !
-! Fortran interface for CDI library version 1.7.2
+! Fortran interface for CDI library version 1.8.0
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   April 2016
+! Uwe Schulzweida, MPI-MET, Hamburg,   August 2016
 !
 
       INTEGER    CDI_MAX_NAME          
@@ -75,18 +75,18 @@
 !
 !  Compress types
 !
-      INTEGER    COMPRESS_NONE         
-      PARAMETER (COMPRESS_NONE          =  0)
-      INTEGER    COMPRESS_SZIP         
-      PARAMETER (COMPRESS_SZIP          =  1)
-      INTEGER    COMPRESS_GZIP         
-      PARAMETER (COMPRESS_GZIP          =  2)
-      INTEGER    COMPRESS_BZIP2        
-      PARAMETER (COMPRESS_BZIP2         =  3)
-      INTEGER    COMPRESS_ZIP          
-      PARAMETER (COMPRESS_ZIP           =  4)
-      INTEGER    COMPRESS_JPEG         
-      PARAMETER (COMPRESS_JPEG          =  5)
+      INTEGER    CDI_COMPRESS_NONE     
+      PARAMETER (CDI_COMPRESS_NONE      =  0)
+      INTEGER    CDI_COMPRESS_SZIP     
+      PARAMETER (CDI_COMPRESS_SZIP      =  1)
+      INTEGER    CDI_COMPRESS_GZIP     
+      PARAMETER (CDI_COMPRESS_GZIP      =  2)
+      INTEGER    CDI_COMPRESS_BZIP2    
+      PARAMETER (CDI_COMPRESS_BZIP2     =  3)
+      INTEGER    CDI_COMPRESS_ZIP      
+      PARAMETER (CDI_COMPRESS_ZIP       =  4)
+      INTEGER    CDI_COMPRESS_JPEG     
+      PARAMETER (CDI_COMPRESS_JPEG      =  5)
 !
 !  external data types
 !
@@ -194,12 +194,12 @@
 !
 !  Chunks
 !
-      INTEGER    CHUNK_AUTO            
-      PARAMETER (CHUNK_AUTO             =  1)
-      INTEGER    CHUNK_GRID            
-      PARAMETER (CHUNK_GRID             =  2)
-      INTEGER    CHUNK_LINES           
-      PARAMETER (CHUNK_LINES            =  3)
+      INTEGER    CDI_CHUNK_AUTO        
+      PARAMETER (CDI_CHUNK_AUTO         =  1)
+      INTEGER    CDI_CHUNK_GRID        
+      PARAMETER (CDI_CHUNK_GRID         =  2)
+      INTEGER    CDI_CHUNK_LINES       
+      PARAMETER (CDI_CHUNK_LINES        =  3)
 !
 !  GRID types
 !
@@ -233,6 +233,14 @@
       PARAMETER (GRID_SINUSOIDAL        = 14)
       INTEGER    GRID_PROJECTION       
       PARAMETER (GRID_PROJECTION        = 15)
+      INTEGER    CDI_PROJ_RLL          
+      PARAMETER (CDI_PROJ_RLL           = 21)
+      INTEGER    CDI_PROJ_LCC          
+      PARAMETER (CDI_PROJ_LCC           = 22)
+      INTEGER    CDI_PROJ_LAEA         
+      PARAMETER (CDI_PROJ_LAEA          = 23)
+      INTEGER    CDI_PROJ_SINU         
+      PARAMETER (CDI_PROJ_SINU          = 24)
 !
 !  ZAXIS types
 !
@@ -1340,78 +1348,78 @@
       EXTERNAL        vlistInqVarUnitsPtr
 
 !
-!  VLIST attributes
+!  CDI attributes
 !
-      INTEGER         vlistInqNatts
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiInqNatts
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     INTEGER         nattsp)
-      EXTERNAL        vlistInqNatts
+      EXTERNAL        cdiInqNatts
 
-      INTEGER         vlistInqAtt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiInqAtt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     INTEGER         attrnum,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         typep,
 !                                     INTEGER         lenp)
-      EXTERNAL        vlistInqAtt
+      EXTERNAL        cdiInqAtt
 
-      INTEGER         vlistDelAtt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiDelAtt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name)
-      EXTERNAL        vlistDelAtt
+      EXTERNAL        cdiDelAtt
 
-      INTEGER         vlistDefAttInt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiDefAttInt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         type,
 !                                     INTEGER         len,
 !                                     INTEGER         ip(*))
-      EXTERNAL        vlistDefAttInt
+      EXTERNAL        cdiDefAttInt
 
-      INTEGER         vlistDefAttFlt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiDefAttFlt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         type,
 !                                     INTEGER         len,
 !                                     DOUBLEPRECISION dp(*))
-      EXTERNAL        vlistDefAttFlt
+      EXTERNAL        cdiDefAttFlt
 
-      INTEGER         vlistDefAttTxt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiDefAttTxt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         len,
 !                                     CHARACTER*(*)   tp_cbuf)
-      EXTERNAL        vlistDefAttTxt
+      EXTERNAL        cdiDefAttTxt
 
-      INTEGER         vlistInqAttInt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiInqAttInt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         mlen,
 !                                     INTEGER         ip(*))
-      EXTERNAL        vlistInqAttInt
+      EXTERNAL        cdiInqAttInt
 
-      INTEGER         vlistInqAttFlt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiInqAttFlt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         mlen,
 !                                     DOUBLEPRECISION dp(*))
-      EXTERNAL        vlistInqAttFlt
+      EXTERNAL        cdiInqAttFlt
 
-      INTEGER         vlistInqAttTxt
-!                                    (INTEGER         vlistID,
+      INTEGER         cdiInqAttTxt
+!                                    (INTEGER         cdiID,
 !                                     INTEGER         varID,
 !                                     CHARACTER*(*)   name,
 !                                     INTEGER         mlen,
 !                                     CHARACTER*(*)   tp_cbuf)
-      EXTERNAL        vlistInqAttTxt
+      EXTERNAL        cdiInqAttTxt
 
 !
 !  GRID routines
@@ -1468,6 +1476,24 @@
 !                                    (INTEGER         gridID)
       EXTERNAL        gridDuplicate
 
+!                     gridDefProj
+!                                    (INTEGER         gridID,
+!                                     INTEGER         projID)
+      EXTERNAL        gridDefProj
+
+      INTEGER         gridInqProj
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqProj
+
+!                     gridDefProjType
+!                                    (INTEGER         gridID,
+!                                     INTEGER         projtype)
+      EXTERNAL        gridDefProjType
+
+      INTEGER         gridInqProjType
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqProjType
+
       INTEGER         gridInqType
 !                                    (INTEGER         gridID)
       EXTERNAL        gridInqType
@@ -1526,37 +1552,41 @@
 !
 !  CDI grid string key values
 !
-      INTEGER    CDI_GRID_XNAME        
-      PARAMETER (CDI_GRID_XNAME         = 901)
-      INTEGER    CDI_GRID_YNAME        
-      PARAMETER (CDI_GRID_YNAME         = 902)
-      INTEGER    CDI_GRID_XDIMNAME     
-      PARAMETER (CDI_GRID_XDIMNAME      = 903)
-      INTEGER    CDI_GRID_YDIMNAME     
-      PARAMETER (CDI_GRID_YDIMNAME      = 904)
-      INTEGER    CDI_GRID_VDIMNAME     
-      PARAMETER (CDI_GRID_VDIMNAME      = 905)
-      INTEGER    CDI_GRID_XLONGNAME    
-      PARAMETER (CDI_GRID_XLONGNAME     = 906)
-      INTEGER    CDI_GRID_YLONGNAME    
-      PARAMETER (CDI_GRID_YLONGNAME     = 907)
-      INTEGER    CDI_GRID_XUNITS       
-      PARAMETER (CDI_GRID_XUNITS        = 908)
-      INTEGER    CDI_GRID_YUNITS       
-      PARAMETER (CDI_GRID_YUNITS        = 909)
-      INTEGER         cdiGridDefString
+      INTEGER    CDI_KEY_XNAME         
+      PARAMETER (CDI_KEY_XNAME          = 901)
+      INTEGER    CDI_KEY_YNAME         
+      PARAMETER (CDI_KEY_YNAME          = 902)
+      INTEGER    CDI_KEY_XDIMNAME      
+      PARAMETER (CDI_KEY_XDIMNAME       = 903)
+      INTEGER    CDI_KEY_YDIMNAME      
+      PARAMETER (CDI_KEY_YDIMNAME       = 904)
+      INTEGER    CDI_KEY_VDIMNAME      
+      PARAMETER (CDI_KEY_VDIMNAME       = 905)
+      INTEGER    CDI_KEY_XLONGNAME     
+      PARAMETER (CDI_KEY_XLONGNAME      = 906)
+      INTEGER    CDI_KEY_YLONGNAME     
+      PARAMETER (CDI_KEY_YLONGNAME      = 907)
+      INTEGER    CDI_KEY_XUNITS        
+      PARAMETER (CDI_KEY_XUNITS         = 908)
+      INTEGER    CDI_KEY_YUNITS        
+      PARAMETER (CDI_KEY_YUNITS         = 909)
+      INTEGER    CDI_KEY_MAPNAME       
+      PARAMETER (CDI_KEY_MAPNAME        = 920)
+      INTEGER    CDI_KEY_MAPPING       
+      PARAMETER (CDI_KEY_MAPPING        = 921)
+      INTEGER         cdiGridDefKeyStr
 !                                    (INTEGER         gridID,
 !                                     INTEGER         key,
 !                                     INTEGER         size,
 !                                     CHARACTER*(*)   mesg)
-      EXTERNAL        cdiGridDefString
+      EXTERNAL        cdiGridDefKeyStr
 
-      INTEGER         cdiGridInqString
+      INTEGER         cdiGridInqKeyStr
 !                                    (INTEGER         gridID,
 !                                     INTEGER         key,
 !                                     INTEGER         size,
 !                                     CHARACTER*(*)   mesg)
-      EXTERNAL        cdiGridInqString
+      EXTERNAL        cdiGridInqKeyStr
 
 !                     gridDefXname
 !                                    (INTEGER         gridID,
@@ -1663,6 +1693,20 @@
 !                                    (INTEGER         gridID)
       EXTERNAL        gridIsRotated
 
+!                     gridInqProjParamRLL
+!                                    (INTEGER         gridID,
+!                                     DOUBLEPRECISION xpole,
+!                                     DOUBLEPRECISION ypole,
+!                                     DOUBLEPRECISION angle)
+      EXTERNAL        gridInqProjParamRLL
+
+!                     gridDefProjParamRLL
+!                                    (INTEGER         gridID,
+!                                     DOUBLEPRECISION xpole,
+!                                     DOUBLEPRECISION ypole,
+!                                     DOUBLEPRECISION angle)
+      EXTERNAL        gridDefProjParamRLL
+
 !                     gridDefXpole
 !                                    (INTEGER         gridID,
 !                                     DOUBLEPRECISION xpole)
diff --git a/src/cdiFortran.c b/src/cdiFortran.c
index 2b83d7036fd11dc1013dbfbe652b3849bb669e06..527c0bd0befc79a5349d4307bf5e9e3731d630b2 100644
--- a/src/cdiFortran.c
+++ b/src/cdiFortran.c
@@ -287,17 +287,17 @@ FCALLSCFUN2 (STRING, vlistInqVarNamePtr, VLISTINQVARNAMEPTR, vlistinqvarnameptr,
 FCALLSCFUN2 (STRING, vlistInqVarLongnamePtr, VLISTINQVARLONGNAMEPTR, vlistinqvarlongnameptr, INT, INT)
 FCALLSCFUN2 (STRING, vlistInqVarUnitsPtr, VLISTINQVARUNITSPTR, vlistinqvarunitsptr, INT, INT)
 
-/*  VLIST attributes  */
-
-FCALLSCFUN3 (INT, vlistInqNatts, VLISTINQNATTS, vlistinqnatts, INT, INT, PINT)
-FCALLSCFUN6 (INT, vlistInqAtt, VLISTINQATT, vlistinqatt, INT, INT, INT, PSTRING, PINT, PINT)
-FCALLSCFUN3 (INT, vlistDelAtt, VLISTDELATT, vlistdelatt, INT, INT, STRING)
-FCALLSCFUN6 (INT, vlistDefAttInt, VLISTDEFATTINT, vlistdefattint, INT, INT, STRING, INT, INT, INTV)
-FCALLSCFUN6 (INT, vlistDefAttFlt, VLISTDEFATTFLT, vlistdefattflt, INT, INT, STRING, INT, INT, DOUBLEV)
-FCALLSCFUN5 (INT, vlistDefAttTxt, VLISTDEFATTTXT, vlistdefatttxt, INT, INT, STRING, INT, PPSTRING)
-FCALLSCFUN5 (INT, vlistInqAttInt, VLISTINQATTINT, vlistinqattint, INT, INT, STRING, INT, INTV)
-FCALLSCFUN5 (INT, vlistInqAttFlt, VLISTINQATTFLT, vlistinqattflt, INT, INT, STRING, INT, DOUBLEV)
-FCALLSCFUN5 (INT, vlistInqAttTxt, VLISTINQATTTXT, vlistinqatttxt, INT, INT, STRING, INT, PPSTRING)
+/*  CDI attributes  */
+
+FCALLSCFUN3 (INT, cdiInqNatts, CDIINQNATTS, cdiinqnatts, INT, INT, PINT)
+FCALLSCFUN6 (INT, cdiInqAtt, CDIINQATT, cdiinqatt, INT, INT, INT, PSTRING, PINT, PINT)
+FCALLSCFUN3 (INT, cdiDelAtt, CDIDELATT, cdidelatt, INT, INT, STRING)
+FCALLSCFUN6 (INT, cdiDefAttInt, CDIDEFATTINT, cdidefattint, INT, INT, STRING, INT, INT, INTV)
+FCALLSCFUN6 (INT, cdiDefAttFlt, CDIDEFATTFLT, cdidefattflt, INT, INT, STRING, INT, INT, DOUBLEV)
+FCALLSCFUN5 (INT, cdiDefAttTxt, CDIDEFATTTXT, cdidefatttxt, INT, INT, STRING, INT, PPSTRING)
+FCALLSCFUN5 (INT, cdiInqAttInt, CDIINQATTINT, cdiinqattint, INT, INT, STRING, INT, INTV)
+FCALLSCFUN5 (INT, cdiInqAttFlt, CDIINQATTFLT, cdiinqattflt, INT, INT, STRING, INT, DOUBLEV)
+FCALLSCFUN5 (INT, cdiInqAttTxt, CDIINQATTTXT, cdiinqatttxt, INT, INT, STRING, INT, PPSTRING)
 
 /*  GRID routines  */
 
@@ -312,6 +312,10 @@ FCALLSCSUB3 (gridPrint, GRIDPRINT, gridprint, INT, INT, INT)
 FCALLSCFUN2 (INT, gridCreate, GRIDCREATE, gridcreate, INT, INT)
 FCALLSCSUB1 (gridDestroy, GRIDDESTROY, griddestroy, INT)
 FCALLSCFUN1 (INT, gridDuplicate, GRIDDUPLICATE, gridduplicate, INT)
+FCALLSCSUB2 (gridDefProj, GRIDDEFPROJ, griddefproj, INT, INT)
+FCALLSCFUN1 (INT, gridInqProj, GRIDINQPROJ, gridinqproj, INT)
+FCALLSCSUB2 (gridDefProjType, GRIDDEFPROJTYPE, griddefprojtype, INT, INT)
+FCALLSCFUN1 (INT, gridInqProjType, GRIDINQPROJTYPE, gridinqprojtype, INT)
 FCALLSCFUN1 (INT, gridInqType, GRIDINQTYPE, gridinqtype, INT)
 FCALLSCFUN1 (INT, gridInqSize, GRIDINQSIZE, gridinqsize, INT)
 FCALLSCSUB2 (gridDefXsize, GRIDDEFXSIZE, griddefxsize, INT, INT)
@@ -327,8 +331,8 @@ FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, DOUBLEV)
 
 /*  CDI grid string key values  */
 
-FCALLSCFUN4 (INT, cdiGridDefString, CDIGRIDDEFSTRING, cdigriddefstring, INT, INT, INT, STRING)
-FCALLSCFUN4 (INT, cdiGridInqString, CDIGRIDINQSTRING, cdigridinqstring, INT, INT, INT, PSTRING)
+FCALLSCFUN4 (INT, cdiGridDefKeyStr, CDIGRIDDEFKEYSTR, cdigriddefkeystr, INT, INT, INT, STRING)
+FCALLSCFUN4 (INT, cdiGridInqKeyStr, CDIGRIDINQKEYSTR, cdigridinqkeystr, INT, INT, INT, PSTRING)
 FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING)
 FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING)
@@ -351,6 +355,8 @@ FCALLSCFUN1 (DOUBLE, gridInqXinc, GRIDINQXINC, gridinqxinc, INT)
 FCALLSCFUN1 (DOUBLE, gridInqYinc, GRIDINQYINC, gridinqyinc, INT)
 FCALLSCFUN1 (INT, gridIsCircular, GRIDISCIRCULAR, gridiscircular, INT)
 FCALLSCFUN1 (INT, gridIsRotated, GRIDISROTATED, gridisrotated, INT)
+FCALLSCSUB4 (gridInqProjParamRLL, GRIDINQPROJPARAMRLL, gridinqprojparamrll, INT, PDOUBLE, PDOUBLE, PDOUBLE)
+FCALLSCSUB4 (gridDefProjParamRLL, GRIDDEFPROJPARAMRLL, griddefprojparamrll, INT, DOUBLE, DOUBLE, DOUBLE)
 FCALLSCSUB2 (gridDefXpole, GRIDDEFXPOLE, griddefxpole, INT, DOUBLE)
 FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT)
 FCALLSCSUB2 (gridDefYpole, GRIDDEFYPOLE, griddefypole, INT, DOUBLE)
diff --git a/src/vlist_att.c b/src/cdi_att.c
similarity index 55%
rename from src/vlist_att.c
rename to src/cdi_att.c
index aea66506f8a78eec256b85840a111424bf24533a..156d9c1f0226e8233a68525a35032c63f457d831 100644
--- a/src/vlist_att.c
+++ b/src/cdi_att.c
@@ -1,5 +1,5 @@
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
+#include "config.h"
 #endif
 
 #include <assert.h>
@@ -12,9 +12,12 @@
 #include "cdi.h"
 #include "cdi_int.h"
 #include "vlist.h"
-#include "vlist_att.h"
+#include "cdi_att.h"
 #include "error.h"
 #include "serialize.h"
+#include "grid.h"
+#include "resource_unpack.h"
+
 
 static
 cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID)
@@ -31,7 +34,7 @@ cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID)
 	attsp = &(vlistptr->vars[varID].atts);
     }
 
-  return (attsp);
+  return attsp;
 }
 
 static
@@ -49,27 +52,24 @@ cdi_att_t *find_att(cdi_atts_t *attsp, const char *name)
     {
       cdi_att_t *attp = atts + attid;
       if ( attp->namesz == slen && memcmp(attp->name, name, slen) == 0 )
-        return (attp); /* Normal return */
+        return attp; /* Normal return */
     }
 
-  return (NULL);
+  return NULL;
 }
 
 static
 cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
 {
-  cdi_att_t *attp;
-  size_t slen;
-
   xassert(attsp != NULL);
   xassert(name  != NULL);
 
-  if ( attsp->nelems == attsp->nalloc ) return (NULL);
+  if ( attsp->nelems == attsp->nalloc ) return NULL;
 
-  attp = &(attsp->value[attsp->nelems]);
+  cdi_att_t *attp = &(attsp->value[attsp->nelems]);
   attsp->nelems++;
 
-  slen = strlen(name);
+  size_t slen = strlen(name);
   if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
 
   attp->name = (char *) Malloc(slen+1);
@@ -77,7 +77,7 @@ cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
   attp->namesz = slen;
   attp->xvalue = NULL;
 
-  return (attp);
+  return attp;
 }
 
 static
@@ -97,44 +97,59 @@ void fill_att(cdi_att_t *attp, int indtype, int exdtype, size_t nelems, size_t x
     }
 }
 
+static
+cdi_atts_t *cdi_get_attsp(int objID, int varID)
+{
+  cdi_atts_t *attsp = NULL;
+
+  if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == GRID )
+    {
+      grid_t *gridptr = gridID2Ptr(objID);
+      attsp = &gridptr->atts;
+    }
+  else
+    {
+      vlist_t *vlistptr = vlist_to_pointer(objID);
+      attsp = get_attsp(vlistptr, varID);
+    }
+
+  return attsp;
+}
+
 /*
-@Function  vlistInqNatts
-@Title     Get number of variable attributes
+@Function  cdiInqNatts
+@Title     Get number of attributes
 
-@Prototype int vlistInqNatts(int vlistID, int varID, int *nattsp)
+@Prototype int cdiInqNatts(int cdiID, int varID, int *nattsp)
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
-    @Item  nattsp   Pointer to location for returned number of variable attributes.
+    @Item  nattsp   Pointer to location for returned number of attributes.
 
 @Description
-The function @func{vlistInqNatts} gets the number of variable attributes assigned to this variable.
+The function @func{cdiInqNatts} gets the number of attributes assigned to this variable.
 
 @EndFunction
 */
-int vlistInqNatts(int vlistID, int varID, int *nattsp)
+int cdiInqNatts(int cdiID, int varID, int *nattsp)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
-  cdi_atts_t *attsp;
 
-  vlistptr = vlist_to_pointer(vlistID);
-
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
   xassert(attsp != NULL);
 
   *nattsp = (int)attsp->nelems;
 
-  return (status);
+  return status;
 }
 
 /*
-@Function  vlistInqAtt
+@Function  cdiInqAtt
 @Title     Get information about an attribute
 
-@Prototype int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
+@Prototype int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  attnum   Attribute number (from 0 to natts-1).
     @Item  name     Pointer to the location for the returned attribute name. The caller must allocate space for the
@@ -144,22 +159,20 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp)
     @Item  lenp     Pointer to location for returned attribute number.
 
 @Description
-The function @func{vlistInqAtt} gets information about an attribute.
+The function @func{cdiInqAtt} gets information about an attribute.
 
 @EndFunction
 */
-int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
+int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
 {
   int status = CDI_NOERR;
-  cdi_att_t *attp = NULL;
 
   xassert(name != NULL);
 
-  vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
-  cdi_atts_t *attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
   xassert(attsp != NULL);
 
+  cdi_att_t *attp = NULL;
   if ( attnum >= 0 && attnum < (int)attsp->nelems )
     attp = &(attsp->value[attnum]);
 
@@ -177,102 +190,79 @@ int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int
       status  = -1;
     }
 
-  return (status);
+  return status;
 }
 
 
-int vlistDelAtts(int vlistID, int varID)
+int cdiDelAtts(int cdiID, int varID)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
-  cdi_att_t *attp = NULL;
-  cdi_atts_t *attsp;
-  int attid;
-
-  vlistptr = vlist_to_pointer(vlistID);
 
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
   xassert(attsp != NULL);
 
-  for ( attid = 0; attid < (int)attsp->nelems; attid++ )
+  for ( int attid = 0; attid < (int)attsp->nelems; attid++ )
     {
-      attp = &(attsp->value[attid]);
+      cdi_att_t *attp = &(attsp->value[attid]);
       if ( attp->name   ) Free(attp->name);
       if ( attp->xvalue ) Free(attp->xvalue);
     }
 
   attsp->nelems = 0;
 
-  return (status);
+  return status;
 }
 
 
-int vlistDelAtt(int vlistID, int varID, const char *name)
+int cdiDelAtt(int cdiID, int varID, const char *name)
 {
   int status = CDI_NOERR;
 
-  UNUSED(vlistID);
+  UNUSED(cdiID);
   UNUSED(varID);
   UNUSED(name);
 
-  fprintf(stderr, "vlistDelAtt not implemented!\n");
+  fprintf(stderr, "cdiDelAtt not implemented!\n");
 
-  return (status);
+  return status;
 }
 
 static
-int vlist_def_att(int indtype, int exdtype, int vlistID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
+int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
-  cdi_att_t *attp;
-  cdi_atts_t *attsp;
 
   if ( len != 0 && xp == NULL ) /* Null arg */
-    {
-      return (CDI_EINVAL);
-    }
+    return CDI_EINVAL;
 
-  vlistptr = vlist_to_pointer(vlistID);
-
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
   xassert(attsp != NULL);
 
-  attp = find_att(attsp, name);
-  if ( attp == NULL )
-    attp = new_att(attsp, name);
+  cdi_att_t *attp = find_att(attsp, name);
+  if ( attp == NULL ) attp = new_att(attsp, name);
 
-  if ( attp != NULL )
-    fill_att(attp, indtype, exdtype, len, xsz, xp);
+  if ( attp != NULL ) fill_att(attp, indtype, exdtype, len, xsz, xp);
 
-  return (status);
+  return status;
 }
 
 static
-int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t mxsz, void *xp)
+int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
-  cdi_att_t *attp;
-  cdi_atts_t *attsp;
-  size_t xsz;
 
   if ( mxsz != 0 && xp == NULL ) /* Null arg */
-    {
-      return (CDI_EINVAL);
-    }
+    return CDI_EINVAL;
 
-  vlistptr = vlist_to_pointer(vlistID);
-
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
   xassert(attsp != NULL);
 
-  attp = find_att(attsp, name);
+  cdi_att_t *attp = find_att(attsp, name);
   if ( attp != NULL ) /* name in use */
     {
       if ( attp->indtype == indtype )
 	{
-	  xsz = attp->xsz;
+	  size_t xsz = attp->xsz;
 	  if ( mxsz < xsz ) xsz = mxsz;
 	  if ( xsz > 0 )
 	    memcpy(xp, attp->xvalue, xsz);
@@ -289,40 +279,34 @@ int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t
       status = -1;
     }
 
-  return (status);
+  return status;
 }
 
 
-int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2)
+int cdiCopyVarAtts(int cdiID1, int varID_1, int cdiID2, int varID_2)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr1;
-  cdi_att_t *attp = NULL;
-  cdi_atts_t *attsp1;
-  int attid;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
 
-  attsp1 = get_attsp(vlistptr1, varID_1);
+  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID_1);
   xassert(attsp1 != NULL);
 
-  for ( attid = 0; attid < (int)attsp1->nelems; attid++ )
+  for ( int attid = 0; attid < (int)attsp1->nelems; attid++ )
     {
-      attp = &(attsp1->value[attid]);
-      vlist_def_att(attp->indtype, attp->exdtype, vlistID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
+      cdi_att_t *attp = &(attsp1->value[attid]);
+      cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
     }
 
-  return (status);
+  return status;
 }
 
 /*
-@Function  vlistDefAttInt
+@Function  cdiDefAttInt
 @Title     Define an integer attribute
 
-@Prototype int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip)
+@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
 
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  type     External data type (@func{DATATYPE_INT16} or @func{DATATYPE_INT32}).
@@ -330,23 +314,23 @@ int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2)
     @Item  ip       Pointer to one or more integer values.
 
 @Description
-The function @func{vlistDefAttInt} defines an integer attribute.
+The function @func{cdiDefAttInt} defines an integer attribute.
 
 @EndFunction
 */
-int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip)
+int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
 {
-  return vlist_def_att(DATATYPE_INT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (int), ip);
+  return cdi_def_att(DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip);
 }
 
 /*
-@Function  vlistDefAttFlt
+@Function  cdiDefAttFlt
 @Title     Define a floating point attribute
 
-@Prototype int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp)
+@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
 
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  type     External data type (@func{DATATYPE_FLT32} or @func{DATATYPE_FLT64}).
@@ -354,110 +338,110 @@ int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len,
     @Item  dp       Pointer to one or more floating point values.
 
 @Description
-The function @func{vlistDefAttFlt} defines a floating point attribute.
+The function @func{cdiDefAttFlt} defines a floating point attribute.
 
 @EndFunction
 */
-int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp)
+int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
 {
-  return vlist_def_att(DATATYPE_FLT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (double), dp);
+  return cdi_def_att(DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp);
 }
 
 /*
-@Function  vlistDefAttTxt
+@Function  cdiDefAttTxt
 @Title     Define a text attribute
 
-@Prototype int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)
+@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
 
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  len      Number of values provided for the attribute.
     @Item  tp       Pointer to one or more character values.
 
 @Description
-The function @func{vlistDefAttTxt} defines a text attribute.
+The function @func{cdiDefAttTxt} defines a text attribute.
 
 @EndFunction
 */
-int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)
+int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
 {
-  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t)len, (size_t)len, tp);
+  return cdi_def_att(DATATYPE_TXT, DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp);
 }
 
 /*
-@Function  vlistInqAttInt
+@Function  cdiInqAttInt
 @Title     Get the value(s) of an integer attribute
 
-@Prototype int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
+@Prototype int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  mlen     Number of allocated values provided for the attribute.
     @Item  ip       Pointer location for returned integer attribute value(s).
 
 @Description
-The function @func{vlistInqAttInt} gets the values(s) of an integer attribute.
+The function @func{cdiInqAttInt} gets the values(s) of an integer attribute.
 
 @EndFunction
 */
-int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
+int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
 {
-  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, (size_t)mlen * sizeof (int), ip);
+  return cdi_inq_att(DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip);
 }
 
 /*
-@Function  vlistInqAttFlt
+@Function  cdiInqAttFlt
 @Title     Get the value(s) of a floating point attribute
 
-@Prototype int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
+@Prototype int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  mlen     Number of allocated values provided for the attribute.
     @Item  dp       Pointer location for returned floating point attribute value(s).
 
 @Description
-The function @func{vlistInqAttFlt} gets the values(s) of a floating point attribute.
+The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute.
 
 @EndFunction
 */
-int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
+int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
 {
-  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, (size_t)mlen * sizeof (double), dp);
+  return cdi_inq_att(DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp);
 }
 
 /*
-@Function  vlistInqAttTxt
+@Function  cdiInqAttTxt
 @Title     Get the value(s) of a text attribute
 
-@Prototype int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
+@Prototype int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
 @Parameter
-    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
+    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
     @Item  name     Attribute name.
     @Item  mlen     Number of allocated values provided for the attribute.
     @Item  tp       Pointer location for returned text attribute value(s).
 
 @Description
-The function @func{vlistInqAttTxt} gets the values(s) of a text attribute.
+The function @func{cdiInqAttTxt} gets the values(s) of a text attribute.
 
 @EndFunction
 */
-int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
+int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
 {
-  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, (size_t)mlen * sizeof (char), tp);
+  return cdi_inq_att(DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp);
 }
 
 enum {
-  vlist_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
+  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
 };
 
-static inline int
-vlistAttTypeLookup(cdi_att_t *attp)
+static inline
+int cdiAttTypeLookup(cdi_att_t *attp)
 {
   int type;
   switch (attp->indtype)
@@ -477,8 +461,7 @@ vlistAttTypeLookup(cdi_att_t *attp)
 }
 
 
-int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB,
-                      int attnum)
+int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum)
 {
   cdi_atts_t *attspa = get_attsp(a, varIDA),
     *attspb = get_attsp(b, varIDB);
@@ -502,8 +485,8 @@ int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB,
 }
 
 
-static int
-vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
+static
+int cdiAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
 {
   cdi_atts_t *attsp;
   cdi_att_t *attp;
@@ -511,30 +494,31 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
   xassert(attsp = get_attsp(vlistptr, varID));
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
   attp = &(attsp->value[attnum]);
-  int txsize = serializeGetSize(vlist_att_nints, DATATYPE_INT, context)
+  int txsize = serializeGetSize(cdi_att_nints, DATATYPE_INT, context)
     + serializeGetSize((int)attp->namesz, DATATYPE_TXT, context);
-  txsize += serializeGetSize((int)attp->nelems, vlistAttTypeLookup(attp), context);
+  txsize += serializeGetSize((int)attp->nelems, cdiAttTypeLookup(attp), context);
   return txsize;
 }
 
-int
-vlistAttsGetSize(vlist_t *p, int varID, void *context)
+
+int cdiAttsGetSize(void *vp, int varID, void *context)
 {
+  vlist_t *p = (vlist_t*) vp;
   cdi_atts_t *attsp = get_attsp(p, varID);
   int txsize = serializeGetSize(1, DATATYPE_INT, context);
   size_t numAtts = attsp->nelems;
   for (size_t i = 0; i < numAtts; ++i)
-    txsize += vlistAttGetSize(p, varID, (int)i, context);
+    txsize += cdiAttGetSize(p, varID, (int)i, context);
   return txsize;
 }
 
-static void
-vlistAttPack(vlist_t *vlistptr, int varID, int attnum,
-             void * buf, int size, int *position, void *context)
+static
+void cdiAttPack(vlist_t *vlistptr, int varID, int attnum,
+                void *buf, int size, int *position, void *context)
 {
   cdi_atts_t *attsp;
   cdi_att_t *attp;
-  int tempbuf[vlist_att_nints];
+  int tempbuf[cdi_att_nints];
 
   xassert(attsp = get_attsp(vlistptr, varID));
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
@@ -543,33 +527,32 @@ vlistAttPack(vlist_t *vlistptr, int varID, int attnum,
   tempbuf[1] = attp->exdtype;
   tempbuf[2] = attp->indtype;
   tempbuf[3] = (int)attp->nelems;
-  serializePack(tempbuf, vlist_att_nints, DATATYPE_INT, buf, size, position, context);
+  serializePack(tempbuf, cdi_att_nints, DATATYPE_INT, buf, size, position, context);
   serializePack(attp->name, (int)attp->namesz, DATATYPE_TXT, buf, size, position, context);
-  serializePack(attp->xvalue, (int)attp->nelems, vlistAttTypeLookup(attp),
+  serializePack(attp->xvalue, (int)attp->nelems, cdiAttTypeLookup(attp),
                 buf, size, position, context);
 }
 
-void
-vlistAttsPack(vlist_t *p, int varID,
-              void * buf, int size, int *position, void *context)
+
+void cdiAttsPack(void *vp, int varID, void *buf, int size, int *position, void *context)
 {
+  vlist_t *p = (vlist_t*) vp;
   cdi_atts_t *attsp = get_attsp(p, varID);
   size_t numAtts = attsp->nelems;
   int numAttsI = (int)numAtts;
   xassert(numAtts <= INT_MAX);
   serializePack(&numAttsI, 1, DATATYPE_INT, buf, size, position, context);
   for (size_t i = 0; i < numAtts; ++i)
-    vlistAttPack(p, varID, (int)i, buf, size, position, context);
+    cdiAttPack(p, varID, (int)i, buf, size, position, context);
 }
 
-static void
-vlistAttUnpack(int vlistID, int varID,
-               void * buf, int size, int *position, void *context)
+static
+void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
 {
-  int tempbuf[vlist_att_nints];
+  int tempbuf[cdi_att_nints];
 
   serializeUnpack(buf, size, position,
-                  tempbuf, vlist_att_nints, DATATYPE_INT, context);
+                  tempbuf, cdi_att_nints, DATATYPE_INT, context);
   char *attName = (char *) Malloc((size_t)tempbuf[0] + 1);
   serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context);
   attName[tempbuf[0]] = '\0';
@@ -595,22 +578,19 @@ vlistAttUnpack(int vlistID, int varID,
   }
   void *attData = (void *) Malloc(elemSize * (size_t)tempbuf[3]);
   serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
-  vlist_def_att(tempbuf[2], tempbuf[1], vlistID, varID, attName,
-                (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
+  cdi_def_att(tempbuf[2], tempbuf[1], cdiID, varID, attName,
+              (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
   Free(attName);
   Free(attData);
 }
 
-void
-vlistAttsUnpack(int vlistID, int varID,
-                void * buf, int size, int *position, void *context)
+
+void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
 {
-  int numAtts, i;
+  int numAtts;
   serializeUnpack(buf, size, position, &numAtts, 1, DATATYPE_INT, context);
-  for (i = 0; i < numAtts; ++i)
-  {
-    vlistAttUnpack(vlistID, varID, buf, size, position, context);
-  }
+  for ( int i = 0; i < numAtts; ++i )
+    cdiAttUnpack(cdiID, varID, buf, size, position, context);
 }
 
 /*
diff --git a/src/cdi_att.h b/src/cdi_att.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c8799bbf516f310887b5d52e8cb6b86bffa2f79
--- /dev/null
+++ b/src/cdi_att.h
@@ -0,0 +1,53 @@
+#ifndef CDI_ATT_H
+#define CDI_ATT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef _CDI_LIMITS_H
+#include "cdi_limits.h"
+#endif
+
+/*
+ * CDI attribute
+ */
+typedef struct {
+  size_t    xsz;	  /* amount of space at xvalue                      */
+  size_t    namesz;       /* size of name                                   */
+  char     *name;         /* attribute name                                 */
+  int       indtype;	  /* internal data type of xvalue (INT, FLT or TXT) */
+  int       exdtype;      /* external data type                             */
+                          /* indtype    exdtype                             */
+                          /* TXT        TXT                                 */
+                          /* INT        INT16, INT32                        */
+                          /* FLT        FLT32, FLT64                        */
+  size_t    nelems;    	  /* number of elements                             */
+  void     *xvalue;       /* the actual data                                */
+} cdi_att_t;
+
+
+typedef struct {
+  size_t     nalloc;		/* number allocated >= nelems */
+  size_t     nelems;		/* length of the array */
+  cdi_att_t  value[MAX_ATTRIBUTES];
+} cdi_atts_t;
+
+
+int cdiAttsGetSize(void *p, int varID, void *context);
+
+void cdiAttsPack(void *p, int varID, void *buf, int size, int *position, void *context);
+
+void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/cdi_int.c b/src/cdi_int.c
index 50507091f62e5270a9b49320d03c9dff5c174929..03873850ffc2cb5deea634a04b682f948d0eee7d 100644
--- a/src/cdi_int.c
+++ b/src/cdi_int.c
@@ -28,7 +28,7 @@ int cdiDefaultModelID  = CDI_UNDEFID;
 int cdiDefaultTableID  = CDI_UNDEFID;
 //int cdiNcMissingValue  = CDI_UNDEFID;
 int cdiNcChunksizehint = CDI_UNDEFID;
-int cdiChunkType       = CHUNK_GRID;
+int cdiChunkType       = CDI_CHUNK_GRID;
 int cdiSplitLtype105   = CDI_UNDEFID;
 
 int cdiIgnoreAttCoordinates = FALSE;
@@ -237,9 +237,9 @@ void cdiSetChunk(const char *chunkAlgo)
   //size_t len = strlen(chunkAlgo);
   int algo = -1;
 
-  if      ( strcmp("auto",  chunkAlgo)   == 0 ) algo = CHUNK_AUTO;
-  else if ( strcmp("grid",  chunkAlgo)   == 0 ) algo = CHUNK_GRID;
-  else if ( strcmp("lines", chunkAlgo)   == 0 ) algo = CHUNK_LINES;
+  if      ( strcmp("auto",  chunkAlgo)   == 0 ) algo = CDI_CHUNK_AUTO;
+  else if ( strcmp("grid",  chunkAlgo)   == 0 ) algo = CDI_CHUNK_GRID;
+  else if ( strcmp("lines", chunkAlgo)   == 0 ) algo = CDI_CHUNK_LINES;
   /*
   else if ( (pch = strstr(chunkAlgo,"x")) != 0 )
     {
diff --git a/src/cdi_int.h b/src/cdi_int.h
index f558ac682bb3ea655b54324006aa211a74644643..67670e5449a1a96f4067a0700838e6c53f2e953c 100644
--- a/src/cdi_int.h
+++ b/src/cdi_int.h
@@ -208,6 +208,17 @@ typedef struct {
 }
 VCT;
 
+#ifdef HAVE_LIBNETCDF
+typedef struct {
+  int gridID;
+  int xdimID;
+  int ydimID;
+  int xvarID;
+  int yvarID;
+  int avarID;
+}
+ncgrid_t;
+#endif
 
 typedef struct {
   int         self;
@@ -233,17 +244,17 @@ typedef struct {
   basetime_t  basetime;
   int         ncmode;
   int         vlistID;
-  int         xdimID[MAX_GRIDS_PS];	//Warning: synchronous array to vlist_to_pointer(vlistID)->gridIDs
-  int         ydimID[MAX_GRIDS_PS];	//Warning: synchronous array to vlist_to_pointer(vlistID)->gridIDs
+#ifdef HAVE_LIBNETCDF
+  ncgrid_t   *ncgrid;
+  int         xdimID[MAX_GRIDS_PS];
+  int         ydimID[MAX_GRIDS_PS];
   int         zaxisID[MAX_ZAXES_PS];	//Warning: synchronous array to vlist_to_pointer(vlistID)->zaxisIDs
   int         nczvarID[MAX_ZAXES_PS];
-  int         ncxvarID[MAX_GRIDS_PS];
-  int         ncyvarID[MAX_GRIDS_PS];
-  int         ncavarID[MAX_GRIDS_PS];
+  VCT         vct;
+#endif
   int         historyID;
   int         globalatts;
   int         localatts;
-  VCT         vct;
   int         unreduced;
   int         sortname;
   int         have_missval;
@@ -366,6 +377,8 @@ void    vlist_check_contents(int vlistID);
 
 void    cdi_create_records(stream_t *streamptr, int tsID);
 
+void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name);
+
 int     recordNewEntry(stream_t *streamptr, int tsID);
 
 void    cdiCreateTimesteps(stream_t *streamptr);
diff --git a/src/cgribexlib.c b/src/cgribexlib.c
index 87395924d59455a56900f71b70cb0deb4a8f075a..3e9c76036cb25d5bb8fdbe4038799ee2a8a05733 100644
--- a/src/cgribexlib.c
+++ b/src/cgribexlib.c
@@ -139,8 +139,8 @@ int correct_bdslen(int bdslen, long recsize, long gribpos);
 
 /* param format:  DDDCCCNNN */
 
-void    cdiDecodeParam(int param, int *dis, int *cat, int *num);
-int     cdiEncodeParam(int dis, int cat, int num);
+void    cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis);
+int     cdiEncodeParam(int pnum, int pcat, int pdis);
 
 /* date format:  YYYYMMDD */
 /* time format:  hhmmss   */
diff --git a/src/config.h.in b/src/config.h.in
index 8f6932de4a47db0698cb1c59cf9fa5520b51ad15..8c9bcb778df2aa883ffd9efb1d2b7d810cb3e66f 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -85,9 +85,6 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
-/* Define to 1 if you have the <jasper.h> header file. */
-#undef HAVE_JASPER_H
-
 /* Define to 1 for GRIB1 decoding/encoding with cgribex */
 #undef HAVE_LIBCGRIBEX
 
@@ -103,12 +100,6 @@
 /* Define to 1 for IEG interface */
 #undef HAVE_LIBIEG
 
-/* Define to 1 for JPEG compression for GRIB2 */
-#undef HAVE_LIBJASPER
-
-/* Define to 1 for PNG compression for GRIB2 */
-#undef HAVE_LIBLIBPNG
-
 /* Define to 1 if you have the `m' library (-lm). */
 #undef HAVE_LIBM
 
@@ -121,9 +112,6 @@
 /* Define to 1 for NetCDF support */
 #undef HAVE_LIBNETCDF
 
-/* Define to 1 for JPEG compression for GRIB2 */
-#undef HAVE_LIBOPENJPEG
-
 /* Define to 1 if you have the `pthread' library (-lpthread). */
 #undef HAVE_LIBPTHREAD
 
@@ -163,15 +151,9 @@
 /* Define to 1 if you have the <netcdf_par.h> header file. */
 #undef HAVE_NETCDF_PAR_H
 
-/* Define to 1 if you have the <openjpeg.h> header file. */
-#undef HAVE_OPENJPEG_H
-
 /* netCDF library does support MPI parallel invocations */
 #undef HAVE_PARALLEL_NC4
 
-/* Define to 1 if you have the <png.h> header file. */
-#undef HAVE_PNG_H
-
 /* ScalES PPM C core library is available */
 #undef HAVE_PPM_CORE
 
diff --git a/src/file.c b/src/file.c
index 529732e12048c04dfadaf1f013fe68e9f02e4d92..4ea2e816134b0bb99d0cda2f3a5b701572ac734a 100644
--- a/src/file.c
+++ b/src/file.c
@@ -6,7 +6,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <limits.h>
+#include <stdint.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
@@ -915,7 +915,7 @@ int file_fill_buffer(bfile_t *fileptr)
 	}
       else
 	{
-          xassert(fileptr->bufferSize <= SSIZE_MAX);
+          xassert(fileptr->bufferSize <= SIZE_MAX);
 	  nread = (ssize_t)fileptr->bufferSize;
 	  if ( (nread + fileptr->bufferPos) > fileptr->size )
 	    nread = fileptr->size - fileptr->bufferPos;
diff --git a/src/gaussgrid.c b/src/gaussgrid.c
index 2ae1b9fe690755c16796b5fc3dc4b1fa9ddfbd4a..a26e1d7a44b4ec7b8fcaaf38c7944b31a0efa46d 100644
--- a/src/gaussgrid.c
+++ b/src/gaussgrid.c
@@ -10,44 +10,26 @@
 
 #include "dmemory.h"
 #include "gaussgrid.h"
-
-#ifndef  M_PI
-#define  M_PI        3.14159265358979323846  /* pi */
-#endif
-
-#ifndef  M_SQRT2
-#define  M_SQRT2     1.41421356237309504880
-#endif
+#include "cdi_int.h"
 
 
 static
-void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag, 
+void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag,
             double *pw, double *pdxn, double *pxmod)
 {
-  double zdlk;
-  double zdlldn;
-  double zdlx;
-  double zdlmod;
-  double zdlxn;
-
-  size_t ik;
-
   /* 1.0 Newton iteration step */
 
-  zdlx = pdx;
-  zdlk = 0.0;
-  if (kodd == 0) 
-    {
-      zdlk = 0.5*pfn[0];
-    }
-  zdlxn  = 0.0;
-  zdlldn = 0.0;
+  double zdlx = pdx;
+  double zdlk = 0.0;
+  if ( kodd == 0 ) zdlk = 0.5*pfn[0];
+  double zdlxn  = 0.0;
+  double zdlldn = 0.0;
 
-  ik = 1;
+  size_t ik = 1;
 
-  if (kflag == 0) 
+  if ( kflag == 0 )
     {
-      for(size_t jn = 2-kodd; jn <= kn; jn += 2) 
+      for ( size_t jn = 2-kodd; jn <= kn; jn += 2 )
 	{
 	  /* normalised ordinary Legendre polynomial == \overbar{p_n}^0 */
 	  zdlk   = zdlk + pfn[ik]*cos((double)(jn)*zdlx);
@@ -56,7 +38,7 @@ void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag,
 	  ik++;
 	}
       /* Newton method */
-      zdlmod = -(zdlk/zdlldn);
+      double zdlmod = -(zdlk/zdlldn);
       zdlxn = zdlx + zdlmod;
       *pdxn = zdlxn;
       *pxmod = zdlmod;
@@ -64,9 +46,9 @@ void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag,
 
   /* 2.0 Compute weights */
 
-  if (kflag == 1) 
+  if ( kflag == 1 )
     {
-      for(size_t jn = 2-kodd; jn <= kn; jn += 2) 
+      for ( size_t jn = 2-kodd; jn <= kn; jn += 2 )
 	{
 	  /* normalised derivative */
 	  zdlldn = zdlldn - pfn[ik]*(double)(jn)*sin((double)(jn)*zdlx);
@@ -82,24 +64,21 @@ static
 void gawl(double *pfn, double *pl, double *pw, size_t kn)
 {
   double pmod = 0;
-  int iflag;
-  int itemax;
   double zw = 0;
-  double zdlx;
   double zdlxn = 0;
 
   /* 1.0 Initizialization */
 
-  iflag  =  0;
-  itemax = 20;
+  int iflag  =  0;
+  int itemax = 20;
 
   size_t iodd   = (kn % 2);
 
-  zdlx   =  *pl;
+  double zdlx   =  *pl;
 
   /* 2.0 Newton iteration */
 
-  for (int jter = 1; jter <= itemax+1; jter++)
+  for ( int jter = 1; jter <= itemax+1; jter++ )
     {
       cpledn(kn, iodd, pfn, zdlx, iflag, &zw, &zdlxn, &pmod);
       zdlx = zdlxn;
@@ -114,7 +93,7 @@ void gawl(double *pfn, double *pl, double *pw, size_t kn)
 }
 
 static
-void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
+void gauaw(size_t kn, double *restrict pl, double *restrict pw)
 {
   /*
    * 1.0 Initialize Fourier coefficients for ordinary Legendre polynomials
@@ -122,26 +101,22 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
    * Belousov, Swarztrauber, and ECHAM use zfn(0,0) = sqrt(2)
    * IFS normalisation chosen to be 0.5*Integral(Pnm**2) = 1 (zfn(0,0) = 2.0)
    */
-  double *zfn, *zfnlat;
-
-  double z, zfnn;
-
-  zfn    = (double *) Malloc((kn+1) * (kn+1) * sizeof(double));
-  zfnlat = (double *) Malloc((kn/2+1+1)*sizeof(double));
+  double *zfn    = (double *) Malloc((kn+1) * (kn+1) * sizeof(double));
+  double *zfnlat = (double *) Malloc((kn/2+1+1)*sizeof(double));
 
   zfn[0] = M_SQRT2;
-  for (size_t jn = 1; jn <= kn; jn++)
+  for ( size_t jn = 1; jn <= kn; jn++ )
     {
-      zfnn = zfn[0];
+      double zfnn = zfn[0];
       for (size_t jgl = 1; jgl <= jn; jgl++)
 	{
-	  zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl))); 
+	  zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl)));
 	}
 
       zfn[jn*(kn+1)+jn] = zfnn;
 
       size_t iodd = jn % 2;
-      for (size_t jgl = 2; jgl <= jn-iodd; jgl += 2) 
+      for ( size_t jgl = 2; jgl <= jn-iodd; jgl += 2 )
 	{
 	  zfn[jn*(kn+1)+jn-jgl] = zfn[jn*(kn+1)+jn-jgl+2]
 	    *((double)((jgl-1)*(2*jn-jgl+2)))/((double)(jgl*(2*jn-jgl+1)));
@@ -153,11 +128,11 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
 
   size_t iodd = kn % 2;
   size_t ik = iodd;
-  for (size_t jgl = iodd; jgl <= kn; jgl += 2)
+  for ( size_t jgl = iodd; jgl <= kn; jgl += 2 )
     {
       zfnlat[ik] = zfn[kn*(kn+1)+jgl];
       ik++;
-    } 
+    }
 
   /*
    * 2.1 Find first approximation of the roots of the
@@ -165,16 +140,17 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
    */
 
   size_t ins2 = kn/2+(kn % 2);
+  double z;
 
-  for (size_t jgl = 1; jgl <= ins2; jgl++) 
+  for ( size_t jgl = 1; jgl <= ins2; jgl++ )
     {
-      z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2)); 
+      z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2));
       pl[jgl-1] = z+1.0/(tan(z)*((double)(8*kn*kn)));
     }
 
   /* 2.2 Computes roots and weights for transformed theta */
 
-  for (size_t jgl = ins2; jgl >= 1 ; jgl--) 
+  for ( size_t jgl = ins2; jgl >= 1 ; jgl-- )
     {
       size_t jglm1 = jgl-1;
       gawl(zfnlat, &(pl[jglm1]), &(pw[jglm1]), kn);
@@ -182,12 +158,12 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
 
   /* convert to physical latitude */
 
-  for (size_t jgl = 0; jgl < ins2; jgl++) 
+  for ( size_t jgl = 0; jgl < ins2; jgl++ )
     {
       pl[jgl] = cos(pl[jgl]);
     }
 
-  for (size_t jgl = 1; jgl <= kn/2; jgl++) 
+  for ( size_t jgl = 1; jgl <= kn/2; jgl++ )
     {
       size_t jglm1 = jgl-1;
       size_t isym =  kn-jgl;
@@ -201,103 +177,48 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw)
   return;
 }
 
-#if 0
-static
-void gauaw_old(double *pa, double *pw, int nlat)
-{
-  /*
-   * Compute Gaussian latitudes.  On return pa contains the
-   * sine of the latitudes starting closest to the north pole and going
-   * toward the south
-   *
-   */
-
-  const int itemax = 20;
-
-  int isym, iter, ins2, jn, j;
-  double za, zw, zan;
-  double z, zk, zkm1, zkm2, zx, zxn, zldn, zmod;
 
-  /*
-   * Perform the Newton loop
-   * Find 0 of Legendre polynomial with Newton loop
-   */
-
-  ins2 = nlat/2 + nlat%2;
-
-  for ( j = 0; j < ins2; j++ )
-    {
-      z = (double) (4*(j+1)-1)*M_PI / (double) (4*nlat+2);
-      pa[j] = cos(z + 1.0/(tan(z)*(double)(8*nlat*nlat)));
-    }
-
-  for ( j = 0; j < ins2; j++ )
-    {
-
-      za = pa[j];
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat)
+{
+  //gauaw_old(pa, pw, nlat);
+  gauaw(nlat, pa, pw);
+}
 
-      iter = 0;
-      do
-	{
-	  iter++;
-	  zk = 0.0;
-
-	  /* Newton iteration step */
-
-	  zkm2 = 1.0;
-	  zkm1 = za;
-	  zx = za;
-	  for ( jn = 2; jn <= nlat; jn++ )
-	    {
-	      zk = ((double) (2*jn-1)*zx*zkm1-(double)(jn-1)*zkm2) / (double)(jn);
-	      zkm2 = zkm1;
-	      zkm1 = zk;
-	    }
-	  zkm1 = zkm2;
-	  zldn = ((double) (nlat)*(zkm1-zx*zk)) / (1.-zx*zx);
-	  zmod = -zk/zldn;
-	  zxn = zx+zmod;
-	  zan = zxn;
-
-	  /* computes weight */
-
-	  zkm2 = 1.0;
-	  zkm1 = zxn;
-	  zx = zxn;
-	  for ( jn = 2; jn <= nlat; jn++ )
-	    {
-	      zk = ((double) (2*jn-1)*zx*zkm1-(double)(jn-1)*zkm2) / (double) (jn);
-	      zkm2 = zkm1;
-	      zkm1 = zk;
-	    }
-	  zkm1 = zkm2;
-	  zw = (1.0-zx*zx) / ((double) (nlat*nlat)*zkm1*zkm1);
-	  za = zan;
-	}
-      while ( iter <= itemax && fabs(zmod) >= DBL_EPSILON );
 
-      pa[j] = zan;
-      pw[j] = 2.0*zw;
-    }
+bool isGaussGrid(size_t ysize, double yinc, const double *yvals)
+{
+  bool lgauss = false;
 
-#if defined (SX)
-#pragma vdir nodep
-#endif
-  for (j = 0; j < nlat/2; j++)
+  if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */
     {
-      isym = nlat-(j+1);
-      pa[isym] = -pa[j];
-      pw[isym] =  pw[j];
+      size_t i;
+      double *yv = (double *) Malloc(ysize*sizeof(double));
+      double *yw = (double *) Malloc(ysize*sizeof(double));
+      gaussaw(yv, yw, ysize);
+      Free(yw);
+      for ( i = 0; i < ysize; i++ )
+        yv[i] = asin(yv[i])/M_PI*180.0;
+
+      for ( i = 0; i < ysize; i++ )
+        if ( fabs(yv[i] - yvals[i]) >
+             ((yv[0] - yv[1])/500) ) break;
+
+      if ( i == ysize ) lgauss = true;
+
+      /* check S->N */
+      if ( lgauss == false )
+        {
+          for ( i = 0; i < ysize; i++ )
+            if ( fabs(yv[i] - yvals[ysize-i-1]) >
+                 ((yv[0] - yv[1])/500) ) break;
+
+          if ( i == ysize ) lgauss = true;
+        }
+
+      Free(yv);
     }
 
-  return;
-}
-#endif
-
-void gaussaw(double *restrict pa, double *restrict pw, size_t nlat)
-{
-  //gauaw_old(pa, pw, nlat);
-  gauaw(nlat, pa, pw);
+  return lgauss;
 }
 
 /*
@@ -312,7 +233,6 @@ int main (int rgc, char *argv[])
   int i;
 
   gauaw(ngl, pl, pw);
-  gauaw_old(plo, pwo, ngl);
   for (i = 0; i < ngl; i++)
     {
       pl[i]  = asin(pl[i])/M_PI*180.0;
diff --git a/src/gaussgrid.h b/src/gaussgrid.h
index e33df5ed6ea26ed2b46870499fa27ebe74e36ba7..3973a6375fe83f9873bbe6f3cda4c773db77fe81 100644
--- a/src/gaussgrid.h
+++ b/src/gaussgrid.h
@@ -1,11 +1,14 @@
 #ifndef _GAUSSGRID_H
 #define _GAUSSGRID_H
 
+#include <stdbool.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+bool isGaussGrid(size_t ysize, double yinc, const double *yvals);
 
 #if defined (__cplusplus)
 }
diff --git a/src/getline.c b/src/getline.c
index 8001390453e06859e979cff71db78ca2079928e8..a77178678d0260c141a8443059516966e1da646d 100644
--- a/src/getline.c
+++ b/src/getline.c
@@ -30,9 +30,10 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <limits.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <string.h>
+#include <limits.h>
 
 /* read until end of line or end of file */
 ssize_t
@@ -82,7 +83,7 @@ getline(char **linebuf, size_t *linebuf_size, FILE *fp)
               && (len += strlen(buf + len)) > old_len
               && buf[len-1] != '\n');
     }
-    status = len > SSIZE_MAX ? SSIZE_MAX : (ssize_t)len;
+    status = len > SIZE_MAX ? SIZE_MAX : (ssize_t)len;
   }
   if (linebuf_size)
     *linebuf_size = buf_size;
diff --git a/src/grb_write.c b/src/grb_write.c
index f47eb68a1f5e840e45649be56eb543171c468b46..9dc61db2a2b30129a6fa6e441d618c880d98cfe6 100644
--- a/src/grb_write.c
+++ b/src/grb_write.c
@@ -121,7 +121,7 @@ void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
       long unzipsize;
       int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
 
-      if ( izip == 0 && streamptr2->comptype == COMPRESS_SZIP )
+      if ( izip == 0 && streamptr2->comptype == CDI_COMPRESS_SZIP )
           nbytes = grbSzip(filetype, gribbuffer, nbytes);
     }
 
@@ -178,9 +178,9 @@ void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp
 #endif
     }
 
-  if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
+  if ( comptype != CDI_COMPRESS_JPEG && comptype != CDI_COMPRESS_SZIP ) comptype = CDI_COMPRESS_NONE;
 
-  if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
+  if ( filetype == FILETYPE_GRB && comptype == CDI_COMPRESS_JPEG )
     {
       static int ljpeg_warn = 1;
       if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
@@ -190,7 +190,7 @@ void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp
   size_t nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
                             datasize, data, nmiss, &gribbuffer, comptype, gc);
 
-  if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
+  if ( filetype == FILETYPE_GRB && streamptr->comptype == CDI_COMPRESS_SZIP )
     nbytes = grbSzip(filetype, gribbuffer, nbytes);
 
   size_t (*myFileWrite)(int fileID, const void *restrict buffer,
diff --git a/src/gribapi.c b/src/gribapi.c
index 675816ecf4c926eaec39264588844eb0f1b1c258..a032dda698e6f69d87c1e853f3f2a62bc0e4dbda 100644
--- a/src/gribapi.c
+++ b/src/gribapi.c
@@ -53,12 +53,10 @@ const char *gribapiLibraryVersionString(void)
 
 void gribContainersNew(stream_t * streamptr)
 {
-  int editionNumber = 2;
+  int editionNumber = (streamptr->filetype == FILETYPE_GRB) ? 1 : 2;
 
-  if ( streamptr->filetype == FILETYPE_GRB ) editionNumber = 1;
-  (void)editionNumber;
 #if  defined  (HAVE_LIBCGRIBEX)
-  if ( streamptr->filetype == FILETYPE_GRB )
+  if ( editionNumber == 1 )
     {
     }
   else
diff --git a/src/gribapi_utilities.c b/src/gribapi_utilities.c
index 9bdcaf66075a12275c0c2877bf5816527797abe1..6c53fde888975cd584f0cc3bae56b4b7594e4af7 100644
--- a/src/gribapi_utilities.c
+++ b/src/gribapi_utilities.c
@@ -276,7 +276,7 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
         return 0;
 
       //case 55 and case 40455 are the same: 55 is the proposed standard value, 40455 is the value in the local use range that is used by the dwd until the standard is updated.
-      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 60: case 1000: case 1002: case 1100: case 40033: case 40455:
+      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 56: case 60: case 1000: case 1002: case 1100: case 40033: case 40455: case 40456:
         *outHaveForecastTime = true, *outHaveTimeRange = false;
         return 0;
 
@@ -429,7 +429,11 @@ int gribapiGetGridType(grib_handle *gh)
         gridtype = ( gribGetLong(gh, "Ni") == (long) GRIB_MISSING_LONG ) ? GRID_GAUSSIAN_REDUCED : GRID_GAUSSIAN;
         break;
 
+#ifdef TEST_PROJECTION
+      case GRIB2_GTYPE_LATLON_ROT:   gridtype = GRID_PROJECTION; break;
+#else
       case GRIB2_GTYPE_LATLON_ROT:   gridtype = GRID_LONLAT; break;
+#endif
       case GRIB2_GTYPE_LCC:          gridtype = GRID_LCC; break;
       case GRIB2_GTYPE_SPECTRAL:     gridtype = GRID_SPECTRAL; break;
       case GRIB2_GTYPE_GME:          gridtype = GRID_GME; break;
@@ -450,6 +454,7 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 {
   long editionNumber = gribEditionNumber(gh);
   int gridtype = gribapiGetGridType(gh);
+  int projtype = (gridtype == GRID_PROJECTION && gribapiGetIsRotated(gh)) ? CDI_PROJ_RLL : CDI_UNDEFID;
   /*
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -466,306 +471,267 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
   long numberOfPoints;
   FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfPoints", &numberOfPoints);
 
-  switch (gridtype)
+  long lpar;
+
+  if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL )
     {
-    case GRID_LONLAT:
-    case GRID_GAUSSIAN:
-      {
-        long nlon, nlat;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon);
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat);
+      long nlon, nlat;
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon);
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat);
 
-        if ( gridtype == GRID_GAUSSIAN )
-          {
-            long lpar;
-            FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
-            grid->np = (int)lpar;
-          }
+      if ( gridtype == GRID_GAUSSIAN )
+        {
+          FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
+          grid->np = (int)lpar;
+        }
 
-        if ( numberOfPoints != nlon*nlat )
-          Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat);
-
-        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
-        grid->size  = (int)numberOfPoints;
-        grid->xsize = (int)nlon;
-        grid->ysize = (int)nlat;
-        grid->xinc  = 0;
-        grid->yinc  = 0;
-        grid->xdef  = 0;
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-        if ( nlon > 1 )
-          FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
-        if ( gridtype == GRID_LONLAT && nlat > 1 )
-          FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->yinc);
-
-        if ( grid->xinc < -999 || grid->xinc > 999 ) grid->xinc = 0;
-        if ( grid->yinc < -999 || grid->yinc > 999 ) grid->yinc = 0;
-
-        if ( grid->yinc > 0 && grid->yfirst > grid->ylast ) grid->yinc = -grid->yinc;
-
-        /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
+      if ( numberOfPoints != nlon*nlat )
+        Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat);
+
+      grid->size  = (int)numberOfPoints;
+      grid->x.size = (int)nlon;
+      grid->y.size = (int)nlat;
+      grid->x.inc  = 0;
+      grid->y.inc  = 0;
+      grid->x.flag = 0;
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->x.first);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->x.last);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->y.first);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->y.last);
+      if ( nlon > 1 )
+        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->x.inc);
+      if ( gridtype == GRID_LONLAT && nlat > 1 )
+        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->y.inc);
+
+      if ( grid->x.inc < -999 || grid->x.inc > 999 ) grid->x.inc = 0;
+      if ( grid->y.inc < -999 || grid->y.inc > 999 ) grid->y.inc = 0;
+
+      if ( grid->y.inc > 0 && grid->y.first > grid->y.last ) grid->y.inc = -grid->y.inc;
+
+      /* if ( IS_NOT_EQUAL(grid->x.first, 0) || IS_NOT_EQUAL(grid->x.last, 0) ) */
+      {
+        if ( grid->x.size > 1 )
           {
-            if ( grid->xsize > 1 )
-              {
-                if ( (grid->xfirst >= grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360;
+            if ( (grid->x.first >= grid->x.last) && (grid->x.first >= 180) ) grid->x.first -= 360;
 
-                if ( editionNumber <= 1 )
+            if ( editionNumber <= 1 )
+              {
+                /* correct xinc if necessary */
+                if ( IS_EQUAL(grid->x.first, 0) && grid->x.last > 354 )
                   {
-                    /* correct xinc if necessary */
-                    if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 )
+                    double xinc = 360. / grid->x.size;
+                    if ( fabs(grid->x.inc-xinc) > 0.0 )
                       {
-                        double xinc = 360. / grid->xsize;
-
-                        if ( fabs(grid->xinc-xinc) > 0.0 )
-                          {
-                            grid->xinc = xinc;
-                            if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
-                          }
+                        grid->x.inc = xinc;
+                        if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc);
                       }
                   }
               }
-            grid->xdef = 2;
           }
-        grid->ydef = 0;
-        /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */
+        grid->x.flag = 2;
+      }
+      grid->y.flag = 0;
+      /* if ( IS_NOT_EQUAL(grid->y.first, 0) || IS_NOT_EQUAL(grid->y.last, 0) ) */
+      {
+        if ( grid->y.size > 1 )
           {
-            if ( grid->ysize > 1 )
+            if ( editionNumber <= 1 )
               {
-                if ( editionNumber <= 1 )
-                  {
-                  }
               }
-            grid->ydef = 2;
           }
-        break;
+        grid->y.flag = 2;
       }
-    case GRID_GAUSSIAN_REDUCED:
+    }
+  else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+    {
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
+      grid->np = (int)lpar;
+
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar);
+      int nlat = (int)lpar;
+
+      grid->size   = (int)numberOfPoints;
+
+      grid->nrowlon = nlat;
+      grid->rowlon = (int *) Malloc((size_t)nlat * sizeof (int));
+      long *pl     = (long *) Malloc((size_t)nlat * sizeof (long));
+      size_t dummy = (size_t)nlat;
+      FAIL_ON_GRIB_ERROR(grib_get_long_array, gh, "pl", pl, &dummy);
+      for ( int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i];
+      Free(pl);
+
+      grid->y.size  = nlat;
+      grid->x.inc   = 0;
+      grid->y.inc   = 0;
+      grid->x.flag  = 0;
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->x.first);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->x.last);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->y.first);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->y.last);
+
+      // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->x.inc);
+      // if ( IS_EQUAL(grid->x.inc, GRIB_MISSING_DOUBLE) ) grid->x.inc = 0;
+
+      /* if ( IS_NOT_EQUAL(grid->x.first, 0) || IS_NOT_EQUAL(grid->x.last, 0) ) */
       {
-        long lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        grid->np = (int)lpar;
-
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar);
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        int nlat = (int)lpar;
-
-        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
-        grid->size   = (int)numberOfPoints;
-
-        grid->nrowlon = nlat;
-        grid->rowlon = (int *) Malloc((size_t)nlat * sizeof (int));
-        long *pl     = (long *) Malloc((size_t)nlat * sizeof (long));
-        size_t dummy = (size_t)nlat;
-        FAIL_ON_GRIB_ERROR(grib_get_long_array, gh, "pl", pl, &dummy);
-        /* FIXME: assert(pl[i] >= INT_MIN && pl[i] <= INT_MIN) */
-        for ( int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i];
-        Free(pl);
-
-        grid->ysize  = nlat;
-        grid->xinc   = 0;
-        grid->yinc   = 0;
-        grid->xdef   = 0;
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast);
-
-        // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc);
-        // if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
-
-        /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
+        if ( grid->x.size > 1 )
           {
-            if ( grid->xsize > 1 )
-              {
-                if ( (grid->xfirst > grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360;
+            if ( (grid->x.first > grid->x.last) && (grid->x.first >= 180) ) grid->x.first -= 360;
 
-                if ( editionNumber <= 1 )
+            if ( editionNumber <= 1 )
+              {
+                /* correct xinc if necessary */
+                if ( IS_EQUAL(grid->x.first, 0) && grid->x.last > 354 )
                   {
-                    /* correct xinc if necessary */
-                    if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 )
+                    double xinc = 360. / grid->x.size;
+                    if ( fabs(grid->x.inc-xinc) > 0.0 )
                       {
-                        double xinc = 360. / grid->xsize;
-
-                        if ( fabs(grid->xinc-xinc) > 0.0 )
-                          {
-                            grid->xinc = xinc;
-                            if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
-                          }
+                        grid->x.inc = xinc;
+                        if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc);
                       }
                   }
               }
-            grid->xdef = 2;
           }
-        grid->ydef  = 0;
-        /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */
+        grid->x.flag = 2;
+      }
+      grid->y.flag = 0;
+      /* if ( IS_NOT_EQUAL(grid->y.first, 0) || IS_NOT_EQUAL(grid->y.last, 0) ) */
+      {
+        if ( grid->y.size > 1 )
           {
-            if ( grid->ysize > 1 )
+            if ( editionNumber <= 1 )
               {
-                if ( editionNumber <= 1 )
-                  {
-                  }
               }
-            grid->ydef = 2;
           }
-        break;
+        grid->y.flag = 2;
       }
-    case GRID_LCC:
-      {
-        int nlon, nlat;
-        long lpar;
-
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nx", &lpar);
-        nlon = (int)lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ny", &lpar);
-        nlat = (int)lpar;
-
-        if ( numberOfPoints != nlon*nlat )
-          Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat);
-
-        grid->size  = (int)numberOfPoints;
-        grid->xsize = nlon;
-        grid->ysize = nlat;
-
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &grid->lcc_xinc);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &grid->lcc_yinc);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->lcc_originLon);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->lcc_originLat);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "LoVInDegrees", &grid->lcc_lonParY);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin1InDegrees", &grid->lcc_lat1);
-        FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin2InDegrees", &grid->lcc_lat2);
-
-        if ( editionNumber <= 1 )
-          {
-            FAIL_ON_GRIB_ERROR(grib_get_long, gh, "projectionCenterFlag", &lpar);
-            grid->lcc_projflag  = (int) lpar;
-            FAIL_ON_GRIB_ERROR(grib_get_long, gh, "scanningMode", &lpar);
-            grid->lcc_scanflag  = (int) lpar;
-          }
-
-        grid->xdef   = 0;
-        grid->ydef   = 0;
+    }
+  else if ( gridtype == GRID_LCC )
+    {
+      int nlon, nlat;
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nx", &lpar);
+      nlon = (int)lpar;
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ny", &lpar);
+      nlat = (int)lpar;
+
+      if ( numberOfPoints != nlon*nlat )
+        Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat);
+
+      grid->size  = (int)numberOfPoints;
+      grid->x.size = nlon;
+      grid->y.size = nlat;
+
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &grid->lcc.xinc);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &grid->lcc.yinc);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->lcc.originLon);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->lcc.originLat);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "LoVInDegrees", &grid->lcc.lonParY);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin1InDegrees", &grid->lcc.lat1);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin2InDegrees", &grid->lcc.lat2);
+
+      if ( editionNumber <= 1 )
+        {
+          FAIL_ON_GRIB_ERROR(grib_get_long, gh, "projectionCenterFlag", &lpar);
+          grid->lcc.projflag  = (int) lpar;
+          FAIL_ON_GRIB_ERROR(grib_get_long, gh, "scanningMode", &lpar);
+          grid->lcc.scanflag  = (int) lpar;
+        }
 
-        break;
-      }
-    case GRID_SPECTRAL:
-      {
-        size_t len = 256;
-        char typeOfPacking[256];
-        FAIL_ON_GRIB_ERROR(grib_get_string, gh, "packingType", typeOfPacking, &len);
-        grid->lcomplex = 0;
-        if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1;
-
-        /* FIXME: assert(datasize >= INT_MIN && datasize <= INT_MAX) */
-        grid->size  = (int)datasize;
-        long lpar;
-        FAIL_ON_GRIB_ERROR(grib_get_long, gh, "J", &lpar);
-        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
-        grid->trunc = (int)lpar;
+      grid->x.flag = 0;
+      grid->y.flag = 0;
+    }
+  else if ( gridtype == GRID_SPECTRAL )
+    {
+      size_t len = 256;
+      char typeOfPacking[256];
+      FAIL_ON_GRIB_ERROR(grib_get_string, gh, "packingType", typeOfPacking, &len);
+      grid->lcomplex = 0;
+      if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1;
 
-        break;
-      }
-    case GRID_GME:
-      {
-        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
-        grid->size  = (int)numberOfPoints;
-        long lpar;
-        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
-        if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->nd  = (int)lpar;
-        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
-        if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->ni  = (int)lpar;
-        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
-        if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->ni2 = (int)lpar;
-        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
-        if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->ni3 = (int)lpar;
+      grid->size  = (int)datasize;
 
-        break;
-      }
-    case GRID_UNSTRUCTURED:
-      {
-        unsigned char uuid[CDI_UUID_SIZE];
-        /*
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "J", &lpar);
+      grid->trunc = (int)lpar;
+    }
+  else if ( gridtype == GRID_GME )
+    {
+      grid->size  = (int)numberOfPoints;
+      if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->gme.nd  = (int)lpar;
+      if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->gme.ni  = (int)lpar;
+      if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->gme.ni2 = (int)lpar;
+      if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->gme.ni3 = (int)lpar;
+    }
+  else if ( gridtype == GRID_UNSTRUCTURED )
+    {
+      unsigned char uuid[CDI_UUID_SIZE];
+      /*
         char reference_link[8192];
         size_t len = sizeof(reference_link);
         reference_link[0] = 0;
-        */
+      */
+      grid->size  = (int)numberOfPoints;
 
-        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
-            grid->size  = (int)numberOfPoints;
-        long lpar;
-        if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 )
-          {
-            /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-            grid->number   = (int)lpar;
-            /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-            if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 )
-              grid->position = (int)lpar;
-            /*
+      if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 )
+        {
+          grid->number   = (int)lpar;
+          if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 )
+            grid->position = (int)lpar;
+          /*
             if ( grib_get_string(gh, "gridDescriptionFile", reference_link, &len) == 0 )
-              {
-                if ( strncmp(reference_link, "file://", 7) == 0 )
-                  grid->reference = strdupx(reference_link);
-              }
-            */
-            size_t len = (size_t)CDI_UUID_SIZE;
-            if ( grib_get_bytes(gh, "uuidOfHGrid", uuid, &len) == 0)
-              {
-                memcpy(grid->uuid, uuid, CDI_UUID_SIZE);
-              }
-          }
-        break;
-      }
-    case GRID_GENERIC:
-      {
-        int nlon = 0, nlat = 0;
-        long lpar;
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = (int)lpar;
-        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
-        if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = (int)lpar;
-
-        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
-        grid->size  = (int)numberOfPoints;
+            {
+            if ( strncmp(reference_link, "file://", 7) == 0 )
+            grid->reference = strdupx(reference_link);
+            }
+          */
+          size_t len = (size_t)CDI_UUID_SIZE;
+          if ( grib_get_bytes(gh, "uuidOfHGrid", uuid, &len) == 0)
+            {
+              memcpy(grid->uuid, uuid, CDI_UUID_SIZE);
+            }
+        }
+    }
+  else if ( gridtype == GRID_GENERIC )
+    {
+      int nlon = 0, nlat = 0;
+      if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = (int)lpar;
+      if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = (int)lpar;
 
-        if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size )
-          {
-            grid->xsize = nlon;
-            grid->ysize = nlat;
-          }
-        else
-          {
-            grid->xsize = 0;
-            grid->ysize = 0;
-          }
+      grid->size  = (int)numberOfPoints;
 
-        break;
-      }
-    default:
-      {
-        Error("Unsupported grid type: %s", gridNamePtr(gridtype));
-        break;
-      }
+      if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size )
+        {
+          grid->x.size = nlon;
+          grid->y.size = nlat;
+        }
+      else
+        {
+          grid->x.size = 0;
+          grid->y.size = 0;
+        }
+    }
+  else
+    {
+      Error("Unsupported grid type: %s", gridNamePtr(gridtype));
     }
 
   grid->isRotated = FALSE;
   if ( gribapiGetIsRotated(gh) )
     {
+      double xpole = 0, ypole = 0, angle = 0;
       grid->isRotated = TRUE;
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfSouthernPoleInDegrees",  &grid->ypole);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfSouthernPoleInDegrees", &grid->xpole);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "angleOfRotation", &grid->angle);
-      /* change from south to north pole */
-      if ( fabs(grid->ypole) > 0 ) grid->ypole = -grid->ypole;
-      grid->xpole =  grid->xpole - 180;
-      if ( fabs(grid->angle) > 0 ) grid->angle = -grid->angle;
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfSouthernPoleInDegrees",  &ypole);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfSouthernPoleInDegrees", &xpole);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "angleOfRotation", &angle);
+      xpole =  xpole - 180;
+      if ( fabs(ypole) > 0 ) ypole = -ypole; // change from south to north pole
+      if ( fabs(angle) > 0 ) angle = -angle;
+      grid->rll.xpole = xpole;
+      grid->rll.ypole = ypole;
+      grid->rll.angle = angle;
     }
 
-  grid->xvals = NULL;
-  grid->yvals = NULL;
   grid->type  = gridtype;
+  grid->projtype  = projtype;
 }
 #endif
 /*
diff --git a/src/grid.c b/src/grid.c
index 9a681357874c878322c950790e5baab960920893..99a41cbd97169630cfaba20f49f4db4d87311194 100644
--- a/src/grid.c
+++ b/src/grid.c
@@ -94,79 +94,90 @@ void grid_init(grid_t *gridptr)
   gridptr->self          = CDI_UNDEFID;
   gridptr->type          = CDI_UNDEFID;
   gridptr->proj          = CDI_UNDEFID;
+  gridptr->projtype      = CDI_UNDEFID;
   gridptr->mask          = NULL;
   gridptr->mask_gme      = NULL;
-  gridptr->xvals         = NULL;
-  gridptr->yvals         = NULL;
+  gridptr->x.vals        = NULL;
+  gridptr->y.vals        = NULL;
+  gridptr->x.bounds      = NULL;
+  gridptr->y.bounds      = NULL;
   gridptr->area          = NULL;
-  gridptr->xbounds       = NULL;
-  gridptr->ybounds       = NULL;
   gridptr->rowlon        = NULL;
   gridptr->nrowlon       = 0;
-  gridptr->xfirst        = 0.0;
-  gridptr->xlast         = 0.0;
-  gridptr->xinc          = 0.0;
-  gridptr->yfirst        = 0.0;
-  gridptr->ylast         = 0.0;
-  gridptr->yinc          = 0.0;
-  gridptr->lcc_originLon = 0.0;
-  gridptr->lcc_originLat = 0.0;
-  gridptr->lcc_lonParY   = 0.0;
-  gridptr->lcc_lat1      = 0.0;
-  gridptr->lcc_lat2      = 0.0;
-  gridptr->lcc_xinc      = 0.0;
-  gridptr->lcc_yinc      = 0.0;
-  gridptr->lcc_projflag  = 0;
-  gridptr->lcc_scanflag  = 0;
-  gridptr->lcc_defined   = FALSE;
-  gridptr->lcc2_lon_0    = 0.0;
-  gridptr->lcc2_lat_0    = 0.0;
-  gridptr->lcc2_lat_1    = 0.0;
-  gridptr->lcc2_lat_2    = 0.0;
-  gridptr->lcc2_a        = 0.0;
-  gridptr->lcc2_defined  = FALSE;
-  gridptr->laea_lon_0    = 0.0;
-  gridptr->laea_lat_0    = 0.0;
-  gridptr->laea_a        = 0.0;
-  gridptr->laea_defined  = FALSE;
+
+  gridptr->x.first       = 0.0;
+  gridptr->x.last        = 0.0;
+  gridptr->x.inc         = 0.0;
+  gridptr->y.first       = 0.0;
+  gridptr->y.last        = 0.0;
+  gridptr->y.inc         = 0.0;
+
+  gridptr->lcc.originLon = 0.0;
+  gridptr->lcc.originLat = 0.0;
+  gridptr->lcc.lonParY   = 0.0;
+  gridptr->lcc.lat1      = 0.0;
+  gridptr->lcc.lat2      = 0.0;
+  gridptr->lcc.xinc      = 0.0;
+  gridptr->lcc.yinc      = 0.0;
+  gridptr->lcc.projflag  = 0;
+  gridptr->lcc.scanflag  = 0;
+  gridptr->lcc.defined   = FALSE;
+  gridptr->lcc2.lon_0    = 0.0;
+  gridptr->lcc2.lat_0    = 0.0;
+  gridptr->lcc2.lat_1    = 0.0;
+  gridptr->lcc2.lat_2    = 0.0;
+  gridptr->lcc2.a        = 0.0;
+  gridptr->lcc2.defined  = FALSE;
+
+  gridptr->laea.lon_0    = 0.0;
+  gridptr->laea.lat_0    = 0.0;
+  gridptr->laea.a        = 0.0;
+  gridptr->laea.defined  = FALSE;
+
+  gridptr->gme.nd        = 0;
+  gridptr->gme.ni        = 0;
+  gridptr->gme.ni2       = 0;
+  gridptr->gme.ni3       = 0;
+
+  gridptr->isRotated     = FALSE;
+  gridptr->rll.xpole     = 0.0;
+  gridptr->rll.ypole     = 0.0;
+  gridptr->rll.angle     = 0.0;
+
   gridptr->trunc         = 0;
   gridptr->nvertex       = 0;
-  gridptr->nd            = 0;
-  gridptr->ni            = 0;
-  gridptr->ni2           = 0;
-  gridptr->ni3           = 0;
   gridptr->number        = 0;
   gridptr->position      = 0;
   gridptr->reference     = NULL;
   gridptr->prec          = 0;
   gridptr->size          = 0;
-  gridptr->xsize         = 0;
-  gridptr->ysize         = 0;
+  gridptr->x.size        = 0;
+  gridptr->y.size        = 0;
   gridptr->np            = 0;
-  gridptr->xdef          = 0;
-  gridptr->ydef          = 0;
+  gridptr->x.flag        = 0;
+  gridptr->y.flag        = 0;
   gridptr->isCyclic      = CDI_UNDEFID;
-  gridptr->isRotated     = FALSE;
-  gridptr->xpole         = 0.0;
-  gridptr->ypole         = 0.0;
-  gridptr->angle         = 0.0;
-  gridptr->lcomplex      = 0;
-  gridptr->hasdims       = TRUE;
-  gridptr->xdimname[0]   = 0;
-  gridptr->ydimname[0]   = 0;
+
+  gridptr->lcomplex      = false;
+  gridptr->hasdims       = true;
+  gridptr->x.dimname[0]  = 0;
+  gridptr->y.dimname[0]  = 0;
+  gridptr->x.name[0]     = 0;
+  gridptr->y.name[0]     = 0;
+  gridptr->x.longname[0] = 0;
+  gridptr->y.longname[0] = 0;
+  gridptr->x.units[0]    = 0;
+  gridptr->y.units[0]    = 0;
+  gridptr->x.stdname     = NULL;
+  gridptr->y.stdname     = NULL;
   gridptr->vdimname[0]   = 0;
-  gridptr->xname[0]      = 0;
-  gridptr->yname[0]      = 0;
-  gridptr->xlongname[0]  = 0;
-  gridptr->ylongname[0]  = 0;
-  gridptr->xunits[0]     = 0;
-  gridptr->yunits[0]     = 0;
-  gridptr->xstdname      = NULL;
-  gridptr->ystdname      = NULL;
+  gridptr->mapname[0]    = 0;
+  gridptr->mapping[0]    = 0;
   memset(gridptr->uuid, 0, CDI_UUID_SIZE);
   gridptr->name          = NULL;
   gridptr->vtable        = &cdiGridVtable;
-  gridptr->extraData     = NULL;
+  gridptr->atts.nalloc   = MAX_ATTRIBUTES;
+  gridptr->atts.nelems   = 0;
 }
 
 
@@ -174,12 +185,13 @@ static void
 grid_free_components(grid_t *gridptr)
 {
   void *p2free[] = { gridptr->mask, gridptr->mask_gme,
-                   gridptr->xvals, gridptr->yvals,
-                   gridptr->xbounds, gridptr->ybounds,
-                   gridptr->rowlon, gridptr->area,
-                   gridptr->reference, gridptr->name };
-  for (size_t i = 0; i < sizeof (p2free) / sizeof (p2free[0]); ++i)
-    if (p2free[i]) Free(p2free[i]);
+                     gridptr->x.vals, gridptr->y.vals,
+                     gridptr->x.bounds, gridptr->y.bounds,
+                     gridptr->rowlon, gridptr->area,
+                     gridptr->reference, gridptr->name};
+
+  for (size_t i = 0; i < sizeof(p2free)/sizeof(p2free[0]); ++i)
+    if ( p2free[i] ) Free(p2free[i]);
 }
 
 void grid_free(grid_t *gridptr)
@@ -188,11 +200,12 @@ void grid_free(grid_t *gridptr)
   grid_init(gridptr);
 }
 
-static grid_t *
-gridNewEntry(cdiResH resH)
+static
+grid_t *gridNewEntry(cdiResH resH)
 {
   grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
   grid_init(gridptr);
+
   if (resH == CDI_UNDEFID)
     gridptr->self = reshPut(gridptr, &gridOps);
   else
@@ -200,6 +213,7 @@ gridNewEntry(cdiResH resH)
       gridptr->self = resH;
       reshReplace(resH, gridptr, &gridOps);
     }
+
   return gridptr;
 }
 
@@ -256,100 +270,72 @@ void gridGetString(char *name, const char *gridstrname, size_t len)
   name[len - 1] = 0;
 }
 
-static inline void
-gridSetName(char *gridstrname, const char *name)
+static inline
+void gridSetName(char *gridstrname, const char *name)
 {
   strncpy(gridstrname, name, CDI_MAX_NAME);
   gridstrname[CDI_MAX_NAME - 1] = 0;
 }
 
-void
-cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
+
+void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
 {
   gridptr->type = gridtype;
   gridptr->size = size;
 
+  if      ( gridtype == GRID_CURVILINEAR  ) gridptr->nvertex = 4;
+  else if ( gridtype == GRID_UNSTRUCTURED ) gridptr->x.size = size;
+
   switch (gridtype)
     {
-    case GRID_CURVILINEAR:
-      gridptr->nvertex = 4;
-      /* Fall through */
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
     case GRID_GAUSSIAN_REDUCED:
     case GRID_TRAJECTORY:
+    case GRID_CURVILINEAR:
+    case GRID_UNSTRUCTURED:
+    case GRID_GME:
       {
         if ( gridtype == GRID_TRAJECTORY )
           {
-            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "tlon");
-            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "tlat");
+            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "tlon");
+            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "tlat");
           }
         else
           {
-            if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
-            if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
+            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "lon");
+            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "lat");
           }
-        gridSetName(gridptr->xlongname, "longitude");
-        gridSetName(gridptr->ylongname, "latitude");
 
-        /*
-        if ( gridtype == GRID_CURVILINEAR )
-          {
-            gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
-            gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
-            gridDefXunits(gridID, "degrees");
-            gridDefYunits(gridID, "degrees");
-          }
-        else
-        */
-          {
-            gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
-            gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-            gridSetName(gridptr->xunits, "degrees_east");
-            gridSetName(gridptr->yunits, "degrees_north");
-          }
+        gridSetName(gridptr->x.longname, "longitude");
+        gridSetName(gridptr->y.longname, "latitude");
 
-        break;
-      }
-    case GRID_UNSTRUCTURED:
-      gridptr->xsize = size;
-      /* Fall through */
-    case GRID_GME:
-      {
-        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon");
-        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat");
-        gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
-        gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
-        gridSetName(gridptr->xunits, "degrees_east");
-        gridSetName(gridptr->yunits, "degrees_north");
-        break;
-      }
-    case GRID_GENERIC:
-      {
+        gridptr->x.stdname = xystdname_tab[grid_xystdname_latlon][0];
+        gridptr->y.stdname = xystdname_tab[grid_xystdname_latlon][1];
+        gridSetName(gridptr->x.units, "degrees_east");
+        gridSetName(gridptr->y.units, "degrees_north");
 
-        /* gridptr->xsize = size; */
-        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
-        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
-        /*
-        strcpy(gridptr->xstdname, "grid_longitude");
-        strcpy(gridptr->ystdname, "grid_latitude");
-        gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
-        gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
-        gridDefXunits(gridID, "degrees");
-        gridDefYunits(gridID, "degrees");
-        */
         break;
       }
+    case GRID_GENERIC:
+    case GRID_PROJECTION:
     case GRID_LCC2:
     case GRID_SINUSOIDAL:
     case GRID_LAEA:
       {
-        if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x");
-        if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y");
-        gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
-        gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
-        gridSetName(gridptr->xunits, "m");
-        gridSetName(gridptr->yunits, "m");
+        if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "x");
+        if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "y");
+        if ( gridtype == GRID_PROJECTION )
+          {
+            gridSetName(gridptr->mapname, "Projection");
+          }
+        if ( gridtype != GRID_GENERIC )
+          {
+            gridptr->x.stdname = xystdname_tab[grid_xystdname_projection][0];
+            gridptr->y.stdname = xystdname_tab[grid_xystdname_projection][1];
+            gridSetName(gridptr->x.units, "m");
+            gridSetName(gridptr->y.units, "m");
+          }
         break;
       }
     }
@@ -551,11 +537,9 @@ int gridCreate(int gridtype, int size)
 static
 void gridDestroyKernel( grid_t * gridptr )
 {
-  int id;
-
   xassert ( gridptr );
 
-  id = gridptr->self;
+  int id = gridptr->self;
 
   grid_free_components(gridptr);
   Free( gridptr );
@@ -579,6 +563,7 @@ void gridDestroy(int gridID)
   gridptr->vtable->destroy(gridptr);
 }
 
+
 void gridDestroyP ( void * gridptr )
 {
   ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
@@ -601,25 +586,33 @@ void gridName(int gridtype, char *gridname)
 }
 
 static
-char *grid_key_to_string(grid_t *gridptr, int key)
+void *grid_key_to_ptr(grid_t *gridptr, int key)
 {
-  char *gridstring = NULL;
+  void *keyptr = NULL;
 
   switch (key)
     {
-    case CDI_GRID_XDIMNAME: gridstring = gridptr->xdimname; break;
-    case CDI_GRID_YDIMNAME: gridstring = gridptr->ydimname; break;
-    case CDI_GRID_VDIMNAME: gridstring = gridptr->vdimname; break;
+    case CDI_KEY_XNAME:      keyptr = (void*)gridptr->x.name; break;
+    case CDI_KEY_XLONGNAME:  keyptr = (void*)gridptr->x.longname; break;
+    case CDI_KEY_XUNITS:     keyptr = (void*)gridptr->x.units; break;
+    case CDI_KEY_YNAME:      keyptr = (void*)gridptr->y.name; break;
+    case CDI_KEY_YLONGNAME:  keyptr = (void*)gridptr->y.longname; break;
+    case CDI_KEY_YUNITS:     keyptr = (void*)gridptr->y.units; break;
+    case CDI_KEY_XDIMNAME:   keyptr = (void*)gridptr->x.dimname; break;
+    case CDI_KEY_YDIMNAME:   keyptr = (void*)gridptr->y.dimname; break;
+    case CDI_KEY_VDIMNAME:   keyptr = (void*)gridptr->vdimname; break;
+    case CDI_KEY_MAPNAME:    keyptr = (void*)gridptr->mapname; break;
+    case CDI_KEY_MAPPING:    keyptr = (void*)gridptr->mapping; break;
     }
 
-  return gridstring;
+  return keyptr;
 }
 
 /*
-@Function  cdiGridDefString
+@Function  cdiGridDefKeyStr
 @Title     Define a CDI grid string value from a key
 
-@Prototype int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+@Prototype int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
 @Parameter
     @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
     @Item  key      The key to be searched
@@ -627,20 +620,20 @@ char *grid_key_to_string(grid_t *gridptr, int key)
     @Item  mesg     The address of a string where the data will be read
 
 @Description
-The function @func{cdiGridDefString} defines a CDI grid string value from a key.
+The function @func{cdiGridDefKeyStr} defines a CDI grid string value from a key.
 
 @Result
-@func{cdiGridDefString} returns 0 if OK and integer value on error.
+@func{cdiGridDefKeyStr} returns 0 if OK and integer value on error.
 
 @EndFunction
 */
-int cdiGridDefString(int gridID, int key, int size, const char *mesg)
+int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
 {
   if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1;
 
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  char *gridstring = grid_key_to_string(gridptr, key);
+  char *gridstring = (char*)grid_key_to_ptr(gridptr, key);
   if ( gridstring == NULL )
     {
       Warning("CDI grid string key %d not supported!", key);
@@ -654,10 +647,10 @@ int cdiGridDefString(int gridID, int key, int size, const char *mesg)
 }
 
 /*
-@Function  cdiGridInqString
+@Function  cdiGridInqKeyStr
 @Title     Get a CDI grid string value from a key
 
-@Prototype int cdiGridInqString(int gridID, int key, int size, char *mesg)
+@Prototype int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
 @Parameter
     @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
     @Item  key      The key to be searched.
@@ -668,19 +661,19 @@ int cdiGridDefString(int gridID, int key, int size, const char *mesg)
                     is given by the predefined constant @func{CDI_MAX_NAME}.
 
 @Description
-The function @func{cdiGridInqString} return a CDI grid string value from a key.
+The function @func{cdiGridInqKeyStr} return a CDI grid string value from a key.
 
 @Result
-@func{cdiGridInqString} returns 0 if OK and integer value on error.
+@func{cdiGridInqKeyStr} returns 0 if OK and integer value on error.
 
 @EndFunction
 */
-int cdiGridInqString(int gridID, int key, int size, char *mesg)
+int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
 {
   if ( size < 1 || mesg == NULL ) return -1;
 
   grid_t *gridptr = gridID2Ptr(gridID);
-  const char *gridstring = grid_key_to_string(gridptr, key);
+  const char *gridstring = (const char*)grid_key_to_ptr(gridptr, key);
   if ( gridstring == NULL)
     {
       Warning("CDI grid string key %d not supported!", key);
@@ -708,12 +701,7 @@ The function @func{gridDefXname} defines the name of a X-axis.
 */
 void gridDefXname(int gridID, const char *xname)
 {
-  if ( xname && *xname )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->xname, xname);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
 }
 
 /*
@@ -732,12 +720,7 @@ The function @func{gridDefXlongname} defines the longname of a X-axis.
 */
 void gridDefXlongname(int gridID, const char *xlongname)
 {
-  if ( xlongname )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->xlongname, xlongname);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
 }
 
 /*
@@ -756,12 +739,7 @@ The function @func{gridDefXunits} defines the units of a X-axis.
 */
 void gridDefXunits(int gridID, const char *xunits)
 {
-  if ( xunits )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->xunits, xunits);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
 }
 
 /*
@@ -780,12 +758,7 @@ The function @func{gridDefYname} defines the name of a Y-axis.
 */
 void gridDefYname(int gridID, const char *yname)
 {
-  if ( yname && *yname )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->yname, yname);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
 }
 
 /*
@@ -804,12 +777,7 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis.
 */
 void gridDefYlongname(int gridID, const char *ylongname)
 {
-  if ( ylongname )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->ylongname, ylongname);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
 }
 
 /*
@@ -828,12 +796,7 @@ The function @func{gridDefYunits} defines the units of a Y-axis.
 */
 void gridDefYunits(int gridID, const char *yunits)
 {
-  if ( yunits )
-    {
-      grid_t *gridptr = gridID2Ptr(gridID);
-      gridSetName(gridptr->yunits, yunits);
-      gridMark4Update(gridID);
-    }
+  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
 }
 
 /*
@@ -857,15 +820,7 @@ The function @func{gridInqXname} returns the name of a X-axis.
 */
 void gridInqXname(int gridID, char *xname)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(xname, gridptr->xname);
-}
-
-const char *gridInqXnamePtr(int gridID)
-{
-  grid_t *gridptr = gridID2Ptr(gridID);
-  return gridptr->xname;
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
 }
 
 /*
@@ -889,9 +844,7 @@ The function @func{gridInqXlongname} returns the longname of a X-axis.
 */
 void gridInqXlongname(int gridID, char *xlongname)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(xlongname, gridptr->xlongname);
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
 }
 
 /*
@@ -915,17 +868,15 @@ The function @func{gridInqXunits} returns the units of a X-axis.
 */
 void gridInqXunits(int gridID, char *xunits)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(xunits, gridptr->xunits);
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
 }
 
 
 void gridInqXstdname(int gridID, char *xstdname)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
-  if ( gridptr->xstdname )
-    strcpy(xstdname, gridptr->xstdname);
+  if ( gridptr->x.stdname )
+    strcpy(xstdname, gridptr->x.stdname);
   else
     xstdname[0] = 0;
 }
@@ -951,15 +902,7 @@ The function @func{gridInqYname} returns the name of a Y-axis.
 */
 void gridInqYname(int gridID, char *yname)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(yname, gridptr->yname);
-}
-
-const char *gridInqYnamePtr(int gridID)
-{
-  grid_t *gridptr = gridID2Ptr(gridID);
-  return gridptr->yname;
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
 }
 
 /*
@@ -983,9 +926,7 @@ The function @func{gridInqYlongname} returns the longname of a Y-axis.
 */
 void gridInqYlongname(int gridID, char *ylongname)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(ylongname, gridptr->ylongname);
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
 }
 
 /*
@@ -1009,20 +950,81 @@ The function @func{gridInqYunits} returns the units of a Y-axis.
 */
 void gridInqYunits(int gridID, char *yunits)
 {
-  grid_t *gridptr = gridID2Ptr(gridID);
-
-  strcpy(yunits, gridptr->yunits);
+  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
 }
 
+
 void gridInqYstdname(int gridID, char *ystdname)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
-  if ( gridptr->ystdname )
-    strcpy(ystdname, gridptr->ystdname);
+  if ( gridptr->y.stdname )
+    strcpy(ystdname, gridptr->y.stdname);
   else
     ystdname[0] = 0;
 }
 
+
+void gridDefProj(int gridID, int projID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  gridptr->proj = projID;
+
+  if ( gridptr->type == GRID_CURVILINEAR )
+    {
+      grid_t *projptr = gridID2Ptr(projID);
+      if ( projptr->x.name[0] ) strcpy(gridptr->x.dimname, projptr->x.name);
+      if ( projptr->y.name[0] ) strcpy(gridptr->y.dimname, projptr->y.name);
+    }
+}
+
+
+int gridInqProj(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+  return gridptr->proj;
+}
+
+
+int gridInqProjType(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+
+  int projtype = gridptr->projtype;
+
+  if ( projtype == -1 )
+    {
+      char mapping[CDI_MAX_NAME]; mapping[0] = 0;
+      cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+      if ( mapping[0] )
+        {
+          if      ( strcmp(mapping, "rotated_latitude_longitude") == 0 )   projtype = CDI_PROJ_RLL;
+          else if ( strcmp(mapping, "lambert_azimuthal_equal_area") == 0 ) projtype = CDI_PROJ_LAEA;
+          else if ( strcmp(mapping, "lambert_conformal_conic") == 0 )      projtype = CDI_PROJ_LCC;
+          else if ( strcmp(mapping, "sinusoidal") == 0 )                   projtype = CDI_PROJ_SINU;
+
+          gridptr->projtype = projtype;
+        }
+    }
+
+  return projtype;
+}
+
+
+void gridVerifyProj(int gridID)
+{
+  grid_t *gridptr = gridID2Ptr(gridID);
+
+  int projtype = gridInqProjType(gridID);
+
+  if ( projtype == CDI_PROJ_RLL )
+    {
+      gridptr->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+      gridptr->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+      gridSetName(gridptr->x.units, "degrees");
+      gridSetName(gridptr->y.units, "degrees");
+    }
+}
+
 /*
 @Function  gridInqType
 @Title     Get the type of a Grid
@@ -1075,8 +1077,8 @@ int gridInqSize(int gridID)
 
   if ( size == 0 )
     {
-      int xsize = gridptr->xsize;
-      int ysize = gridptr->ysize;
+      int xsize = gridptr->x.size;
+      int ysize = gridptr->y.size;
 
       if ( ysize )
         size = xsize * ysize;
@@ -1113,7 +1115,7 @@ int gridInqTrunc(int gridID)
         gridptr->trunc = nsp2trunc(gridptr->size);
       /*
       else if      ( gridptr->type == GRID_GAUSSIAN )
-        gridptr->trunc = nlat2trunc(gridptr->ysize);
+        gridptr->trunc = nlat2trunc(gridptr->y.size);
       */
     }
 
@@ -1158,18 +1160,18 @@ void gridDefXsize(int gridID, int xsize)
   if ( gridType == GRID_UNSTRUCTURED && xsize != gridSize )
     Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridSize);
 
-  if ( gridptr->xsize != xsize )
+  if ( gridptr->x.size != xsize )
     {
       gridMark4Update(gridID);
-      gridptr->xsize = xsize;
+      gridptr->x.size = xsize;
     }
 
-  if ( gridType != GRID_UNSTRUCTURED )
+  if ( gridType != GRID_UNSTRUCTURED && gridType != GRID_PROJECTION )
     {
-      long axisproduct = gridptr->xsize*gridptr->ysize;
+      long axisproduct = gridptr->x.size*gridptr->y.size;
       if ( axisproduct > 0 && axisproduct != gridSize )
         Error("Inconsistent grid declaration! (xsize=%d ysize=%d gridsize=%d)",
-              gridptr->xsize, gridptr->ysize, gridSize);
+              gridptr->x.size, gridptr->y.size, gridSize);
     }
 }
 
@@ -1231,7 +1233,7 @@ int gridInqXsize(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->xsize;
+  return gridptr->x.size;
 }
 
 /*
@@ -1257,21 +1259,22 @@ void gridDefYsize(int gridID, int ysize)
   if ( ysize > gridSize )
     Error("ysize %d is greater then gridsize %d", ysize, gridSize);
 
-  if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ysize != gridSize )
+  int gridType = gridInqType(gridID);
+  if ( gridType == GRID_UNSTRUCTURED && ysize != gridSize )
     Error("ysize %d must be equal gridsize %d for gridtype: UNSTRUCTURED", ysize, gridSize);
 
-  if ( gridptr->ysize != ysize )
+  if ( gridptr->y.size != ysize )
     {
       gridMark4Update(gridID);
-      gridptr->ysize = ysize;
+      gridptr->y.size = ysize;
     }
 
-  if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
+  if ( gridType != GRID_UNSTRUCTURED && gridType != GRID_PROJECTION )
     {
-      long axisproduct = gridptr->xsize*gridptr->ysize;
+      long axisproduct = gridptr->x.size*gridptr->y.size;
       if ( axisproduct > 0 && axisproduct != gridSize )
         Error("Inconsistent grid declaration! (xsize=%d ysize=%d gridsize=%d)",
-              gridptr->xsize, gridptr->ysize, gridSize);
+              gridptr->x.size, gridptr->y.size, gridSize);
     }
 }
 
@@ -1295,7 +1298,7 @@ int gridInqYsize(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->ysize;
+  return gridptr->y.size;
 }
 
 /*
@@ -1503,12 +1506,12 @@ gridInqXValsSerial(grid_t *gridptr, double *xvals)
   else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
     size = 2;
   else
-    size = gridptr->xsize;
+    size = gridptr->x.size;
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d", gridptr->self);
 
-  if ( gridptr->xvals )
+  if ( gridptr->x.vals )
     {
       if ( size && xvals )
         {
@@ -1560,16 +1563,16 @@ gridDefXValsSerial(grid_t *gridptr, const double *xvals)
   else if ( gridtype == GRID_GAUSSIAN_REDUCED )
     size = 2;
   else
-    size = gridptr->xsize;
+    size = gridptr->x.size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d", gridptr->self);
 
-  if (gridptr->xvals && CDI_Debug)
+  if (gridptr->x.vals && CDI_Debug)
     Warning("values already defined!");
-  gridptr->xvals = (double *)Realloc(gridptr->xvals,
+  gridptr->x.vals = (double *)Realloc(gridptr->x.vals,
                                       (size_t)size * sizeof(double));
-  memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
+  memcpy(gridptr->x.vals, xvals, (size_t)size * sizeof (double));
 }
 
 /*
@@ -1599,12 +1602,12 @@ gridInqYValsSerial(grid_t *gridptr, double *yvals)
   int gridtype = gridptr->type;
   long size
     = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
-    ? gridptr->size : gridptr->ysize;
+    ? gridptr->size : gridptr->y.size;
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d!", gridptr->self);
 
-  if ( gridptr->yvals )
+  if ( gridptr->y.vals )
     {
       if ( size && yvals )
         {
@@ -1650,16 +1653,16 @@ gridDefYValsSerial(grid_t *gridptr, const double *yvals)
   int gridtype = gridptr->type;
   long size
     = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
-    ? gridptr->size : gridptr->ysize;
+    ? gridptr->size : gridptr->y.size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d!", gridptr->self);
 
-  if (gridptr->yvals && CDI_Debug)
+  if (gridptr->y.vals && CDI_Debug)
     Warning("Values already defined!");
 
-  gridptr->yvals = (double *)Realloc(gridptr->yvals, (size_t)size * sizeof (double));
-  memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
+  gridptr->y.vals = (double *)Realloc(gridptr->y.vals, (size_t)size * sizeof (double));
+  memcpy(gridptr->y.vals, yvals, (size_t)size * sizeof (double));
 }
 
 
@@ -1687,7 +1690,7 @@ void gridDefYvals(int gridID, const double *yvals)
 static double
 gridInqXValSerial(grid_t *gridptr, int index)
 {
-  double xval = gridptr->xvals ? gridptr->xvals[index] : 0;
+  double xval = gridptr->x.vals ? gridptr->x.vals[index] : 0;
   return xval;
 }
 
@@ -1701,7 +1704,7 @@ double gridInqXval(int gridID, int index)
 static double
 gridInqYValSerial(grid_t *gridptr, int index)
 {
-  double yval = gridptr->yvals ? gridptr->yvals[index] : 0;
+  double yval = gridptr->y.vals ? gridptr->y.vals[index] : 0;
   return yval;
 }
 
@@ -1734,23 +1737,23 @@ double gridInqYval(int gridID, int index)
 double gridInqXinc(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
-  double xinc = gridptr->xinc;
+  double xinc = gridptr->x.inc;
   const double *restrict xvals = gridptr->vtable->inqXValsPtr(gridptr);
 
   if ( (! (fabs(xinc) > 0)) && xvals )
     {
-      int xsize = gridptr->xsize;
+      int xsize = gridptr->x.size;
       if ( xsize > 1 )
         {
           xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
-          for (size_t i = 2; i < (size_t)xsize; i++ )
+          for ( int i = 2; i < xsize; i++ )
             if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc )
               {
                 xinc = 0;
                 break;
               }
 
-          gridptr->xinc = xinc;
+          gridptr->x.inc = xinc;
         }
     }
 
@@ -1770,12 +1773,12 @@ double gridInqXinc(int gridID)
 double gridInqYinc(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
-  double yinc = gridptr->yinc;
+  double yinc = gridptr->y.inc;
   const double *yvals = gridptr->vtable->inqYValsPtr(gridptr);
 
   if ( (! (fabs(yinc) > 0)) && yvals )
     {
-      int ysize = gridptr->ysize;
+      int ysize = gridptr->y.size;
       if ( ysize > 1 )
         {
           yinc = yvals[1] - yvals[0];
@@ -1787,13 +1790,67 @@ double gridInqYinc(int gridID)
                 break;
               }
 
-          gridptr->yinc = yinc;
+          gridptr->y.inc = yinc;
         }
     }
 
   return yinc;
 }
 
+
+void gridInqProjParamRLL(int gridID, double *xpole, double *ypole, double *angle)
+{
+  *xpole = 0; *ypole = 0; *angle = 0;
+
+  const char *projection = "rotated_latitude_longitude";
+  char mapping[CDI_MAX_NAME]; mapping[0] = 0;
+  cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+  if ( mapping[0] && strcmp(mapping, projection) == 0 )
+    {
+      int atttype, attlen;
+      char attname[CDI_MAX_NAME+1];
+
+      int natts;
+      cdiInqNatts(gridID, CDI_GLOBAL, &natts);
+
+      for ( int iatt = 0; iatt < natts; ++iatt )
+        {
+          cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
+
+          if ( attlen != 1 ) continue;
+
+          if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
+            {
+              double attflt;
+              cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, &attflt);
+              if      ( strcmp(attname, "grid_north_pole_longitude") == 0 ) *xpole = attflt;
+              else if ( strcmp(attname, "grid_north_pole_latitude")  == 0 ) *ypole = attflt;
+              else if ( strcmp(attname, "north_pole_grid_longitude") == 0 ) *angle = attflt;
+            }
+        }
+    }
+  else
+    Warning("%s mapping parameter missing!", projection);
+}
+
+
+void gridDefProjParamRLL(int gridID, double xpole, double ypole, double angle)
+{
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, "rotated_pole");
+
+  const char *mapping = "rotated_latitude_longitude";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", strlen(mapping), mapping);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_longitude", DATATYPE_FLT64, 1, &xpole);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_latitude", DATATYPE_FLT64, 1, &ypole);
+  if ( IS_NOT_EQUAL(angle, 0) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "north_pole_grid_longitude", DATATYPE_FLT64, 1, &angle);
+
+  grid_t *gridptr = gridID2Ptr(gridID);
+  gridptr->projtype = CDI_PROJ_RLL;
+
+  gridVerifyProj(gridID);
+}
+
 /*
 @Function
 @Title
@@ -1809,7 +1866,7 @@ double gridInqXpole(int gridID)
   // Xpole -> grid_north_pole_longitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->xpole;
+  return gridptr->rll.xpole;
 }
 
 /*
@@ -1827,13 +1884,13 @@ void gridDefXpole(int gridID, double xpole)
   // Xpole -> grid_north_pole_longitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->xstdname && memcmp(gridptr->xstdname, "grid", 4) != 0 )
-    gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+  if ( gridptr->x.stdname && memcmp(gridptr->x.stdname, "grid", 4) != 0 )
+    gridptr->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0];
 
-  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) )
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.xpole, xpole) )
     {
       gridptr->isRotated = TRUE;
-      gridptr->xpole = xpole;
+      gridptr->rll.xpole = xpole;
       gridMark4Update(gridID);
     }
 }
@@ -1853,7 +1910,7 @@ double gridInqYpole(int gridID)
   // Ypole -> grid_north_pole_latitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->ypole;
+  return gridptr->rll.ypole;
 }
 
 /*
@@ -1871,13 +1928,13 @@ void gridDefYpole(int gridID, double ypole)
   // Ypole -> grid_north_pole_latitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->ystdname && memcmp(gridptr->ystdname, "grid", 4) != 0 )
-    gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+  if ( gridptr->y.stdname && memcmp(gridptr->y.stdname, "grid", 4) != 0 )
+    gridptr->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1];
 
-  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) )
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.ypole, ypole) )
     {
       gridptr->isRotated = TRUE;
-      gridptr->ypole = ypole;
+      gridptr->rll.ypole = ypole;
       gridMark4Update(gridID);
     }
 }
@@ -1897,7 +1954,7 @@ double gridInqAngle(int gridID)
   // Angle -> north_pole_grid_longitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->angle;
+  return gridptr->rll.angle;
 }
 
 /*
@@ -1915,10 +1972,10 @@ void gridDefAngle(int gridID, double angle)
   // Angle -> north_pole_grid_longitude
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->angle, angle) )
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.angle, angle) )
     {
       gridptr->isRotated = TRUE;
-      gridptr->angle = angle;
+      gridptr->rll.angle = angle;
       gridMark4Update(gridID);
     }
 }
@@ -1937,7 +1994,7 @@ int gridInqGMEnd(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->nd;
+  return gridptr->gme.nd;
 }
 
 /*
@@ -1954,9 +2011,9 @@ void gridDefGMEnd(int gridID, int nd)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if (gridptr->nd != nd)
+  if (gridptr->gme.nd != nd)
     {
-      gridptr->nd = nd;
+      gridptr->gme.nd = nd;
       gridMark4Update(gridID);
     }
 }
@@ -1975,7 +2032,7 @@ int gridInqGMEni(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->ni;
+  return gridptr->gme.ni;
 }
 
 /*
@@ -1992,9 +2049,9 @@ void gridDefGMEni(int gridID, int ni)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->ni != ni )
+  if ( gridptr->gme.ni != ni )
     {
-      gridptr->ni = ni;
+      gridptr->gme.ni = ni;
       gridMark4Update(gridID);
     }
 }
@@ -2013,7 +2070,7 @@ int gridInqGMEni2(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->ni2;
+  return gridptr->gme.ni2;
 }
 
 /*
@@ -2030,9 +2087,9 @@ void gridDefGMEni2(int gridID, int ni2)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->ni2 != ni2 )
+  if ( gridptr->gme.ni2 != ni2 )
     {
-      gridptr->ni2 = ni2;
+      gridptr->gme.ni2 = ni2;
       gridMark4Update(gridID);
     }
 }
@@ -2051,16 +2108,16 @@ int gridInqGMEni3(int gridID)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  return gridptr->ni3;
+  return gridptr->gme.ni3;
 }
 
 void gridDefGMEni3(int gridID, int ni3)
 {
   grid_t *gridptr = gridID2Ptr(gridID);
 
-  if ( gridptr->ni3 != ni3 )
+  if ( gridptr->gme.ni3 != ni3 )
     {
-      gridptr->ni3 = ni3;
+      gridptr->gme.ni3 = ni3;
       gridMark4Update(gridID);
     }
 }
@@ -2094,8 +2151,8 @@ void grid_check_cyclic(grid_t *gridptr)
 {
   gridptr->isCyclic = FALSE;
   enum { numVertices = 4 };
-  size_t xsize = gridptr->xsize >= 0 ? (size_t)gridptr->xsize : 0,
-    ysize = gridptr->ysize >= 0 ? (size_t)gridptr->ysize : 0;
+  size_t xsize = gridptr->x.size >= 0 ? (size_t)gridptr->x.size : 0,
+    ysize = gridptr->y.size >= 0 ? (size_t)gridptr->y.size : 0;
   const double *xvals = gridptr->vtable->inqXValsPtr(gridptr),
     (*xbounds)[numVertices]
     = (const double (*)[numVertices])gridptr->vtable->inqXBoundsPtr(gridptr);
@@ -2201,7 +2258,7 @@ bool compareXYvals(grid_t *gridRef, grid_t *gridTest)
 {
   bool differ = false;
 
-  int xsizeTest = gridTest->xsize, ysizeTest = gridTest->ysize;
+  int xsizeTest = gridTest->x.size, ysizeTest = gridTest->y.size;
   if ( !differ && xsizeTest > 0 && xsizeTest == gridRef->vtable->inqXVals(gridRef, NULL) )
     {
       const double *restrict xvalsRef = gridRef->vtable->inqXValsPtr(gridRef),
@@ -2235,8 +2292,8 @@ bool compareXYvals2(grid_t *gridRef, grid_t *gridTest)
 {
   int gridsize = gridTest->size;
   bool differ
-    = ((gridTest->xvals == NULL) ^ (gridRef->xvals == NULL))
-    || ((gridTest->yvals == NULL) ^ (gridRef->yvals == NULL));
+    = ((gridTest->x.vals == NULL) ^ (gridRef->x.vals == NULL))
+    || ((gridTest->y.vals == NULL) ^ (gridRef->y.vals == NULL));
 
   typedef double (*inqVal)(grid_t *grid, int index);
   inqVal inqXValRef = gridRef->vtable->inqXVal,
@@ -2244,11 +2301,11 @@ bool compareXYvals2(grid_t *gridRef, grid_t *gridTest)
     inqXValTest = gridTest->vtable->inqXVal,
     inqYValTest = gridTest->vtable->inqYVal;
 
-  if ( !differ && gridTest->xvals )
+  if ( !differ && gridTest->x.vals )
     differ = fabs(inqXValTest(gridTest, 0) - inqXValRef(gridRef, 0)) > 1.e-9
       || fabs(inqXValTest(gridTest, gridsize-1) - inqXValRef(gridRef, gridsize-1)) > 1.e-9;
 
-  if ( !differ && gridTest->yvals )
+  if ( !differ && gridTest->y.vals )
     differ = fabs(inqYValTest(gridTest, 0) - inqYValRef(gridRef, 0)) > 1.e-9
       || fabs(inqYValTest(gridTest, gridsize-1) - inqYValRef(gridRef, gridsize-1)) > 1.e-9;
 
@@ -2266,49 +2323,49 @@ bool gridCompare(int gridID, const grid_t *grid)
       if ( grid->size == gridRef->size )
 	{
 	  differ = false;
-	  if ( grid->type == GRID_LONLAT )
+	  if ( grid->type == GRID_LONLAT || grid->type == GRID_PROJECTION )
 	    {
 	      /*
 	      printf("gridID      %d\n", gridID);
-	      printf("grid.xdef   %d\n", grid->xdef);
-	      printf("grid.ydef   %d\n", grid->ydef);
-	      printf("grid.xsize  %d\n", grid->xsize);
-	      printf("grid.ysize  %d\n", grid->ysize);
-	      printf("grid.xfirst %f\n", grid->xfirst);
-	      printf("grid.yfirst %f\n", grid->yfirst);
+	      printf("grid.xdef   %d\n", grid->x.flag);
+	      printf("grid.ydef   %d\n", grid->y.flag);
+	      printf("grid.xsize  %d\n", grid->x.size);
+	      printf("grid.ysize  %d\n", grid->y.size);
+	      printf("grid.xfirst %f\n", grid->x.first);
+	      printf("grid.yfirst %f\n", grid->y.first);
 	      printf("grid.xfirst %f\n", gridInqXval(gridID, 0));
 	      printf("grid.yfirst %f\n", gridInqYval(gridID, 0));
-	      printf("grid.xinc   %f\n", grid->xinc);
-	      printf("grid.yinc   %f\n", grid->yinc);
+	      printf("grid.xinc   %f\n", grid->x.inc);
+	      printf("grid.yinc   %f\n", grid->y.inc);
 	      printf("grid.xinc   %f\n", gridInqXinc(gridID));
 	      printf("grid.yinc   %f\n", gridInqYinc(gridID));
 	      */
-	      if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+	      if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size )
 		{
-		  if ( grid->xdef == 2 && grid->ydef == 2 )
+		  if ( grid->x.flag == 2 && grid->y.flag == 2 )
 		    {
-		      if ( ! (IS_EQUAL(grid->xfirst, 0) && IS_EQUAL(grid->xlast, 0) && IS_EQUAL(grid->xinc, 0)) &&
-			   ! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0) && IS_EQUAL(grid->yinc, 0)) &&
-			   IS_NOT_EQUAL(grid->xfirst, grid->xlast) && IS_NOT_EQUAL(grid->yfirst, grid->ylast) )
+		      if ( ! (IS_EQUAL(grid->x.first, 0) && IS_EQUAL(grid->x.last, 0) && IS_EQUAL(grid->x.inc, 0)) &&
+			   ! (IS_EQUAL(grid->y.first, 0) && IS_EQUAL(grid->y.last, 0) && IS_EQUAL(grid->y.inc, 0)) &&
+			   IS_NOT_EQUAL(grid->x.first, grid->x.last) && IS_NOT_EQUAL(grid->y.first, grid->y.last) )
 			{
-			  if ( IS_NOT_EQUAL(grid->xfirst, gridInqXval(gridID, 0)) ||
-			       IS_NOT_EQUAL(grid->yfirst, gridInqYval(gridID, 0)))
+			  if ( IS_NOT_EQUAL(grid->x.first, gridInqXval(gridID, 0)) ||
+			       IS_NOT_EQUAL(grid->y.first, gridInqYval(gridID, 0)))
 			    {
 			      differ = true;
 			    }
-			  if ( !differ && fabs(grid->xinc) > 0 &&
-			       fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000))
+			  if ( !differ && fabs(grid->x.inc) > 0 &&
+			       fabs(fabs(grid->x.inc) - fabs(gridRef->x.inc)) > fabs(grid->x.inc/1000))
 			    {
 			      differ = true;
 			    }
-			  if ( !differ && fabs(grid->yinc) > 0 &&
-			       fabs(fabs(grid->yinc) - fabs(gridRef->yinc)) > fabs(grid->yinc/1000))
+			  if ( !differ && fabs(grid->y.inc) > 0 &&
+			       fabs(fabs(grid->y.inc) - fabs(gridRef->y.inc)) > fabs(grid->y.inc/1000))
 			    {
 			      differ = true;
 			    }
 			}
 		    }
-		  else if ( grid->xvals && grid->yvals )
+		  else if ( grid->x.vals && grid->y.vals )
                     differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
 		}
 	      else
@@ -2316,14 +2373,14 @@ bool gridCompare(int gridID, const grid_t *grid)
 	    }
 	  else if ( grid->type == GRID_GENERIC )
 	    {
-	      if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+	      if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size )
 		{
-		  if ( grid->xdef == 1 && grid->ydef == 1
-                       && grid->xvals && grid->yvals )
+		  if ( grid->x.flag == 1 && grid->y.flag == 1
+                       && grid->x.vals && grid->y.vals )
                     differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
 		}
-	      else if ( (grid->ysize == 0 || grid->ysize == 1) &&
-			grid->xsize == gridRef->xsize*gridRef->ysize )
+	      else if ( (grid->y.size == 0 || grid->y.size == 1) &&
+			grid->x.size == gridRef->x.size*gridRef->y.size )
 		{
 		}
 	      else
@@ -2331,20 +2388,20 @@ bool gridCompare(int gridID, const grid_t *grid)
 	    }
 	  else if ( grid->type == GRID_GAUSSIAN )
 	    {
-	      if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+	      if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size )
 		{
-		  if ( grid->xdef == 2 && grid->ydef == 2 )
+		  if ( grid->x.flag == 2 && grid->y.flag == 2 )
 		    {
-		      if ( ! (IS_EQUAL(grid->xfirst, 0) && IS_EQUAL(grid->xlast, 0) && IS_EQUAL(grid->xinc, 0)) &&
-			   ! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0)) )
-			if ( fabs(grid->xfirst - gridInqXval(gridID, 0)) > 0.0015 ||
-			     fabs(grid->yfirst - gridInqYval(gridID, 0)) > 0.0015 ||
-			     (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) )
+		      if ( ! (IS_EQUAL(grid->x.first, 0) && IS_EQUAL(grid->x.last, 0) && IS_EQUAL(grid->x.inc, 0)) &&
+			   ! (IS_EQUAL(grid->y.first, 0) && IS_EQUAL(grid->y.last, 0)) )
+			if ( fabs(grid->x.first - gridInqXval(gridID, 0)) > 0.0015 ||
+			     fabs(grid->y.first - gridInqYval(gridID, 0)) > 0.0015 ||
+			     (fabs(grid->x.inc)>0 && fabs(fabs(grid->x.inc) - fabs(gridRef->x.inc)) > fabs(grid->x.inc/1000)) )
 			  {
 			    differ = true;
 			  }
 		    }
-		  else if ( grid->xvals && grid->yvals )
+		  else if ( grid->x.vals && grid->y.vals )
                     differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
 		}
 	      else
@@ -2354,20 +2411,20 @@ bool gridCompare(int gridID, const grid_t *grid)
 	    {
 	      /*
 	      printf("gridID      %d\n", gridID);
-	      printf("grid.xsize  %d\n", grid->xsize);
-	      printf("grid.ysize  %d\n", grid->ysize);
-	      printf("grid.xfirst %f\n", grid->xvals[0]);
-	      printf("grid.yfirst %f\n", grid->yvals[0]);
+	      printf("grid.xsize  %d\n", grid->x.size);
+	      printf("grid.ysize  %d\n", grid->y.size);
+	      printf("grid.xfirst %f\n", grid->x.vals[0]);
+	      printf("grid.yfirst %f\n", grid->y.vals[0]);
 	      printf("grid xfirst %f\n", gridInqXval(gridID, 0));
 	      printf("grid yfirst %f\n", gridInqYval(gridID, 0));
-	      printf("grid.xlast  %f\n", grid->xvals[grid->size-1]);
-	      printf("grid.ylast  %f\n", grid->yvals[grid->size-1]);
+	      printf("grid.xlast  %f\n", grid->x.vals[grid->size-1]);
+	      printf("grid.ylast  %f\n", grid->y.vals[grid->size-1]);
 	      printf("grid xlast  %f\n", gridInqXval(gridID, grid->size-1));
 	      printf("grid ylast  %f\n", gridInqYval(gridID, grid->size-1));
 	      printf("grid.nv     %d\n", grid->nvertex);
 	      printf("grid nv     %d\n", gridInqNvertex(gridID));
 	      */
-	      if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+	      if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size )
                 differ = gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid);
 	    }
 	  else if ( grid->type == GRID_UNSTRUCTURED )
@@ -2377,8 +2434,8 @@ bool gridCompare(int gridID, const grid_t *grid)
               differ = differ || ( gridRef->uuid[0] && grid->uuid[0] && memcmp(gridRef->uuid, grid->uuid, CDI_UUID_SIZE) != 0 );
 
               if ( !differ &&
-                   ((grid->xvals == NULL) ^ (gridRef->xvals == NULL)) &&
-                   ((grid->yvals == NULL) ^ (gridRef->yvals == NULL)) )
+                   ((grid->x.vals == NULL) ^ (gridRef->x.vals == NULL)) &&
+                   ((grid->y.vals == NULL) ^ (gridRef->y.vals == NULL)) )
                 {
                   int nvertexA, nvertexB, numberA, numberB;
                   differ = ( (nvertexA = grid->nvertex)
@@ -2419,53 +2476,53 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
 
   if ( g1->type          != g2->type         ) return differ;
   if ( g1->prec          != g2->prec         ) return differ;
-  if ( g1->lcc_projflag  != g2->lcc_projflag ) return differ;
-  if ( g1->lcc_scanflag  != g2->lcc_scanflag ) return differ;
-  if ( g1->lcc_defined   != g2->lcc_defined  ) return differ;
-  if ( g1->lcc2_defined  != g2->lcc2_defined ) return differ;
-  if ( g1->laea_defined  != g2->laea_defined ) return differ;
+  if ( g1->lcc.projflag  != g2->lcc.projflag ) return differ;
+  if ( g1->lcc.scanflag  != g2->lcc.scanflag ) return differ;
+  if ( g1->lcc.defined   != g2->lcc.defined  ) return differ;
+  if ( g1->lcc2.defined  != g2->lcc2.defined ) return differ;
+  if ( g1->laea.defined  != g2->laea.defined ) return differ;
   if ( g1->isCyclic      != g2->isCyclic     ) return differ;
   if ( g1->isRotated     != g2->isRotated    ) return differ;
-  if ( g1->xdef          != g2->xdef         ) return differ;
-  if ( g1->ydef          != g2->ydef         ) return differ;
-  if ( g1->nd            != g2->nd           ) return differ;
-  if ( g1->ni            != g2->ni           ) return differ;
-  if ( g1->ni2           != g2->ni2          ) return differ;
-  if ( g1->ni3           != g2->ni3          ) return differ;
+  if ( g1->x.flag        != g2->x.flag       ) return differ;
+  if ( g1->y.flag        != g2->y.flag       ) return differ;
+  if ( g1->gme.nd        != g2->gme.nd       ) return differ;
+  if ( g1->gme.ni        != g2->gme.ni       ) return differ;
+  if ( g1->gme.ni2       != g2->gme.ni2      ) return differ;
+  if ( g1->gme.ni3       != g2->gme.ni3      ) return differ;
   if ( g1->number        != g2->number       ) return differ;
   if ( g1->position      != g2->position     ) return differ;
   if ( g1->trunc         != g2->trunc        ) return differ;
   if ( g1->nvertex       != g2->nvertex      ) return differ;
   if ( g1->nrowlon       != g2->nrowlon      ) return differ;
   if ( g1->size          != g2->size         ) return differ;
-  if ( g1->xsize         != g2->xsize        ) return differ;
-  if ( g1->ysize         != g2->ysize        ) return differ;
+  if ( g1->x.size        != g2->x.size       ) return differ;
+  if ( g1->y.size        != g2->y.size       ) return differ;
   if ( g1->lcomplex      != g2->lcomplex     ) return differ;
 
-  if ( IS_NOT_EQUAL(g1->xfirst        , g2->xfirst)        ) return differ;
-  if ( IS_NOT_EQUAL(g1->yfirst	      , g2->yfirst)        ) return differ;
-  if ( IS_NOT_EQUAL(g1->xlast         , g2->xlast)         ) return differ;
-  if ( IS_NOT_EQUAL(g1->ylast         , g2->ylast)         ) return differ;
-  if ( IS_NOT_EQUAL(g1->xinc	      , g2->xinc)          ) return differ;
-  if ( IS_NOT_EQUAL(g1->yinc	      , g2->yinc)          ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_originLon , g2->lcc_originLon) ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_originLat , g2->lcc_originLat) ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_lonParY   , g2->lcc_lonParY)   ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_lat1      , g2->lcc_lat1)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_lat2      , g2->lcc_lat2)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_xinc      , g2->lcc_xinc)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc_yinc      , g2->lcc_yinc)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc2_lon_0    , g2->lcc2_lon_0)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc2_lat_0    , g2->lcc2_lat_0)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc2_lat_1    , g2->lcc2_lat_1)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc2_lat_2    , g2->lcc2_lat_2)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc2_a        , g2->lcc2_a)        ) return differ;
-  if ( IS_NOT_EQUAL(g1->laea_lon_0    , g2->laea_lon_0)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->laea_lat_0    , g2->laea_lat_0)    ) return differ;
-  if ( IS_NOT_EQUAL(g1->laea_a        , g2->laea_a)        ) return differ;
-  if ( IS_NOT_EQUAL(g1->xpole         , g2->xpole)         ) return differ;
-  if ( IS_NOT_EQUAL(g1->ypole         , g2->ypole)         ) return differ;
-  if ( IS_NOT_EQUAL(g1->angle         , g2->angle)         ) return differ;
+  if ( IS_NOT_EQUAL(g1->x.first       , g2->x.first)       ) return differ;
+  if ( IS_NOT_EQUAL(g1->y.first	      , g2->y.first)       ) return differ;
+  if ( IS_NOT_EQUAL(g1->x.last        , g2->x.last)        ) return differ;
+  if ( IS_NOT_EQUAL(g1->y.last        , g2->y.last)        ) return differ;
+  if ( IS_NOT_EQUAL(g1->x.inc	      , g2->x.inc)         ) return differ;
+  if ( IS_NOT_EQUAL(g1->y.inc	      , g2->y.inc)         ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.originLon , g2->lcc.originLon) ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.originLat , g2->lcc.originLat) ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.lonParY   , g2->lcc.lonParY)   ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.lat1      , g2->lcc.lat1)      ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.lat2      , g2->lcc.lat2)      ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.xinc      , g2->lcc.xinc)      ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc.yinc      , g2->lcc.yinc)      ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc2.lon_0    , g2->lcc2.lon_0)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc2.lat_0    , g2->lcc2.lat_0)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc2.lat_1    , g2->lcc2.lat_1)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc2.lat_2    , g2->lcc2.lat_2)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->lcc2.a        , g2->lcc2.a)        ) return differ;
+  if ( IS_NOT_EQUAL(g1->laea.lon_0    , g2->laea.lon_0)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->laea.lat_0    , g2->laea.lat_0)    ) return differ;
+  if ( IS_NOT_EQUAL(g1->laea.a        , g2->laea.a)        ) return differ;
+  if ( IS_NOT_EQUAL(g1->rll.xpole     , g2->rll.xpole)     ) return differ;
+  if ( IS_NOT_EQUAL(g1->rll.ypole     , g2->rll.ypole)     ) return differ;
+  if ( IS_NOT_EQUAL(g1->rll.angle     , g2->rll.angle)     ) return differ;
 
   const double *restrict g1_xvals = g1->vtable->inqXValsPtr(g1),
     *restrict g2_xvals = g2->vtable->inqXValsPtr(g2);
@@ -2474,7 +2531,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
       if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
         size = g1->size;
       else
-        size = g1->xsize;
+        size = g1->x.size;
       xassert ( size );
 
       if ( !g2_xvals ) return differ;
@@ -2492,7 +2549,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
       if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
 	size = g1->size;
       else
-	size = g1->ysize;
+	size = g1->y.size;
       xassert ( size );
 
       if ( !g2_yvals ) return differ;
@@ -2525,7 +2582,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
         if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
           size = g1->nvertex * g1->size;
         else
-          size = g1->nvertex * g1->xsize;
+          size = g1->nvertex * g1->x.size;
         xassert ( size );
 
         if ( !(g2_xbounds = g2->vtable->inqXBoundsPtr(g2)) ) return differ;
@@ -2545,26 +2602,28 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
         if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
           size = g1->nvertex * g1->size;
         else
-          size = g1->nvertex * g1->ysize;
+          size = g1->nvertex * g1->y.size;
         xassert ( size );
 
         if ( ! (g2_ybounds = g2->vtable->inqYBoundsPtr(g2)) ) return differ;
 
         for ( i = 0; i < size; i++ )
-          if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ;
+          if ( IS_NOT_EQUAL(g1->y.bounds[i], g2->y.bounds[i]) ) return differ;
       }
     else if ( g2->vtable->inqYBoundsPtr(g2) )
       return differ;
   }
 
-  if (strcmp(g1->xname, g2->xname)) return differ;
-  if (strcmp(g1->yname, g2->yname)) return differ;
-  if (strcmp(g1->xlongname, g2->xlongname)) return differ;
-  if (strcmp(g1->ylongname, g2->ylongname)) return differ;
-  if (g1->xstdname != g2->xstdname) return differ;
-  if (g1->ystdname != g2->ystdname) return differ;
-  if (strcmp(g1->xunits, g2->xunits)) return differ;
-  if (strcmp(g1->yunits, g2->yunits)) return differ;
+  if (strcmp(g1->x.name, g2->x.name)) return differ;
+  if (strcmp(g1->y.name, g2->y.name)) return differ;
+  if (strcmp(g1->x.longname, g2->x.longname)) return differ;
+  if (strcmp(g1->y.longname, g2->y.longname)) return differ;
+  if (g1->x.stdname != g2->x.stdname) return differ;
+  if (g1->y.stdname != g2->y.stdname) return differ;
+  if (strcmp(g1->x.units, g2->x.units)) return differ;
+  if (strcmp(g1->y.units, g2->y.units)) return differ;
+
+  if (strcmp(g1->mapping, g2->mapping)) return differ;
 
   if ( g1->reference )
     {
@@ -2598,7 +2657,8 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   return equal;
 }
 
-static void gridComplete(grid_t *grid)
+static
+void gridComplete(grid_t *grid)
 {
   int gridID = grid->self;
   gridDefPrec(gridID, grid->prec);
@@ -2617,78 +2677,74 @@ static void gridComplete(grid_t *grid)
     case GRID_LAEA:
     case GRID_PROJECTION:
       {
-	if ( grid->xsize > 0 ) gridDefXsize(gridID, grid->xsize);
-	if ( grid->ysize > 0 ) gridDefYsize(gridID, grid->ysize);
+	if ( grid->x.size > 0 ) gridDefXsize(gridID, grid->x.size);
+	if ( grid->y.size > 0 ) gridDefYsize(gridID, grid->y.size);
 
         if ( gridtype == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np);
 
 	if ( grid->nvertex > 0 )
 	  gridDefNvertex(gridID, grid->nvertex);
 
-	if ( grid->xdef == 2 )
+	if ( grid->x.flag == 2 )
 	  {
-            assert(gridtype != GRID_UNSTRUCTURED
-                   && gridtype != GRID_CURVILINEAR);
-	    double *xvals
-              = (double *) Malloc((size_t)grid->xsize * sizeof (double));
-	    gridGenXvals(grid->xsize, grid->xfirst, grid->xlast, grid->xinc, xvals);
-	    grid->xvals = xvals;
+            assert(gridtype != GRID_UNSTRUCTURED && gridtype != GRID_CURVILINEAR);
+	    double *xvals = (double *) Malloc((size_t)grid->x.size * sizeof (double));
+	    gridGenXvals(grid->x.size, grid->x.first, grid->x.last, grid->x.inc, xvals);
+	    grid->x.vals = xvals;
 	    /*
-	    gridDefXinc(gridID, grid->xinc);
+	    gridDefXinc(gridID, grid->x.inc);
 	    */
 	  }
 
-	if ( grid->ydef == 2 )
+	if ( grid->y.flag == 2 )
 	  {
-            assert(gridtype != GRID_UNSTRUCTURED
-                   && gridtype != GRID_CURVILINEAR);
-	    double *yvals
-              = (double *) Malloc((size_t)grid->ysize * sizeof (double));
-	    gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
-	    grid->yvals = yvals;
+            assert(gridtype != GRID_UNSTRUCTURED && gridtype != GRID_CURVILINEAR);
+	    double *yvals = (double *) Malloc((size_t)grid->y.size * sizeof (double));
+	    gridGenYvals(gridtype, grid->y.size, grid->y.first, grid->y.last, grid->y.inc, yvals);
+	    grid->y.vals = yvals;
 	    /*
-	    gridDefYinc(gridID, grid->yinc);
+	    gridDefYinc(gridID, grid->y.inc);
 	    */
 	  }
 
-	if ( grid->isRotated )
+	if ( grid->isRotated  || grid->projtype == CDI_PROJ_RLL )
 	  {
-	    gridDefXname(gridID, "rlon");
-	    gridDefYname(gridID, "rlat");
-	    gridDefXlongname(gridID, "longitude in rotated pole grid");
-	    gridDefYlongname(gridID, "latitude in rotated pole grid");
-            grid->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
-            grid->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
-	    gridDefXunits(gridID, "degrees");
-	    gridDefYunits(gridID, "degrees");
-
-	    gridDefXpole(gridID, grid->xpole);
-	    gridDefYpole(gridID, grid->ypole);
-	    gridDefAngle(gridID, grid->angle);
+	    if ( grid->x.name[0] == 0 || grid->x.name[0] == 'x' ) gridDefXname(gridID, "rlon");
+	    if ( grid->y.name[0] == 0 || grid->y.name[0] == 'y' ) gridDefYname(gridID, "rlat");
+	    if ( grid->x.longname[0] == 0 ) gridDefXlongname(gridID, "longitude in rotated pole grid");
+	    if ( grid->y.longname[0] == 0 ) gridDefYlongname(gridID, "latitude in rotated pole grid");
+            grid->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+            grid->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+	    if ( grid->x.units[0] == 0 ) gridDefXunits(gridID, "degrees");
+	    if ( grid->y.units[0] == 0 ) gridDefYunits(gridID, "degrees");
+
+            if ( grid->isRotated )
+              {
+                gridDefXpole(gridID, grid->rll.xpole);
+                gridDefYpole(gridID, grid->rll.ypole);
+                gridDefAngle(gridID, grid->rll.angle);
+              }
 	  }
 
         switch (gridtype)
           {
           case GRID_LAEA:
-            gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0);
+            gridDefLaea(gridID, grid->laea.a, grid->laea.lon_0, grid->laea.lat_0);
             break;
           case GRID_LCC2:
-            gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2);
+            gridDefLcc2(gridID, grid->lcc2.a, grid->lcc2.lon_0, grid->lcc2.lat_0, grid->lcc2.lat_1, grid->lcc2.lat_2);
             break;
           case GRID_LCC:
-            gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY,
-                       grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc,
-                       grid->lcc_projflag, grid->lcc_scanflag);
+            gridDefLCC(gridID, grid->lcc.originLon, grid->lcc.originLat, grid->lcc.lonParY,
+                       grid->lcc.lat1, grid->lcc.lat2, grid->lcc.xinc, grid->lcc.yinc,
+                       grid->lcc.projflag, grid->lcc.scanflag);
             break;
           case GRID_UNSTRUCTURED:
             {
               int number = grid->number;
               int position = grid->position >= 0 ? grid->position : 0;
-              if ( number > 0 )
-                {
-                  gridDefNumber(gridID, number);
-                  gridDefPosition(gridID, position);
-                }
+              if ( number > 0 ) gridDefNumber(gridID, number);
+              gridDefPosition(gridID, position);
             }
             break;
 	  }
@@ -2698,21 +2754,20 @@ static void gridComplete(grid_t *grid)
     case GRID_GAUSSIAN_REDUCED:
       {
 	gridDefNP(gridID, grid->np);
-	gridDefYsize(gridID, grid->ysize);
-        if ( grid->xdef == 2 )
+	gridDefYsize(gridID, grid->y.size);
+        if ( grid->x.flag == 2 )
           {
-            double xvals[2] = { grid->xfirst, grid->xlast };
+            double xvals[2] = { grid->x.first, grid->x.last };
             gridDefXvals(gridID, xvals);
           }
 
-        if ( grid->ydef == 2 )
+        if ( grid->y.flag == 2 )
 	  {
-	    double *yvals
-              = (double *) Malloc((size_t)grid->ysize * sizeof (double));
-	    gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
-            grid->yvals = yvals;
+	    double *yvals = (double *) Malloc((size_t)grid->y.size * sizeof (double));
+	    gridGenYvals(gridtype, grid->y.size, grid->y.first, grid->y.last, grid->y.inc, yvals);
+            grid->y.vals = yvals;
 	    /*
-	    gridDefYinc(gridID, grid->yinc);
+	    gridDefYinc(gridID, grid->y.inc);
 	    */
 	  }
 	break;
@@ -2730,21 +2785,21 @@ static void gridComplete(grid_t *grid)
       }
     case GRID_GME:
       {
-        gridDefGMEnd(gridID, grid->nd);
-        gridDefGMEni(gridID, grid->ni);
-        gridDefGMEni2(gridID, grid->ni2);
-        gridDefGMEni3(gridID, grid->ni3);
+        gridDefGMEnd(gridID, grid->gme.nd);
+        gridDefGMEni(gridID, grid->gme.ni);
+        gridDefGMEni2(gridID, grid->gme.ni2);
+        gridDefGMEni3(gridID, grid->gme.ni3);
         break;
       }
       /*
     case GRID_GENERIC:
       {
-        if ( grid->xsize > 0 && grid->ysize > 0 )
+        if ( grid->x.size > 0 && grid->y.size > 0 )
           {
-            gridDefXsize(gridID, grid->xsize);
-            gridDefYsize(gridID, grid->ysize);
-            if ( grid->xvals ) gridDefXvals(gridID, grid->xvals);
-            if ( grid->yvals ) gridDefYvals(gridID, grid->yvals);
+            gridDefXsize(gridID, grid->x.size);
+            gridDefYsize(gridID, grid->y.size);
+            if ( grid->x.vals ) gridDefXvals(gridID, grid->x.vals);
+            if ( grid->y.vals ) gridDefYvals(gridID, grid->y.vals);
           }
         break;
       }
@@ -2762,18 +2817,18 @@ static void gridComplete(grid_t *grid)
       }
     }
 
-  grid->xname[CDI_MAX_NAME - 1] = 0;
-  grid->xlongname[CDI_MAX_NAME - 1] = 0;
-  grid->xunits[CDI_MAX_NAME - 1] = 0;
-  grid->yname[CDI_MAX_NAME - 1] = 0;
-  grid->ylongname[CDI_MAX_NAME - 1] = 0;
-  grid->yunits[CDI_MAX_NAME - 1] = 0;
+  grid->x.name[CDI_MAX_NAME - 1] = 0;
+  grid->x.longname[CDI_MAX_NAME - 1] = 0;
+  grid->x.units[CDI_MAX_NAME - 1] = 0;
+  grid->y.name[CDI_MAX_NAME - 1] = 0;
+  grid->y.longname[CDI_MAX_NAME - 1] = 0;
+  grid->y.units[CDI_MAX_NAME - 1] = 0;
 }
 
-#define GRID_STR_SERIALIZE(gridP) { gridP->xdimname, gridP->ydimname,  \
-    gridP->vdimname, gridP->xname, gridP->yname,  \
-    gridP->xlongname, gridP->ylongname, \
-    gridP->xunits, gridP->yunits }
+#define GRID_STR_SERIALIZE(gridP) { gridP->x.dimname, gridP->y.dimname,  \
+    gridP->vdimname, gridP->x.name, gridP->y.name,  \
+    gridP->x.longname, gridP->y.longname, \
+    gridP->x.units, gridP->y.units }
 
 int gridGenerate(const grid_t *grid)
 {
@@ -2781,11 +2836,11 @@ int gridGenerate(const grid_t *grid)
   int gridID = gridCreate(gridtype, grid->size);
   grid_t *restrict gridptr = gridID2Ptr(gridID);
   gridptr->prec = grid->prec;
-  gridptr->xsize = grid->xsize;
-  gridptr->ysize = grid->ysize;
+  gridptr->x.size = grid->x.size;
+  gridptr->y.size = grid->y.size;
   gridptr->np = grid->np;
   gridptr->nvertex = grid->nvertex;
-  gridptr->xdef = grid->xdef;
+  gridptr->x.flag = grid->x.flag;
   int valdef_group1 = 0;
   static const int valdef_group1_tab[] = {
     GRID_LONLAT, GRID_GAUSSIAN, GRID_UNSTRUCTURED, GRID_CURVILINEAR,
@@ -2794,48 +2849,48 @@ int gridGenerate(const grid_t *grid)
   };
   for ( size_t i = 0; i < sizeof (valdef_group1_tab) / sizeof (valdef_group1_tab[0]); ++i)
     valdef_group1 |= (gridtype == valdef_group1_tab[i]);
-  if ( valdef_group1 && grid->xdef == 1 )
+  if ( valdef_group1 && grid->x.flag == 1 )
     {
-      gridDefXvals(gridID, grid->xvals);
-      if ( grid->xbounds )
-        gridDefXbounds(gridID, grid->xbounds);
+      gridDefXvals(gridID, grid->x.vals);
+      if ( grid->x.bounds )
+        gridDefXbounds(gridID, grid->x.bounds);
     }
-  gridptr->xfirst = grid->xfirst;
-  gridptr->xlast = grid->xlast;
-  gridptr->xinc = grid->xinc;
-  gridptr->ydef = grid->ydef;
-  if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->ydef == 1)
+  gridptr->x.first = grid->x.first;
+  gridptr->x.last = grid->x.last;
+  gridptr->x.inc = grid->x.inc;
+  gridptr->y.flag = grid->y.flag;
+  if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->y.flag == 1)
     {
-      gridDefYvals(gridID, grid->yvals);
-      if ( grid->ybounds )
-        gridDefYbounds(gridID, grid->ybounds);
+      gridDefYvals(gridID, grid->y.vals);
+      if ( grid->y.bounds )
+        gridDefYbounds(gridID, grid->y.bounds);
     }
-  gridptr->yfirst = grid->yfirst;
-  gridptr->ylast = grid->ylast;
-  gridptr->yinc = grid->yinc;
+  gridptr->y.first = grid->y.first;
+  gridptr->y.last = grid->y.last;
+  gridptr->y.inc = grid->y.inc;
   gridptr->isRotated = grid->isRotated;
-  gridptr->xpole = grid->xpole;
-  gridptr->ypole = grid->ypole;
-  gridptr->angle = grid->angle;
+  gridptr->rll.xpole = grid->rll.xpole;
+  gridptr->rll.ypole = grid->rll.ypole;
+  gridptr->rll.angle = grid->rll.angle;
   if ( valdef_group1 && grid->area)
     gridDefArea(gridID, grid->area);
-  gridptr->laea_a = grid->laea_a;
-  gridptr->laea_lon_0 = grid->laea_lon_0;
-  gridptr->laea_lat_0 = grid->laea_lat_0;
-  gridptr->lcc2_a = grid->lcc2_a;
-  gridptr->lcc2_lon_0 = grid->lcc2_lon_0;
-  gridptr->lcc2_lat_0 = grid->lcc2_lat_0;
-  gridptr->lcc2_lat_1 = grid->lcc2_lat_1;
-  gridptr->lcc2_lat_2 = grid->lcc2_lat_2;
-  gridptr->lcc_originLon = grid->lcc_originLon;
-  gridptr->lcc_originLat = grid->lcc_originLat;
-  gridptr->lcc_lonParY = grid->lcc_lonParY;
-  gridptr->lcc_lat1 = grid->lcc_lat1;
-  gridptr->lcc_lat2 = grid->lcc_lat2;
-  gridptr->lcc_xinc = grid->lcc_xinc;
-  gridptr->lcc_yinc = grid->lcc_yinc;
-  gridptr->lcc_projflag = grid->lcc_projflag;
-  gridptr->lcc_scanflag = grid->lcc_scanflag;
+  gridptr->laea.a = grid->laea.a;
+  gridptr->laea.lon_0 = grid->laea.lon_0;
+  gridptr->laea.lat_0 = grid->laea.lat_0;
+  gridptr->lcc2.a = grid->lcc2.a;
+  gridptr->lcc2.lon_0 = grid->lcc2.lon_0;
+  gridptr->lcc2.lat_0 = grid->lcc2.lat_0;
+  gridptr->lcc2.lat_1 = grid->lcc2.lat_1;
+  gridptr->lcc2.lat_2 = grid->lcc2.lat_2;
+  gridptr->lcc.originLon = grid->lcc.originLon;
+  gridptr->lcc.originLat = grid->lcc.originLat;
+  gridptr->lcc.lonParY = grid->lcc.lonParY;
+  gridptr->lcc.lat1 = grid->lcc.lat1;
+  gridptr->lcc.lat2 = grid->lcc.lat2;
+  gridptr->lcc.xinc = grid->lcc.xinc;
+  gridptr->lcc.yinc = grid->lcc.yinc;
+  gridptr->lcc.projflag = grid->lcc.projflag;
+  gridptr->lcc.scanflag = grid->lcc.scanflag;
   gridptr->number = grid->number;
   gridptr->position = grid->position;
   memcpy(gridptr->uuid, grid->uuid, CDI_UUID_SIZE);
@@ -2844,19 +2899,20 @@ int gridGenerate(const grid_t *grid)
   if ( gridtype == GRID_PROJECTION )
     gridptr->name = strdup(grid->name);
   if ( gridtype == GRID_GAUSSIAN_REDUCED )
-    gridDefRowlon(gridID, grid->ysize, grid->rowlon);
+    gridDefRowlon(gridID, grid->y.size, grid->rowlon);
   gridptr->trunc = grid->trunc;
   gridptr->lcomplex = grid->lcomplex;
-  gridptr->nd = grid->nd;
-  gridptr->ni = grid->ni;
-  gridptr->ni2 = grid->ni2;
-  gridptr->ni3 = grid->ni3;
+  gridptr->gme.nd = grid->gme.nd;
+  gridptr->gme.ni = grid->gme.ni;
+  gridptr->gme.ni2 = grid->gme.ni2;
+  gridptr->gme.ni3 = grid->gme.ni3;
   const char *grid_str_tab[] = GRID_STR_SERIALIZE(grid);
   char *gridptr_str_tab[] = GRID_STR_SERIALIZE(gridptr);
   for (size_t i = 0; i < sizeof (grid_str_tab) / sizeof (grid_str_tab[0]); ++i)
     if ( grid_str_tab[i][0] )
       memcpy(gridptr_str_tab[i], grid_str_tab[i], CDI_MAX_NAME);
   gridComplete(gridptr);
+
   return gridID;
 }
 
@@ -2873,38 +2929,38 @@ grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
       memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
     }
 
-  if ( gridptrOrig->xvals != NULL )
+  if ( gridptrOrig->x.vals != NULL )
     {
-      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->xsize;
+      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->x.size;
 
-      gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
+      gridptrDup->x.vals = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->x.vals, gridptrOrig->x.vals, size * sizeof (double));
     }
 
-  if ( gridptrOrig->yvals != NULL )
+  if ( gridptrOrig->y.vals != NULL )
     {
-      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->ysize;
+      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->y.size;
 
-      gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
+      gridptrDup->y.vals = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->y.vals, gridptrOrig->y.vals, size * sizeof (double));
     }
 
-  if ( gridptrOrig->xbounds != NULL )
+  if ( gridptrOrig->x.bounds != NULL )
     {
-      size_t size  = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
+      size_t size  = (irregular ? gridsize : (size_t)gridptrOrig->x.size)
         * (size_t)gridptrOrig->nvertex;
 
-      gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
+      gridptrDup->x.bounds = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->x.bounds, gridptrOrig->x.bounds, size * sizeof (double));
     }
 
-  if ( gridptrOrig->ybounds != NULL )
+  if ( gridptrOrig->y.bounds != NULL )
     {
-      size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
+      size_t size = (irregular ? gridsize : (size_t)gridptrOrig->y.size)
         * (size_t)gridptrOrig->nvertex;
 
-      gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
+      gridptrDup->y.bounds = (double *)Malloc(size * sizeof (double));
+      memcpy(gridptrDup->y.bounds, gridptrOrig->y.bounds, size * sizeof (double));
     }
 
   {
@@ -3012,12 +3068,12 @@ void gridCompress(int gridID)
 	  /* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */
 	  gridsize = nselect;
 	  gridptr->size  = (int)gridsize;
-	  gridptr->xsize = (int)gridsize;
-	  gridptr->ysize = (int)gridsize;
+	  gridptr->x.size = (int)gridsize;
+	  gridptr->y.size = (int)gridsize;
 
-          double **resizeP[] = { &gridptr->xvals, &gridptr->yvals,
+          double **resizeP[] = { &gridptr->x.vals, &gridptr->y.vals,
                                  &gridptr->area,
-                                 &gridptr->xbounds, &gridptr->ybounds };
+                                 &gridptr->x.bounds, &gridptr->y.bounds };
           size_t newSize[] = { gridsize, gridsize, gridsize, nv*gridsize,
                                nv*gridsize };
           for ( size_t i = 0; i < sizeof (resizeP) / sizeof (resizeP[0]); ++i)
@@ -3144,7 +3200,7 @@ gridDefBoundsGeneric(grid_t *gridptr, const double *bounds, int regularSize,
 static void
 gridDefXBoundsSerial(grid_t *gridptr, const double *xbounds)
 {
-  gridDefBoundsGeneric(gridptr, xbounds, gridptr->xsize, &gridptr->xbounds);
+  gridDefBoundsGeneric(gridptr, xbounds, gridptr->x.size, &gridptr->x.bounds);
 }
 
 /*
@@ -3175,7 +3231,7 @@ gridInqXBoundsSerial(grid_t *gridptr, double *xbounds)
 
   int irregular = gridptr->type == GRID_CURVILINEAR
     || gridptr->type == GRID_UNSTRUCTURED;
-  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->x.size);
 
   const double *gridptr_xbounds = gridptr->vtable->inqXBoundsPtr(gridptr);
   if ( gridptr_xbounds )
@@ -3218,7 +3274,7 @@ int gridInqXbounds(int gridID, double *xbounds)
 static const double *
 gridInqXBoundsPtrSerial(grid_t *gridptr)
 {
-  return gridptr->xbounds;
+  return gridptr->x.bounds;
 }
 
 
@@ -3231,7 +3287,7 @@ const double *gridInqXboundsPtr(int gridID)
 static void
 gridDefYBoundsSerial(grid_t *gridptr, const double *ybounds)
 {
-  gridDefBoundsGeneric(gridptr, ybounds, gridptr->ysize, &gridptr->ybounds);
+  gridDefBoundsGeneric(gridptr, ybounds, gridptr->y.size, &gridptr->y.bounds);
 }
 
 /*
@@ -3262,7 +3318,7 @@ gridInqYBoundsSerial(grid_t *gridptr, double *ybounds)
 
   int irregular = gridptr->type == GRID_CURVILINEAR
     || gridptr->type == GRID_UNSTRUCTURED;
-  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->y.size);
 
   const double *gridptr_ybounds = gridptr->vtable->inqYBoundsPtr(gridptr);
   if ( gridptr_ybounds )
@@ -3306,7 +3362,7 @@ int gridInqYbounds(int gridID, double *ybounds)
 static const double *
 gridInqYBoundsPtrSerial(grid_t *gridptr)
 {
-  return gridptr->ybounds;
+  return gridptr->y.bounds;
 }
 
 
@@ -3389,7 +3445,78 @@ printMask(FILE *fp, const char prefix[], size_t nbyte0,
   fputs("\n", fp);
 }
 
-static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
+static inline
+void *resizeBuffer(void **buf, size_t *bufSize, size_t reqSize)
+{
+  if (reqSize > *bufSize)
+    {
+      *buf = Realloc(*buf, reqSize);
+      *bufSize = reqSize;
+    }
+  return *buf;
+}
+
+static
+void gridPrintAttributes(FILE *fp, int gridID)
+{
+  int cdiID = gridID;
+  int varID = CDI_GLOBAL;
+  int atttype, attlen;
+  char attname[CDI_MAX_NAME+1];
+  void *attBuf = NULL;
+  size_t attBufSize = 0;
+
+  int natts;
+  cdiInqNatts(cdiID, varID, &natts);
+
+  for ( int iatt = 0; iatt < natts; ++iatt )
+    {
+      cdiInqAtt(cdiID, varID, iatt, attname, &atttype, &attlen);
+
+      if ( attlen == 0 ) continue;
+
+      if ( atttype == DATATYPE_TXT )
+        {
+          size_t attSize = (size_t)(attlen+1)*sizeof(char);
+          char *atttxt = (char *)resizeBuffer(&attBuf, &attBufSize, attSize);
+          cdiInqAttTxt(cdiID, varID, attname, attlen, atttxt);
+          atttxt[attlen] = 0;
+          fprintf(fp, "ATTR_TXT: %s = \"%s\"\n", attname, atttxt);
+        }
+      else if ( atttype == DATATYPE_INT8  || atttype == DATATYPE_UINT8  ||
+                atttype == DATATYPE_INT16 || atttype == DATATYPE_UINT16 ||
+                atttype == DATATYPE_INT32 || atttype == DATATYPE_UINT32 )
+        {
+          size_t attSize = (size_t)attlen*sizeof(int);
+          int *attint = (int *)resizeBuffer(&attBuf, &attBufSize, attSize);
+          cdiInqAttInt(cdiID, varID, attname, attlen, &attint[0]);
+          if ( attlen == 1 )
+            fprintf(fp, "ATTR_INT: %s =", attname);
+          else
+            fprintf(fp, "ATTR_INT_%d: %s =", attlen, attname);
+          for ( int i = 0; i < attlen; ++i ) fprintf(fp, " %d", attint[i]);
+          fprintf(fp, "\n");
+        }
+      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
+        {
+          size_t attSize = (size_t)attlen * sizeof(double);
+          double *attflt = (double *)resizeBuffer(&attBuf, &attBufSize, attSize);
+          int dig = (atttype == DATATYPE_FLT64) ? 15 : 7;
+          cdiInqAttFlt(cdiID, varID, attname, attlen, attflt);
+          if ( attlen == 1 )
+            fprintf(fp, "ATTR_FLT: %s =", attname);
+          else
+            fprintf(fp, "ATTR_FLT_%d: %s =", attlen, attname);
+          for ( int i = 0; i < attlen; ++i ) fprintf(fp, " %.*g", dig, attflt[i]);
+          fprintf(fp, "\n");
+        }
+    }
+
+  Free(attBuf);
+}
+
+static
+void gridPrintKernel(grid_t *gridptr, int index, int opt, FILE *fp)
 {
   int xdim, ydim;
   unsigned char uuidOfHGrid[CDI_UUID_SIZE];
@@ -3410,6 +3537,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 
   int dig = (prec == DATATYPE_FLT64) ? 15 : 7;
 
+  struct gridaxis_t *xaxis = &gridptr->x;
+  struct gridaxis_t *yaxis = &gridptr->y;
+
   fprintf(fp, "#\n"
           "# gridID %d\n"
           "#\n"
@@ -3418,18 +3548,31 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 
   if ( type != GRID_GME )
     {
+      if ( type != GRID_UNSTRUCTURED && type != GRID_SPECTRAL && type != GRID_FOURIER )
+        {
+          if ( xsize > 0 ) fprintf(fp, "xsize     = %d\n", xsize);
+          if ( ysize > 0 ) fprintf(fp, "ysize     = %d\n", ysize);
+        }
+
       if ( xvals )
         {
-          if ( gridptr->xname[0]     )     fprintf(fp, "xname     = %s\n", gridptr->xname);
-          if ( gridptr->xlongname[0] )     fprintf(fp, "xlongname = %s\n", gridptr->xlongname);
-          if ( gridptr->xunits[0]    )     fprintf(fp, "xunits    = %s\n", gridptr->xunits);
+          if ( xaxis->name[0]     )  fprintf(fp, "xname     = %s\n", xaxis->name);
+          if ( xaxis->longname[0] )  fprintf(fp, "xlongname = %s\n", xaxis->longname);
+          if ( xaxis->units[0]    )  fprintf(fp, "xunits    = %s\n", xaxis->units);
+          if ( xaxis->dimname[0] && strcmp(xaxis->name, xaxis->dimname) )
+            fprintf(fp, "xdimname  = %s\n", xaxis->dimname);
         }
       if ( yvals )
         {
-          if ( gridptr->yname[0]     )     fprintf(fp, "yname     = %s\n", gridptr->yname);
-          if ( gridptr->ylongname[0] )     fprintf(fp, "ylongname = %s\n", gridptr->ylongname);
-          if ( gridptr->yunits[0]    )     fprintf(fp, "yunits    = %s\n", gridptr->yunits);
+          if ( yaxis->name[0]     )  fprintf(fp, "yname     = %s\n", yaxis->name);
+          if ( yaxis->longname[0] )  fprintf(fp, "ylongname = %s\n", yaxis->longname);
+          if ( yaxis->units[0]    )  fprintf(fp, "yunits    = %s\n", yaxis->units);
+          if ( yaxis->dimname[0] && strcmp(yaxis->name, yaxis->dimname) )
+            fprintf(fp, "ydimname  = %s\n", yaxis->dimname);
         }
+
+      if ( type == GRID_UNSTRUCTURED || type == GRID_CURVILINEAR )
+        if ( gridptr->vdimname[0] ) fprintf(fp, "vdimname  = %s\n", gridptr->vdimname);
       if ( type == GRID_UNSTRUCTURED && nvertex > 0 ) fprintf(fp, "nvertex   = %d\n", nvertex);
     }
 
@@ -3442,6 +3585,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
     case GRID_LCC2:
     case GRID_SINUSOIDAL:
     case GRID_LAEA:
+    case GRID_PROJECTION:
     case GRID_CURVILINEAR:
     case GRID_UNSTRUCTURED:
       {
@@ -3463,12 +3607,6 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	    ydim = ysize;
 	  }
 
-	if ( type != GRID_UNSTRUCTURED )
-	  {
-	    if ( xsize > 0 ) fprintf(fp, "xsize     = %d\n", xsize);
-	    if ( ysize > 0 ) fprintf(fp, "ysize     = %d\n", ysize);
-	  }
-
 	if ( type == GRID_UNSTRUCTURED )
           {
             int number = gridInqNumber(gridID);
@@ -3517,9 +3655,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 
 	if ( gridptr->isRotated )
 	  {
-	    if ( xsize > 0 ) fprintf(fp, "xnpole    = %.*g\n", dig, gridptr->xpole);
-	    if ( ysize > 0 ) fprintf(fp, "ynpole    = %.*g\n", dig, gridptr->ypole);
-	    if ( IS_NOT_EQUAL(gridptr->angle, 0) ) fprintf(fp, "angle     = %.*g\n", dig, gridptr->angle);
+	    if ( xsize > 0 ) fprintf(fp, "xnpole    = %.*g\n", dig, gridptr->rll.xpole);
+	    if ( ysize > 0 ) fprintf(fp, "ynpole    = %.*g\n", dig, gridptr->rll.ypole);
+	    if ( IS_NOT_EQUAL(gridptr->rll.angle, 0) ) fprintf(fp, "angle     = %.*g\n", dig, gridptr->rll.angle);
  	  }
 
 	if ( xvals )
@@ -3527,6 +3665,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	    double xfirst = 0.0, xinc = 0.0;
 
 	    if ( type == GRID_LONLAT     || type == GRID_GAUSSIAN ||
+		 type == GRID_PROJECTION ||
 		 type == GRID_GENERIC    || type == GRID_LCC2     ||
                  type == GRID_SINUSOIDAL || type == GRID_LAEA )
 	      {
@@ -3559,7 +3698,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 	  {
 	    double yfirst = 0.0, yinc = 0.0;
 
-	    if ( type == GRID_LONLAT || type == GRID_GENERIC || type == GRID_LCC2 ||
+	    if ( type == GRID_LONLAT || type == GRID_GENERIC ||
+                 type == GRID_PROJECTION ||
+		 type == GRID_GENERIC    || type == GRID_LCC2 ||
 		 type == GRID_SINUSOIDAL || type == GRID_LAEA )
 	      {
 		yfirst = gridInqYval(gridID, 0);
@@ -3604,6 +3745,8 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
             Free(rowlon);
           }
 
+        if ( type == GRID_PROJECTION ) gridPrintAttributes(fp, gridID);
+
 	break;
       }
     case GRID_LCC:
@@ -3614,8 +3757,6 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
 		   &projflag, &scanflag);
 
 	fprintf(fp,
-                "xsize     = %d\n"
-                "ysize     = %d\n"
                 "originLon = %.*g\n"
                 "originLat = %.*g\n"
                 "lonParY   = %.*g\n"
@@ -3624,7 +3765,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
                 "xinc      = %.*g\n"
                 "yinc      = %.*g\n"
                 "projection = %s\n",
-                xsize, ysize, dig, originLon, dig, originLat, dig, lonParY,
+                dig, originLon, dig, originLat, dig, lonParY,
                 dig, lat1, dig, lat2, dig, xincm, dig, yincm,
                 (projflag & 128) == 0 ? "northpole" : "southpole");
 	break;
@@ -3642,7 +3783,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
       }
     case GRID_GME:
       {
-        fprintf(fp, "ni        = %d\n", gridptr->ni );
+        fprintf(fp, "ni        = %d\n", gridptr->gme.ni );
         break;
       }
    default:
@@ -3697,8 +3838,8 @@ void gridPrintP ( void * voidptr, FILE * fp )
           "trunc     = %d\n"
           "lcomplex  = %d\n"
           "nrowlon   = %d\n",
-          gridptr->prec, gridptr->nd, gridptr->ni, gridptr->ni2,
-          gridptr->ni3, gridptr->number, gridptr->position, gridptr->trunc,
+          gridptr->prec, gridptr->gme.nd, gridptr->gme.ni, gridptr->gme.ni2,
+          gridptr->gme.ni3, gridptr->number, gridptr->position, gridptr->trunc,
           gridptr->lcomplex, gridptr->nrowlon );
 
   if ( gridptr->rowlon )
@@ -3720,7 +3861,7 @@ void gridPrintP ( void * voidptr, FILE * fp )
 
 static const double *gridInqXValsPtrSerial(grid_t *gridptr)
 {
-  return gridptr->xvals;
+  return gridptr->x.vals;
 }
 
 const double *gridInqXvalsPtr(int gridID)
@@ -3732,7 +3873,7 @@ const double *gridInqXvalsPtr(int gridID)
 
 static const double *gridInqYValsPtrSerial(grid_t *gridptr)
 {
-  return gridptr->yvals;
+  return gridptr->y.vals;
 }
 
 const double *gridInqYvalsPtr(int gridID)
@@ -3774,16 +3915,16 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
 	    gridNamePtr(gridptr->type));
   else
     {
-      gridptr->lcc_originLon = originLon;
-      gridptr->lcc_originLat = originLat;
-      gridptr->lcc_lonParY   = lonParY;
-      gridptr->lcc_lat1      = lat1;
-      gridptr->lcc_lat2      = lat2;
-      gridptr->lcc_xinc      = xinc;
-      gridptr->lcc_yinc      = yinc;
-      gridptr->lcc_projflag  = projflag;
-      gridptr->lcc_scanflag  = scanflag;
-      gridptr->lcc_defined   = TRUE;
+      gridptr->lcc.originLon = originLon;
+      gridptr->lcc.originLat = originLat;
+      gridptr->lcc.lonParY   = lonParY;
+      gridptr->lcc.lat1      = lat1;
+      gridptr->lcc.lat2      = lat2;
+      gridptr->lcc.xinc      = xinc;
+      gridptr->lcc.yinc      = yinc;
+      gridptr->lcc.projflag  = projflag;
+      gridptr->lcc.scanflag  = scanflag;
+      gridptr->lcc.defined   = TRUE;
       gridMark4Update(gridID);
     }
 }
@@ -3821,17 +3962,17 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar
 	    gridNamePtr(gridptr->type));
   else
     {
-      if ( gridptr->lcc_defined )
+      if ( gridptr->lcc.defined )
         {
-          *originLon = gridptr->lcc_originLon;
-          *originLat = gridptr->lcc_originLat;
-          *lonParY   = gridptr->lcc_lonParY;
-          *lat1      = gridptr->lcc_lat1;
-          *lat2      = gridptr->lcc_lat2;
-          *xinc      = gridptr->lcc_xinc;
-          *yinc      = gridptr->lcc_yinc;
-          *projflag  = gridptr->lcc_projflag;
-          *scanflag  = gridptr->lcc_scanflag;
+          *originLon = gridptr->lcc.originLon;
+          *originLat = gridptr->lcc.originLat;
+          *lonParY   = gridptr->lcc.lonParY;
+          *lat1      = gridptr->lcc.lat1;
+          *lat2      = gridptr->lcc.lat2;
+          *xinc      = gridptr->lcc.xinc;
+          *yinc      = gridptr->lcc.yinc;
+          *projflag  = gridptr->lcc.projflag;
+          *scanflag  = gridptr->lcc.scanflag;
         }
       else
 	Warning("Lambert Conformal grid undefined (gridID = %d)", gridID);
@@ -3847,12 +3988,12 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do
 	    gridNamePtr(gridptr->type));
   else
     {
-      gridptr->lcc2_a       = earth_radius;
-      gridptr->lcc2_lon_0   = lon_0;
-      gridptr->lcc2_lat_0   = lat_0;
-      gridptr->lcc2_lat_1   = lat_1;
-      gridptr->lcc2_lat_2   = lat_2;
-      gridptr->lcc2_defined = TRUE;
+      gridptr->lcc2.a       = earth_radius;
+      gridptr->lcc2.lon_0   = lon_0;
+      gridptr->lcc2.lat_0   = lat_0;
+      gridptr->lcc2.lat_1   = lat_1;
+      gridptr->lcc2.lat_2   = lat_2;
+      gridptr->lcc2.defined = TRUE;
       gridMark4Update(gridID);
     }
 }
@@ -3867,13 +4008,13 @@ void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0,
 	    gridNamePtr(gridptr->type));
   else
     {
-      if ( gridptr->lcc2_defined )
+      if ( gridptr->lcc2.defined )
         {
-          *earth_radius = gridptr->lcc2_a;
-          *lon_0        = gridptr->lcc2_lon_0;
-          *lat_0        = gridptr->lcc2_lat_0;
-          *lat_1        = gridptr->lcc2_lat_1;
-          *lat_2        = gridptr->lcc2_lat_2;
+          *earth_radius = gridptr->lcc2.a;
+          *lon_0        = gridptr->lcc2.lon_0;
+          *lat_0        = gridptr->lcc2.lat_0;
+          *lat_1        = gridptr->lcc2.lat_1;
+          *lat_2        = gridptr->lcc2.lat_2;
         }
       else
         Warning("LCC2 grid undefined (gridID = %d)", gridID);
@@ -3889,10 +4030,10 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
             gridNamePtr(gridptr->type));
   else
     {
-      gridptr->laea_a       = earth_radius;
-      gridptr->laea_lon_0   = lon_0;
-      gridptr->laea_lat_0   = lat_0;
-      gridptr->laea_defined = TRUE;
+      gridptr->laea.a       = earth_radius;
+      gridptr->laea.lon_0   = lon_0;
+      gridptr->laea.lat_0   = lat_0;
+      gridptr->laea.defined = TRUE;
       gridMark4Update(gridID);
     }
 }
@@ -3907,11 +4048,11 @@ void gridInqLaea(int gridID, double *earth_radius, double *lon_0, double *lat_0)
             gridNamePtr(gridptr->type));
   else
     {
-      if ( gridptr->laea_defined )
+      if ( gridptr->laea.defined )
         {
-          *earth_radius = gridptr->laea_a;
-          *lon_0        = gridptr->laea_lon_0;
-          *lat_0        = gridptr->laea_lat_0;
+          *earth_radius = gridptr->laea.a;
+          *lon_0        = gridptr->laea.lon_0;
+          *lat_0        = gridptr->laea.lat_0;
         }
       else
         Warning("LAEA grid undefined (gridID = %d)", gridID);
@@ -3925,7 +4066,7 @@ void gridDefComplexPacking(int gridID, int lcomplex)
 
   if (gridptr->lcomplex != lcomplex)
     {
-      gridptr->lcomplex = (short)(lcomplex != 0);
+      gridptr->lcomplex = lcomplex != 0;
       gridMark4Update(gridID);
     }
 }
@@ -3935,7 +4076,7 @@ int gridInqComplexPacking(int gridID)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  return gridptr->lcomplex;
+  return (int)gridptr->lcomplex;
 }
 
 
@@ -3955,7 +4096,7 @@ int gridInqHasDims(int gridID)
 {
   grid_t* gridptr = gridID2Ptr(gridID);
 
-  return gridptr->hasdims;
+  return (int)gridptr->hasdims;
 }
 
 /*
@@ -4201,8 +4342,8 @@ static int gridGetComponentFlags(const grid_t * gridP)
     | (gridHasAreaFlag
        & (int)((unsigned)(gridP->vtable->inqAreaPtr((grid_t *)gridP) == NULL)
                - 1U))
-    | (gridHasXBoundsFlag & (int)((unsigned)(gridP->xbounds == NULL) - 1U))
-    | (gridHasYBoundsFlag & (int)((unsigned)(gridP->ybounds == NULL) - 1U))
+    | (gridHasXBoundsFlag & (int)((unsigned)(gridP->x.bounds == NULL) - 1U))
+    | (gridHasYBoundsFlag & (int)((unsigned)(gridP->y.bounds == NULL) - 1U))
     | (gridHasReferenceFlag & (int)((unsigned)(gridP->reference == NULL) - 1U))
     | (gridHasRowLonFlag & (int)((unsigned)(gridP->rowlon == NULL) - 1U))
     | (gridHasUUIDFlag & (int)((unsigned)cdiUUIDIsNull(gridP->uuid) - 1U));
@@ -4232,7 +4373,7 @@ gridGetPackSize(void * voidP, void *context)
       if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
 	count = gridP->size;
       else
-	count = gridP->xsize;
+	count = gridP->x.size;
       xassert(count);
       packBuffSize += serializeGetSize(count, DATATYPE_FLT64, context)
         + serializeGetSize(1, DATATYPE_UINT32, context);
@@ -4243,7 +4384,7 @@ gridGetPackSize(void * voidP, void *context)
       if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
 	count = gridP->size;
       else
-	count = gridP->ysize;
+	count = gridP->y.size;
       xassert(count);
       packBuffSize += serializeGetSize(count, DATATYPE_FLT64, context)
         + serializeGetSize(1, DATATYPE_UINT32, context);
@@ -4257,26 +4398,26 @@ gridGetPackSize(void * voidP, void *context)
         + serializeGetSize(1, DATATYPE_UINT32, context);
     }
 
-  if (gridP->xbounds)
+  if (gridP->x.bounds)
     {
       xassert(gridP->nvertex);
       if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
 	count = gridP->size;
       else
-	count = gridP->xsize;
+	count = gridP->x.size;
       xassert(count);
       packBuffSize
         += (serializeGetSize(gridP->nvertex * count, DATATYPE_FLT64, context)
             + serializeGetSize(1, DATATYPE_UINT32, context));
     }
 
-  if (gridP->ybounds)
+  if (gridP->y.bounds)
     {
       xassert(gridP->nvertex);
       if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
 	count = gridP->size;
       else
-	count = gridP->ysize;
+	count = gridP->y.size;
       xassert(count);
       packBuffSize
         += (serializeGetSize(gridP->nvertex * count, DATATYPE_FLT64, context)
@@ -4345,31 +4486,31 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
     gridP->type          =   intBuffer[1];
     gridP->prec          =   intBuffer[2];
-    gridP->lcc_projflag  =   intBuffer[3];
-    gridP->lcc_scanflag  =   intBuffer[4];
-    gridP->lcc_defined   =   (short)intBuffer[5];
-    gridP->lcc2_defined  =   (short)intBuffer[6];
-    gridP->laea_defined  =   intBuffer[7];
+    gridP->lcc.projflag  =   intBuffer[3];
+    gridP->lcc.scanflag  =   intBuffer[4];
+    gridP->lcc.defined   =   (short)intBuffer[5];
+    gridP->lcc2.defined  =   (short)intBuffer[6];
+    gridP->laea.defined  =   intBuffer[7];
     gridP->isCyclic      =   (short)intBuffer[8];
     gridP->isRotated     =   (short)intBuffer[9];
-    gridP->xdef          =   (short)intBuffer[10];
-    gridP->ydef          =   (short)intBuffer[11];
-    gridP->nd            =   intBuffer[12];
-    gridP->ni            =   intBuffer[13];
-    gridP->ni2           =   intBuffer[14];
-    gridP->ni3           =   intBuffer[15];
+    gridP->x.flag        =   (short)intBuffer[10];
+    gridP->y.flag        =   (short)intBuffer[11];
+    gridP->gme.nd        =   intBuffer[12];
+    gridP->gme.ni        =   intBuffer[13];
+    gridP->gme.ni2       =   intBuffer[14];
+    gridP->gme.ni3       =   intBuffer[15];
     gridP->number        =   intBuffer[16];
     gridP->position      =   intBuffer[17];
     gridP->trunc         =   intBuffer[18];
     gridP->nvertex       =   intBuffer[19];
     gridP->nrowlon       =   intBuffer[20];
     gridP->size          =   intBuffer[21];
-    gridP->xsize         =   intBuffer[22];
-    gridP->ysize         =   intBuffer[23];
-    gridP->lcomplex      =   (short)intBuffer[24];
+    gridP->x.size        =   intBuffer[22];
+    gridP->y.size        =   intBuffer[23];
+    gridP->lcomplex      =   (bool)intBuffer[24];
     memberMask           =   intBuffer[25];
-    gridP->xstdname      =   xystdname_tab[intBuffer[26]][0];
-    gridP->ystdname      =   xystdname_tab[intBuffer[27]][1];
+    gridP->x.stdname     =   xystdname_tab[intBuffer[26]][0];
+    gridP->y.stdname     =   xystdname_tab[intBuffer[27]][1];
   }
 
   if (memberMask & gridHasRowLonFlag)
@@ -4391,56 +4532,56 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
                     &d, 1, DATATYPE_UINT32, context);
     xassert(d == cdiCheckSum(DATATYPE_FLT, gridNdouble, doubleBuffer));
 
-    gridP->xfirst = doubleBuffer[0];
-    gridP->yfirst = doubleBuffer[1];
-    gridP->xlast = doubleBuffer[2];
-    gridP->ylast = doubleBuffer[3];
-    gridP->xinc = doubleBuffer[4];
-    gridP->yinc = doubleBuffer[5];
-    gridP->lcc_originLon = doubleBuffer[6];
-    gridP->lcc_originLat = doubleBuffer[7];
-    gridP->lcc_lonParY = doubleBuffer[8];
-    gridP->lcc_lat1 = doubleBuffer[9];
-    gridP->lcc_lat2 = doubleBuffer[10];
-    gridP->lcc_xinc = doubleBuffer[11];
-    gridP->lcc_yinc = doubleBuffer[12];
-    gridP->lcc2_lon_0 = doubleBuffer[13];
-    gridP->lcc2_lat_0 = doubleBuffer[14];
-    gridP->lcc2_lat_1 = doubleBuffer[15];
-    gridP->lcc2_lat_2 = doubleBuffer[16];
-    gridP->lcc2_a = doubleBuffer[17];
-    gridP->laea_lon_0 = doubleBuffer[18];
-    gridP->laea_lat_0 = doubleBuffer[19];
-    gridP->laea_a = doubleBuffer[20];
-    gridP->xpole = doubleBuffer[21];
-    gridP->ypole = doubleBuffer[22];
-    gridP->angle = doubleBuffer[23];
+    gridP->x.first = doubleBuffer[0];
+    gridP->y.first = doubleBuffer[1];
+    gridP->x.last = doubleBuffer[2];
+    gridP->y.last = doubleBuffer[3];
+    gridP->x.inc = doubleBuffer[4];
+    gridP->y.inc = doubleBuffer[5];
+    gridP->lcc.originLon = doubleBuffer[6];
+    gridP->lcc.originLat = doubleBuffer[7];
+    gridP->lcc.lonParY = doubleBuffer[8];
+    gridP->lcc.lat1 = doubleBuffer[9];
+    gridP->lcc.lat2 = doubleBuffer[10];
+    gridP->lcc.xinc = doubleBuffer[11];
+    gridP->lcc.yinc = doubleBuffer[12];
+    gridP->lcc2.lon_0 = doubleBuffer[13];
+    gridP->lcc2.lat_0 = doubleBuffer[14];
+    gridP->lcc2.lat_1 = doubleBuffer[15];
+    gridP->lcc2.lat_2 = doubleBuffer[16];
+    gridP->lcc2.a = doubleBuffer[17];
+    gridP->laea.lon_0 = doubleBuffer[18];
+    gridP->laea.lat_0 = doubleBuffer[19];
+    gridP->laea.a = doubleBuffer[20];
+    gridP->rll.xpole = doubleBuffer[21];
+    gridP->rll.ypole = doubleBuffer[22];
+    gridP->rll.angle = doubleBuffer[23];
   }
 
   int irregular = gridP->type == GRID_UNSTRUCTURED
     || gridP->type == GRID_CURVILINEAR;
   if (memberMask & gridHasXValsFlag)
     {
-      size = irregular ? gridP->size : gridP->xsize;
+      size = irregular ? gridP->size : gridP->x.size;
 
-      gridP->xvals = (double *) Malloc((size_t)size * sizeof (double));
+      gridP->x.vals = (double *) Malloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                      gridP->xvals, size, DATATYPE_FLT64, context);
+                      gridP->x.vals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &d, 1, DATATYPE_UINT32, context);
-      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->xvals) == d );
+      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->x.vals) == d );
     }
 
   if (memberMask & gridHasYValsFlag)
     {
-      size = irregular ? gridP->size : gridP->ysize;
+      size = irregular ? gridP->size : gridP->y.size;
 
-      gridP->yvals = (double *) Malloc((size_t)size * sizeof (double));
+      gridP->y.vals = (double *) Malloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                      gridP->yvals, size, DATATYPE_FLT64, context);
+                      gridP->y.vals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &d, 1, DATATYPE_UINT32, context);
-      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->yvals) == d);
+      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->y.vals) == d);
     }
 
   if (memberMask & gridHasAreaFlag)
@@ -4457,28 +4598,28 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasXBoundsFlag)
     {
-      size = gridP->nvertex * (irregular ? gridP->size : gridP->xsize);
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->x.size);
       xassert(size);
 
-      gridP->xbounds = (double *) Malloc((size_t)size * sizeof (double));
+      gridP->x.bounds = (double *) Malloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                      gridP->xbounds, size, DATATYPE_FLT64, context);
+                      gridP->x.bounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &d, 1, DATATYPE_UINT32, context);
-      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->xbounds) == d);
+      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->x.bounds) == d);
     }
 
   if (memberMask & gridHasYBoundsFlag)
     {
-      size = gridP->nvertex * (irregular ? gridP->size : gridP->ysize);
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->y.size);
       xassert(size);
 
-      gridP->ybounds = (double *) Malloc((size_t)size * sizeof (double));
+      gridP->y.bounds = (double *) Malloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-			  gridP->ybounds, size, DATATYPE_FLT64, context);
+			  gridP->y.bounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &d, 1, DATATYPE_UINT32, context);
-      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->ybounds) == d);
+      xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->y.bounds) == d);
     }
 
   {
@@ -4548,32 +4689,32 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
     intBuffer[0]  = gridP->self;
     intBuffer[1]  = gridP->type;
     intBuffer[2]  = gridP->prec;
-    intBuffer[3]  = gridP->lcc_projflag;
-    intBuffer[4]  = gridP->lcc_scanflag;
-    intBuffer[5]  = gridP->lcc_defined;
-    intBuffer[6]  = gridP->lcc2_defined;
-    intBuffer[7]  = gridP->laea_defined;
+    intBuffer[3]  = gridP->lcc.projflag;
+    intBuffer[4]  = gridP->lcc.scanflag;
+    intBuffer[5]  = gridP->lcc.defined;
+    intBuffer[6]  = gridP->lcc2.defined;
+    intBuffer[7]  = gridP->laea.defined;
     intBuffer[8]  = gridP->isCyclic;
     intBuffer[9]  = gridP->isRotated;
-    intBuffer[10] = gridP->xdef;
-    intBuffer[11] = gridP->ydef;
-    intBuffer[12] = gridP->nd;
-    intBuffer[13] = gridP->ni;
-    intBuffer[14] = gridP->ni2;
-    intBuffer[15] = gridP->ni3;
+    intBuffer[10] = gridP->x.flag;
+    intBuffer[11] = gridP->y.flag;
+    intBuffer[12] = gridP->gme.nd;
+    intBuffer[13] = gridP->gme.ni;
+    intBuffer[14] = gridP->gme.ni2;
+    intBuffer[15] = gridP->gme.ni3;
     intBuffer[16] = gridP->number;
     intBuffer[17] = gridP->position;
     intBuffer[18] = gridP->trunc;
     intBuffer[19] = gridP->nvertex;
     intBuffer[20] = gridP->nrowlon;
     intBuffer[21] = gridP->size;
-    intBuffer[22] = gridP->xsize;
-    intBuffer[23] = gridP->ysize;
+    intBuffer[22] = gridP->x.size;
+    intBuffer[23] = gridP->y.size;
     intBuffer[24] = gridP->lcomplex;
     intBuffer[25] = memberMask = gridGetComponentFlags(gridP);
-    intBuffer[26] = (int)((const char (*)[2][24])gridP->xstdname
+    intBuffer[26] = (int)((const char (*)[2][24])gridP->x.stdname
                           - xystdname_tab);
-    intBuffer[27] = (int)((const char (*)[2][24])gridP->ystdname
+    intBuffer[27] = (int)((const char (*)[2][24])gridP->y.stdname
                           - (const char (*)[2][24])xystdname_tab[0][1]);
 
     serializePack(intBuffer, gridNint, DATATYPE_INT,
@@ -4597,30 +4738,30 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
   {
     double doubleBuffer[gridNdouble];
 
-    doubleBuffer[0]  = gridP->xfirst;
-    doubleBuffer[1]  = gridP->yfirst;
-    doubleBuffer[2]  = gridP->xlast;
-    doubleBuffer[3]  = gridP->ylast;
-    doubleBuffer[4]  = gridP->xinc;
-    doubleBuffer[5]  = gridP->yinc;
-    doubleBuffer[6]  = gridP->lcc_originLon;
-    doubleBuffer[7]  = gridP->lcc_originLat;
-    doubleBuffer[8]  = gridP->lcc_lonParY;
-    doubleBuffer[9]  = gridP->lcc_lat1;
-    doubleBuffer[10] = gridP->lcc_lat2;
-    doubleBuffer[11] = gridP->lcc_xinc;
-    doubleBuffer[12] = gridP->lcc_yinc;
-    doubleBuffer[13] = gridP->lcc2_lon_0;
-    doubleBuffer[14] = gridP->lcc2_lat_0;
-    doubleBuffer[15] = gridP->lcc2_lat_1;
-    doubleBuffer[16] = gridP->lcc2_lat_2;
-    doubleBuffer[17] = gridP->lcc2_a;
-    doubleBuffer[18] = gridP->laea_lon_0;
-    doubleBuffer[19] = gridP->laea_lat_0;
-    doubleBuffer[20] = gridP->laea_a;
-    doubleBuffer[21] = gridP->xpole;
-    doubleBuffer[22] = gridP->ypole;
-    doubleBuffer[23] = gridP->angle;
+    doubleBuffer[0]  = gridP->x.first;
+    doubleBuffer[1]  = gridP->y.first;
+    doubleBuffer[2]  = gridP->x.last;
+    doubleBuffer[3]  = gridP->y.last;
+    doubleBuffer[4]  = gridP->x.inc;
+    doubleBuffer[5]  = gridP->y.inc;
+    doubleBuffer[6]  = gridP->lcc.originLon;
+    doubleBuffer[7]  = gridP->lcc.originLat;
+    doubleBuffer[8]  = gridP->lcc.lonParY;
+    doubleBuffer[9]  = gridP->lcc.lat1;
+    doubleBuffer[10] = gridP->lcc.lat2;
+    doubleBuffer[11] = gridP->lcc.xinc;
+    doubleBuffer[12] = gridP->lcc.yinc;
+    doubleBuffer[13] = gridP->lcc2.lon_0;
+    doubleBuffer[14] = gridP->lcc2.lat_0;
+    doubleBuffer[15] = gridP->lcc2.lat_1;
+    doubleBuffer[16] = gridP->lcc2.lat_2;
+    doubleBuffer[17] = gridP->lcc2.a;
+    doubleBuffer[18] = gridP->laea.lon_0;
+    doubleBuffer[19] = gridP->laea.lat_0;
+    doubleBuffer[20] = gridP->laea.a;
+    doubleBuffer[21] = gridP->rll.xpole;
+    doubleBuffer[22] = gridP->rll.ypole;
+    doubleBuffer[23] = gridP->rll.angle;
 
     serializePack(doubleBuffer, gridNdouble, DATATYPE_FLT64,
                   packBuffer, packBufferSize, packBufferPos, context);
@@ -4634,7 +4775,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
       if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
 	size = gridP->size;
       else
-	size = gridP->xsize;
+	size = gridP->x.size;
       xassert(size);
 
       const double *gridP_xvals = gridP->vtable->inqXValsPtr(gridP);
@@ -4650,7 +4791,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
       if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR )
 	size = gridP->size;
       else
-	size = gridP->ysize;
+	size = gridP->y.size;
       xassert(size);
       const double *gridP_yvals = gridP->vtable->inqYValsPtr(gridP);
       serializePack(gridP_yvals, size, DATATYPE_FLT64,
@@ -4677,12 +4818,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
       if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
 	size = gridP->nvertex * gridP->size;
       else
-	size = gridP->nvertex * gridP->xsize;
+	size = gridP->nvertex * gridP->x.size;
       xassert ( size );
 
-      serializePack(gridP->xbounds, size, DATATYPE_FLT64,
+      serializePack(gridP->x.bounds, size, DATATYPE_FLT64,
                     packBuffer, packBufferSize, packBufferPos, context);
-      d = cdiCheckSum(DATATYPE_FLT, size, gridP->xbounds);
+      d = cdiCheckSum(DATATYPE_FLT, size, gridP->x.bounds);
       serializePack(&d, 1, DATATYPE_UINT32,
                     packBuffer, packBufferSize, packBufferPos, context);
     }
@@ -4693,12 +4834,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
       if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
 	size = gridP->nvertex * gridP->size;
       else
-	size = gridP->nvertex * gridP->ysize;
+	size = gridP->nvertex * gridP->y.size;
       xassert ( size );
 
-      serializePack(gridP->ybounds, size, DATATYPE_FLT64,
+      serializePack(gridP->y.bounds, size, DATATYPE_FLT64,
                     packBuffer, packBufferSize, packBufferPos, context);
-      d = cdiCheckSum(DATATYPE_FLT, size, gridP->ybounds);
+      d = cdiCheckSum(DATATYPE_FLT, size, gridP->y.bounds);
       serializePack(&d, 1, DATATYPE_UINT32,
                     packBuffer, packBufferSize, packBufferPos, context);
     }
@@ -4771,12 +4912,13 @@ gridCompareSearch(int id, void *res, void *data)
     return CDI_APPLY_GO_ON;
 }
 
-/* Add grid (which must be Malloc'ed to vlist if not already found */
-struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
+/* Add grid (which must be Malloc'ed to vlist if not already found) */
+struct addIfNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
 {
   /*
     mode: 0 search in vlist and grid table
           1 search in grid table only
+          2 search in grid table only and don't store the grid in vlist
    */
   bool gridglobdefined = false;
   bool griddefined = false;
@@ -4799,20 +4941,18 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
         else
           Error("Internal problem: undefined gridID in vlist "
                 "%d, position %u!", vlistID, index);
-
       }
 
   if ( ! griddefined )
     {
       struct gridCompareSearchState query;
       query.queryKey = grid;// = { .queryKey = grid };
-      if ((gridglobdefined
-           = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query)
-              == CDI_APPLY_STOP)))
+      if ( (gridglobdefined = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query)
+              == CDI_APPLY_STOP)) )
         gridID = query.resIDValue;
 
       if ( mode == 1 && gridglobdefined )
-	for (unsigned index = 0; index < ngrids; index++ )
+	for ( unsigned index = 0; index < ngrids; index++ )
 	  if ( vlistptr->gridIDs[index] == gridID )
 	    {
 	      gridglobdefined = false;
@@ -4827,14 +4967,17 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
           grid->self = gridID = reshPut(grid, &gridOps);
           gridComplete(grid);
         }
-      vlistptr->gridIDs[ngrids] = gridID;
-      vlistptr->ngrids++;
+      if ( mode < 2 )
+        {
+          vlistptr->gridIDs[ngrids] = gridID;
+          vlistptr->ngrids++;
+        }
     }
 
-  return (struct addIffNewRes){ .Id = gridID,
-      .isNew = !griddefined && !gridglobdefined };
+  return (struct addIfNewRes){ .Id = gridID, .isNew = !griddefined && !gridglobdefined };
 }
 
+
 const struct gridVirtTable cdiGridVtable
   = {
   .destroy = gridDestroyKernel,
diff --git a/src/grid.h b/src/grid.h
index 5ae1682087df5886895aa5e66ec676e43b99a47d..5f36eae33f91b11e5e427378164c2905f9433d0f 100644
--- a/src/grid.h
+++ b/src/grid.h
@@ -4,6 +4,8 @@
 #include "cdi.h"
 #include <stdbool.h>
 
+#include "cdi_att.h"
+
 typedef unsigned char mask_t;
 
 typedef struct grid_t grid_t;
@@ -43,47 +45,77 @@ struct gridVirtTable
   const double *(*inqYBoundsPtr)(grid_t *gridptr);
 };
 
+struct gridaxis_t {
+  char    name[CDI_MAX_NAME];
+  char    longname[CDI_MAX_NAME];
+  char    units[CDI_MAX_NAME];
+  char    dimname[CDI_MAX_NAME];
+  const char *stdname;
+  int     size;                  // number of values
+  short   flag;                  // 0: undefined 1:vals 2:first+inc
+  double  first, last, inc;
+  double *vals;
+  double *bounds;
+};
+
+// Lambert Conformal Conic
+struct grid_lcc_t {
+  double  originLon;
+  double  originLat;
+  double  lonParY;
+  double  lat1;
+  double  lat2;
+  double  xinc;
+  double  yinc;
+  int     projflag;
+  int     scanflag;
+  short   defined;
+};
+
+// Lambert Conformal Conic 2
+struct grid_lcc2_t {
+  double  lon_0;
+  double  lat_0;
+  double  lat_1;
+  double  lat_2;
+  double  a;
+  short   defined;
+};
+
+// Lambert Azimuthal Equal Area
+struct grid_laea_t {
+  double  lon_0;
+  double  lat_0;
+  double  a;
+  short   defined;
+};
+
+// GME Grid
+struct grid_gme_t {
+  int     nd, ni, ni2, ni3;       /* parameter for GRID_GME         */
+};
+
+// Rotated LonLat
+struct grid_rll_t {
+  double  xpole, ypole, angle;    /* rotated north pole             */
+};
+
 struct grid_t {
   int     self;
   int     type;                   /* grid type                      */
   int     prec;                   /* grid precision                 */
   int     proj;                   /* grid projection                */
+  int     projtype;               /* grid projection type           */
   mask_t *mask;
   mask_t *mask_gme;
-  double *xvals;
-  double *yvals;
   double *area;
-  double *xbounds;
-  double *ybounds;
-  double  xfirst, yfirst;
-  double  xlast, ylast;
-  double  xinc, yinc;
-  double  lcc_originLon;          /* Lambert Conformal Conic        */
-  double  lcc_originLat;
-  double  lcc_lonParY;
-  double  lcc_lat1;
-  double  lcc_lat2;
-  double  lcc_xinc;
-  double  lcc_yinc;
-  int     lcc_projflag;
-  int     lcc_scanflag;
-  short   lcc_defined;
-  short   lcc2_defined;
-  int     laea_defined;
-  double  lcc2_lon_0;             /* Lambert Conformal Conic 2      */
-  double  lcc2_lat_0;
-  double  lcc2_lat_1;
-  double  lcc2_lat_2;
-  double  lcc2_a;
-  double  laea_lon_0;             /* Lambert Azimuthal Equal Area   */
-  double  laea_lat_0;
-  double  laea_a;
-  double  xpole, ypole, angle;    /* rotated north pole             */
+  struct grid_lcc_t  lcc;
+  struct grid_lcc2_t lcc2;
+  struct grid_laea_t laea;
+  struct grid_gme_t  gme;
+  struct grid_rll_t  rll;
   short   isCyclic;               /* TRUE for global cyclic grids   */
   short   isRotated;              /* TRUE for rotated grids         */
-  short   xdef;                   /* 0: undefined 1:xvals 2:x0+xinc */
-  short   ydef;                   /* 0: undefined 1:yvals 2:y0+yinc */
-  int     nd, ni, ni2, ni3;       /* parameter for GRID_GME         */
   int     number, position;       /* parameter for GRID_REFERENCE   */
   int     trunc;                  /* parameter for GRID_SPECTEAL    */
   int     nvertex;
@@ -92,37 +124,30 @@ struct grid_t {
   int    *rowlon;
   int     nrowlon;
   int     size;
-  int     xsize;                  /* number of values along X */
-  int     ysize;                  /* number of values along Y */
   int     np;                     /* number of parallels between a pole and the equator */
-  short   lcomplex;
-  short   hasdims;
-  const char *xstdname;
-  const char *ystdname;
-  char    xdimname[CDI_MAX_NAME];
-  char    ydimname[CDI_MAX_NAME];
+  bool    lcomplex;
+  bool    hasdims;
   char    vdimname[CDI_MAX_NAME];
-  char    xname[CDI_MAX_NAME];
-  char    yname[CDI_MAX_NAME];
-  char    xlongname[CDI_MAX_NAME];
-  char    ylongname[CDI_MAX_NAME];
-  char    xunits[CDI_MAX_NAME];
-  char    yunits[CDI_MAX_NAME];
+  char    mapname[CDI_MAX_NAME];
+  char    mapping[CDI_MAX_NAME];
   char   *name;
+  struct gridaxis_t x;
+  struct gridaxis_t y;
   const struct gridVirtTable *vtable;
-  void *extraData;
+  cdi_atts_t atts;
 };
 
 
 void grid_init(grid_t *gridptr);
-void
-cdiGridTypeInit(grid_t *gridptr, int gridtype, int size);
+void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size);
 void grid_free(grid_t *gridptr);
 grid_t *gridID2Ptr(int gridID);
 extern const struct gridVirtTable cdiGridVtable;
 
 unsigned cdiGridCount(void);
 
+void gridVerifyProj(int gridID);
+
 const double *gridInqXvalsPtr(int gridID);
 const double *gridInqYvalsPtr(int gridID);
 
@@ -130,9 +155,6 @@ const double *gridInqXboundsPtr(int gridID);
 const double *gridInqYboundsPtr(int gridID);
 const double *gridInqAreaPtr(int gridID);
 
-const char *gridInqXnamePtr(int gridID);
-const char *gridInqYnamePtr(int gridID);
-
 const char *gridInqReferencePtr(int gridID);
 
 int gridGenerate(const grid_t *grid);
@@ -144,13 +166,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
            int * unpackBufferPos, int originNamespace, void *context,
            int force_id);
 
-struct addIffNewRes
+struct addIfNewRes
 {
   int Id;
   int isNew;
 };
 
-struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode);
+struct addIfNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode);
 
 #endif
 /*
diff --git a/src/make_cdilib b/src/make_cdilib
index 8527d91fe7d43832a7e95753c1421273f85f1978..a936a802cc01df1f7be8ff1989811ee2e045c252 100755
--- a/src/make_cdilib
+++ b/src/make_cdilib
@@ -94,6 +94,8 @@ files="basetime.c \
    calendar.c \
    cdf.c \
    cdf_int.c \
+   cdf_util.c \
+   cdf_lazy_grid.c \
    cdi_cksum.c \
    cdi_error.c \
    cdi_int.c \
@@ -123,10 +125,10 @@ files="basetime.c \
    stream.c \
    stream_write.c \
    stream_read.c \
-   stream_cdf.c \
+   stream_cdf_i.c \
+   stream_cdf_o.c \
    stream_cgribex.c \
    stream_ext.c \
-   stream_fcommon.c \
    stream_grb.c \
    stream_gribapi.c \
    stream_history.c \
@@ -147,7 +149,7 @@ files="basetime.c \
    util.c \
    varscan.c \
    vlist.c \
-   vlist_att.c \
+   cdi_att.c \
    vlist_var.c \
    zaxis.c"
 
diff --git a/src/make_fint.c b/src/make_fint.c
index 45b72da6e34f08098745dd01c5c8ad6dfeccf622..64fdbceaa407d429251db4561bd6fb93611182e3 100644
--- a/src/make_fint.c
+++ b/src/make_fint.c
@@ -15,7 +15,7 @@
 #endif
 
 //#include "config.h"
-#define VERSION "1.7.2"
+#define VERSION "1.8.0"
 typedef struct
 {
   size_t naline;
diff --git a/src/pio_interface.c b/src/pio_interface.c
index da371c63ff0ad3f73a4983bf95146d73cf01e017..37b2f033ae886ea919f708a2aa46b7bb0c9d38ef 100644
--- a/src/pio_interface.c
+++ b/src/pio_interface.c
@@ -2,7 +2,7 @@
 #  include "config.h"
 #endif
 
-#include <limits.h>
+#include <stdint.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -340,7 +340,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos,
   unsigned char *dstBuf = (unsigned char *)buf + pos_,
     *bufEnd = (unsigned char *)buf + size;
   size_t elemSize = p->elemSize;
-  xassert(elemSize <= SSIZE_MAX);
+  xassert(elemSize <= SIZE_MAX);
   const unsigned char *data = p->data;
   unsigned copyCount = 0, numElems = p->numElems;
   for (unsigned j = 0; j < numBlocks && copyCount < numElems; ++j)
@@ -356,7 +356,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos,
             }
           size_t bsize = (size_t)bl * elemSize;
           xassert(dstBuf + bsize <= bufEnd);
-          memcpy(dstBuf, data + (ssize_t)elemSize * (ssize_t)disps[j], bsize);
+          memcpy(dstBuf, data + (size_t)elemSize * (size_t)disps[j], bsize);
           dstBuf += bsize;
         }
     }
diff --git a/src/resource_handle.c b/src/resource_handle.c
index 0685d61798716f5968f5d897b937b3d0c9a3d17e..d282f82d2b6b59230352094fde0ff4a6908666af 100644
--- a/src/resource_handle.c
+++ b/src/resource_handle.c
@@ -379,17 +379,15 @@ static listElem_t *
 reshGetElem(const char *caller, const char* expressionString, cdiResH resH, const resOps *ops)
 {
   listElem_t *listElem;
-  int nsp;
-  namespaceTuple_t nspT;
   xassert ( ops );
 
   LIST_INIT(1);
 
   LIST_LOCK();
 
-  nsp = namespaceGetActive ();
+  int nsp = namespaceGetActive ();
 
-  nspT = namespaceResHDecode ( resH );
+  namespaceTuple_t nspT = namespaceResHDecode ( resH );
   assert(nspT.idx >= 0);
 
   if (nspT.nsp == nsp &&
@@ -583,9 +581,35 @@ void reshPackBufferDestroy ( char ** buffer )
 
 /**************************************************************/
 
+int reshGetTxCode(cdiResH resH)
+{
+  int type = 0;
+
+  LIST_LOCK();
+
+  int nsp = namespaceGetActive ();
+
+  namespaceTuple_t nspT = namespaceResHDecode ( resH );
+  assert(nspT.idx >= 0);
+
+  if (nspT.nsp == nsp &&
+      nspT.idx < resHList[nsp].size)
+    {
+      listElem_t *listElem = resHList[nsp].resources + nspT.idx;
+      xassert ( listElem->res.v.ops );
+      type = listElem->res.v.ops->valTxCode();
+    }
+
+  LIST_UNLOCK();
+
+  return type;
+}
+
+/**************************************************************/
+
 int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
 {
-  int i, packBufferPos = 0;
+  int packBufferPos = 0;
   int end = END;
 
   xassert ( packBuffer );
@@ -603,7 +627,7 @@ int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
   }
 
   listElem_t *r = resHList[nsp].resources;
-  for ( i = 0; i < resHList[nsp].size; i++ )
+  for ( int i = 0; i < resHList[nsp].size; i++ )
     if (r[i].status & RESH_SYNC_BIT)
       {
         if (r[i].status == RESH_DESYNC_DELETED)
@@ -630,6 +654,7 @@ int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
   LIST_UNLOCK();
 
   serializePack(&end, 1,  DATATYPE_INT, pB, pBSize, &packBufferPos, context);
+
   return packBufferPos;
 }
 
diff --git a/src/resource_handle.h b/src/resource_handle.h
index 88264ad4a18c8171c328f5ee67c9d5e164900359..44f8b63f5e9a8dc8bc2c0d06fb9ecabc49e565b7 100644
--- a/src/resource_handle.h
+++ b/src/resource_handle.h
@@ -99,6 +99,7 @@ enum reshListMismatch {
 
 int reshListCompare(int nsp0, int nsp1);
 void reshListPrint(FILE *fp);
+int reshGetTxCode(cdiResH resH);
 
 #endif
 /*
diff --git a/src/stream.c b/src/stream.c
index c6467c288ebc3ffe5cc519461a23bef55b4f1c30..0cc02c1fb3bd09516d6110707eff505c23741e03 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -330,7 +330,7 @@ long cdiInqTimeSize(int streamID)
 }
 
 static
-int cdiInqContents(stream_t * streamptr)
+int cdiInqContents(stream_t *streamptr)
 {
   int status = 0;
 
@@ -593,27 +593,26 @@ int streamOpenID(const char *filename, char filemode, int filetype, int resH)
   return streamID;
 }
 
-static int streamOpen(const char *filename, const char *filemode, int filetype)
+static
+int streamOpen(const char *filename, const char *filemode, int filetype)
 {
   if (!filemode || strlen(filemode) != 1) return CDI_EINVAL;
   return streamOpenID(filename, (char)tolower(filemode[0]),
                       filetype, CDI_UNDEFID);
 }
 
-static int streamOpenA(const char *filename, const char *filemode, int filetype)
+static
+int streamOpenA(const char *filename, const char *filemode, int filetype)
 {
-  int fileID = CDI_UNDEFID;
-  int streamID = CDI_ESYSTEM;
-  int status;
-  stream_t *streamptr = stream_new_entry(CDI_UNDEFID);
-  vlist_t *vlistptr;
-
   if ( CDI_Debug )
     Message("Open %s file (mode=%c); filename: %s", strfiletype(filetype), (int) *filemode, filename);
   if ( CDI_Debug ) printf("streamOpenA: %s\n", filename); // seg fault without this line on thunder/squall with "cdo cat x y"
 
   if ( ! filename || ! filemode || filetype < 0 ) return CDI_EINVAL;
 
+  stream_t *streamptr = stream_new_entry(CDI_UNDEFID);
+  int fileID = CDI_UNDEFID;
+
   {
     int (*streamOpenDelegate)(const char *filename, char filemode,
                               int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
@@ -625,7 +624,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
 
   if ( fileID == CDI_UNDEFID || fileID == CDI_ELIBNAVAIL || fileID == CDI_ESYSTEM ) return fileID;
 
-  streamID = streamptr->self;
+  int streamID = streamptr->self;
 
   streamptr->filemode = tolower(*filemode);
   streamptr->filename = strdupx(filename);
@@ -634,9 +633,9 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
   streamptr->vlistID = vlistCreate();
   cdiVlistMakeInternal(streamptr->vlistID);
   /* cdiReadByteorder(streamID); */
-  status = cdiInqContents(streamptr);
+  int status = cdiInqContents(streamptr);
   if ( status < 0 ) return status;
-  vlistptr = vlist_to_pointer(streamptr->vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
   vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
   if(!strcmp(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID);
 
@@ -655,6 +654,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
     case FILETYPE_GRB2:
       {
         fileID = gribOpen(filename, filemode);
+        if ( fileID != CDI_UNDEFID ) gribContainersNew(streamptr);
 	break;
       }
 #endif
@@ -869,39 +869,40 @@ void streamDefaultValue ( stream_t * streamptr )
   streamptr->vlistID           = CDI_UNDEFID;
   streamptr->globalatts        = 0;
   streamptr->localatts         = 0;
-  streamptr->vct.ilev          = 0;
-  streamptr->vct.mlev          = 0;
-  streamptr->vct.ilevID        = CDI_UNDEFID;
-  streamptr->vct.mlevID        = CDI_UNDEFID;
   streamptr->unreduced         = cdiDataUnreduced;
   streamptr->sortname          = cdiSortName;
   streamptr->have_missval      = cdiHaveMissval;
-  streamptr->comptype          = COMPRESS_NONE;
+  streamptr->comptype          = CDI_COMPRESS_NONE;
   streamptr->complevel         = 0;
 
   basetimeInit(&streamptr->basetime);
 
+#ifdef HAVE_LIBNETCDF
   int i;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i]   = CDI_UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i]   = CDI_UNDEFID;
+  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i]  = CDI_UNDEFID;
+  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i]  = CDI_UNDEFID;
   for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->zaxisID[i]  = CDI_UNDEFID;
   for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->nczvarID[i] = CDI_UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncxvarID[i] = CDI_UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncyvarID[i] = CDI_UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncavarID[i] = CDI_UNDEFID;
+
+  streamptr->ncgrid            = NULL;
+
+  streamptr->vct.ilev          = 0;
+  streamptr->vct.mlev          = 0;
+  streamptr->vct.ilevID        = CDI_UNDEFID;
+  streamptr->vct.mlevID        = CDI_UNDEFID;
+#endif
 
   streamptr->gribContainers    = NULL;
 }
 
-
-static stream_t *stream_new_entry(int resH)
+static
+stream_t *stream_new_entry(int resH)
 {
-  stream_t *streamptr;
-
   cdiInitialize(); /* ***************** make MT version !!! */
 
-  streamptr = (stream_t *) Malloc(sizeof(stream_t));
+  stream_t *streamptr = (stream_t *) Malloc(sizeof(stream_t));
   streamDefaultValue ( streamptr );
+
   if (resH == CDI_UNDEFID)
     streamptr->self = reshPut(streamptr, &streamOps);
   else
@@ -914,8 +915,7 @@ static stream_t *stream_new_entry(int resH)
 }
 
 
-void
-cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
+void cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
 {
   int fileID   = streamptr->fileID;
   int filetype = streamptr->filetype;
@@ -968,6 +968,7 @@ cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
       case FILETYPE_NC4C:
         {
           cdfClose(fileID);
+          if ( streamptr->ncgrid ) { Free(streamptr->ncgrid); streamptr->ncgrid = NULL; }
           break;
         }
 #endif
@@ -980,7 +981,8 @@ cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
 }
 
 
-static void deallocate_sleveltable_t(sleveltable_t *entry)
+static
+void deallocate_sleveltable_t(sleveltable_t *entry)
 {
   if (entry->recordID) Free(entry->recordID);
   if (entry->lindex)   Free(entry->lindex);
@@ -1004,7 +1006,6 @@ The function @func{streamClose} closes an open dataset.
 */
 void streamClose(int streamID)
 {
-  int index;
   stream_t *streamptr = stream_to_pointer(streamID);
 
   if ( CDI_Debug )
@@ -1029,7 +1030,7 @@ void streamClose(int streamID)
   streamptr->filetype = 0;
   if ( streamptr->filename ) Free(streamptr->filename);
 
-  for ( index = 0; index < streamptr->nvars; index++ )
+  for ( int index = 0; index < streamptr->nvars; index++ )
     {
       sleveltable_t *pslev = streamptr->vars[index].recordTable;
       unsigned nsub = streamptr->vars[index].subtypeSize >= 0
@@ -1043,7 +1044,7 @@ void streamClose(int streamID)
   Free(streamptr->vars);
   streamptr->vars = NULL;
 
-  for ( index = 0; index < streamptr->ntsteps; ++index )
+  for ( int index = 0; index < streamptr->ntsteps; ++index )
     {
       if ( streamptr->tsteps[index].records )
         Free(streamptr->tsteps[index].records);
@@ -1070,13 +1071,12 @@ void streamClose(int streamID)
   stream_delete_entry(streamptr);
 }
 
-static void stream_delete_entry(stream_t *streamptr)
+static
+void stream_delete_entry(stream_t *streamptr)
 {
-  int idx;
-
   xassert ( streamptr );
 
-  idx = streamptr->self;
+  int idx = streamptr->self;
   Free( streamptr );
   reshRemove ( idx, &streamOps );
 
@@ -1233,6 +1233,7 @@ int streamDefTimestep(int streamID, int tsID)
   return myStreamDefTimestep_(streamptr, tsID);
 }
 
+
 int streamInqCurTimestepID(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
@@ -1474,8 +1475,7 @@ void streamDefVlist(int streamID, int vlistID)
 }
 
 /* the single image implementation of streamDefVlist */
-void
-cdiStreamDefVlist_(int streamID, int vlistID)
+void cdiStreamDefVlist_(int streamID, int vlistID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
@@ -1581,29 +1581,26 @@ int streamTxCode(void)
   return STREAM;
 }
 
-void
-cdiStreamSetupVlist(stream_t *streamptr, int vlistID)
+void cdiStreamSetupVlist(stream_t *streamptr, int vlistID)
 {
   void (*myStreamSetupVlist)(stream_t *streamptr, int vlistID)
-    = (void (*)(stream_t *, int))
-    namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func;
+    = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func;
   myStreamSetupVlist(streamptr, vlistID);
 }
 
-void
-cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
+
+void cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
 {
-  int nvars = vlistNvars(vlistID);
   streamptr->vlistID = vlistID;
-  for (int varID = 0; varID < nvars; varID++ )
+  int nvars = vlistNvars(vlistID);
+  for ( int varID = 0; varID < nvars; varID++ )
     {
       int gridID    = vlistInqVarGrid(vlistID, varID);
       int zaxisID   = vlistInqVarZaxis(vlistID, varID);
       int tilesetID = vlistInqVarSubtype(vlistID, varID);
       stream_new_var(streamptr, gridID, zaxisID, tilesetID);
       if ( streamptr->have_missval )
-        vlistDefVarMissval(vlistID, varID,
-                           vlistInqVarMissval(vlistID, varID));
+        vlistDefVarMissval(vlistID, varID, vlistInqVarMissval(vlistID, varID));
     }
 
   if (streamptr->filemode == 'w')
@@ -1616,8 +1613,7 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
       case FILETYPE_NC4C:
         {
           void (*myCdfDefVars)(stream_t *streamptr)
-            = (void (*)(stream_t *))
-            namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
+            = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
           myCdfDefVars(streamptr);
         }
         break;
diff --git a/src/stream_cdf.c b/src/stream_cdf.c
deleted file mode 100644
index 90c5a1597b61221bcfd330ae8e38ade004af5077..0000000000000000000000000000000000000000
--- a/src/stream_cdf.c
+++ /dev/null
@@ -1,7180 +0,0 @@
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#ifdef HAVE_LIBNETCDF
-
-//#define TEST_GROUPS 1
-
-#include <limits.h>
-#include <ctype.h>
-#include <math.h>
-#include <float.h>
-#ifdef HAVE_MMAP
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#endif
-#ifdef HAVE_LIBPTHREAD
-#include <pthread.h>
-#endif
-
-#include <netcdf.h>
-
-#include "dmemory.h"
-#include "cdi.h"
-#include "basetime.h"
-#include "gaussgrid.h"
-#include "cdi_int.h"
-#include "cdi_uuid.h"
-#include "stream_cdf.h"
-#include "cdf.h"
-#include "cdf_int.h"
-#include "varscan.h"
-#include "vlist.h"
-#include "zaxis.h"
-
-//#define PROJECTION_TEST
-
-#undef  UNDEFID
-#define UNDEFID  CDI_UNDEFID
-
-static const char bndsName[] = "bnds";
-
-#define  X_AXIS  1
-#define  Y_AXIS  2
-#define  Z_AXIS  3
-#define  T_AXIS  4
-
-#define  POSITIVE_UP    1
-#define  POSITIVE_DOWN  2
-
-typedef struct {
-  int     ncvarid;
-  int     dimtype;
-  size_t  len;
-  char    name[CDI_MAX_NAME];
-}
-ncdim_t;
-#define  MAX_COORDVARS  4
-#define  MAX_AUXVARS    4
-
-typedef struct {
-  int      ncid;
-  int      ignore;
-  short    isvar;
-  short    islon;
-  int      islat;
-  int      islev;
-  int      istime;
-  int      warn;
-  int      tsteptype;
-  int      param;
-  int      code;
-  int      tabnum;
-  int      climatology;
-  int      bounds;
-  int      lformula;
-  int      lformulaterms;
-  int      gridID;
-  int      zaxisID;
-  int      gridtype;
-  int      zaxistype;
-  int      xdim;
-  int      ydim;
-  int      zdim;
-  int      xvarid;
-  int      yvarid;
-  int      zvarid;
-  int      tvarid;
-  int      psvarid;
-  int      p0varid;
-  int      ncoordvars;
-  int      coordvarids[MAX_COORDVARS];
-  int      nauxvars;
-  int      auxvarids[MAX_AUXVARS];
-  int      cellarea;
-  int      calendar;
-  int      tableID;
-  int      truncation;
-  int      position;
-  int      defmissval;
-  int      deffillval;
-  int      xtype;
-  int      ndims;
-  int      gmapid;
-  int      positive;
-  int      dimids[8];
-  int      dimtype[8];
-  int      chunks[8];
-  int      chunked;
-  int      chunktype;
-  int      natts;
-  int      deflate;
-  int      lunsigned;
-  int      lvalidrange;
-  int     *atts;
-  size_t   vctsize;
-  double  *vct;
-  double   missval;
-  double   fillval;
-  double   addoffset;
-  double   scalefactor;
-  double   validrange[2];
-  char     name[CDI_MAX_NAME];
-  char     longname[CDI_MAX_NAME];
-  char     stdname[CDI_MAX_NAME];
-  char     units[CDI_MAX_NAME];
-  char     extra[CDI_MAX_NAME];
-  ensinfo_t   *ensdata;    /* Ensemble information */
-}
-ncvar_t;
-
-static
-void strtolower(char *str)
-{
-  if ( str )
-    for (size_t i = 0; str[i]; ++i)
-      str[i] = (char)tolower((int)str[i]);
-}
-
-static
-int get_timeunit(size_t len, const char *ptu)
-{
-  int timeunit = -1;
-
-  if ( len > 2 )
-    {
-      if      ( memcmp(ptu, "sec",    3) == 0 )          timeunit = TUNIT_SECOND;
-      else if ( memcmp(ptu, "minute", 6) == 0 )          timeunit = TUNIT_MINUTE;
-      else if ( memcmp(ptu, "hour",   4) == 0 )          timeunit = TUNIT_HOUR;
-      else if ( memcmp(ptu, "day",    3) == 0 )          timeunit = TUNIT_DAY;
-      else if ( memcmp(ptu, "month",  5) == 0 )          timeunit = TUNIT_MONTH;
-      else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH;
-      else if ( memcmp(ptu, "year",   4) == 0 )          timeunit = TUNIT_YEAR;
-    }
-  else if ( len == 1 )
-    {
-      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
-    }
-
-  return timeunit;
-}
-
-static
-bool isTimeUnits(const char *timeunits)
-{
-  bool status = strncmp(timeunits, "sec",    3) == 0
-    || strncmp(timeunits, "minute", 6) == 0
-    || strncmp(timeunits, "hour",   4) == 0
-    || strncmp(timeunits, "day",    3) == 0
-    || strncmp(timeunits, "month",  5) == 0;
-  return status;
-}
-
-static
-bool isTimeAxisUnits(const char *timeunits)
-{
-  bool status = false;
-
-  size_t len = strlen(timeunits);
-  char *tu = (char *) Malloc((len+1)*sizeof(char));
-  memcpy(tu, timeunits, (len+1) * sizeof(char));
-  char *ptu = tu;
-
-  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
-
-  int timeunit = get_timeunit(len, ptu);
-  if ( timeunit != -1 )
-    {
-
-      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
-      if ( *ptu )
-        {
-          while ( isspace(*ptu) ) ptu++;
-
-          int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE :
-            memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1;
-
-          status = timetype != -1;
-        }
-    }
-
-  Free(tu);
-
-  return status;
-}
-
-static
-void scanTimeString(const char *ptu, int *rdate, int *rtime)
-{
-  int year = 1, month = 1, day = 1;
-  int hour = 0, minute = 0, second = 0;
-  int v1 = 1, v2 = 1, v3 = 1;
-
-  *rdate = 0;
-  *rtime = 0;
-
-  if ( *ptu )
-    {
-      v1 = atoi(ptu);
-      if ( v1 < 0 ) ptu++;
-      while ( isdigit((int) *ptu) ) ptu++;
-      if ( *ptu )
-        {
-          v2 = atoi(++ptu);
-          while ( isdigit((int) *ptu) ) ptu++;
-          if ( *ptu )
-            {
-              v3 = atoi(++ptu);
-              while ( isdigit((int) *ptu) ) ptu++;
-            }
-        }
-    }
-
-  if ( v3 > 999 && v1 < 32 )
-    { year = v3; month = v2; day = v1; }
-  else
-    { year = v1; month = v2; day = v3; }
-
-  while ( isspace((int) *ptu) ) ptu++;
-
-  if ( *ptu )
-    {
-      while ( ! isdigit((int) *ptu) ) ptu++;
-
-      hour = atoi(ptu);
-      while ( isdigit((int) *ptu) ) ptu++;
-      if ( *ptu == ':' )
-        {
-          ptu++;
-          minute = atoi(ptu);
-          while ( isdigit((int) *ptu) ) ptu++;
-          if ( *ptu == ':' )
-            {
-              ptu++;
-              second = atoi(ptu);
-            }
-        }
-    }
-
-  *rdate = cdiEncodeDate(year, month, day);
-  *rtime = cdiEncodeTime(hour, minute, second);
-}
-
-static
-int scanTimeUnit(const char *unitstr)
-{
-  size_t len = strlen(unitstr);
-  int timeunit = get_timeunit(len, unitstr);
-  if ( timeunit == -1 )
-    Message("Unsupported TIMEUNIT: %s!", unitstr);
-
-  return timeunit;
-}
-
-static
-void setForecastTime(const char *timestr, taxis_t *taxis)
-{
-  (*taxis).fdate = 0;
-  (*taxis).ftime = 0;
-
-  int len = (int) strlen(timestr);
-  if ( len == 0 ) return;
-
-  int fdate = 0, ftime = 0;
-  scanTimeString(timestr, &fdate, &ftime);
-
-  (*taxis).fdate = fdate;
-  (*taxis).ftime = ftime;
-}
-
-static
-int setBaseTime(const char *timeunits, taxis_t *taxis)
-{
-  int timetype = TAXIS_ABSOLUTE;
-  int rdate = -1, rtime = -1;
-
-  size_t len = strlen(timeunits);
-  char *tu = (char *) Malloc((len+1) * sizeof (char));
-  memcpy(tu, timeunits, (len+1) * sizeof (char));
-  char *ptu = tu;
-
-  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
-
-  int timeunit = get_timeunit(len, ptu);
-  if ( timeunit == -1 )
-    {
-      Message("Unsupported TIMEUNIT: %s!", timeunits);
-      return (1);
-    }
-
-  while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
-  if ( *ptu )
-    {
-      while ( isspace(*ptu) ) ptu++;
-
-      if ( memcmp(ptu, "as", 2) == 0 )
-        timetype = TAXIS_ABSOLUTE;
-      else if ( memcmp(ptu, "since", 5) == 0 )
-        timetype = TAXIS_RELATIVE;
-
-      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
-      if ( *ptu )
-        {
-          while ( isspace(*ptu) ) ptu++;
-
-          if ( timetype == TAXIS_ABSOLUTE )
-            {
-              if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
-                {
-                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
-                  timeunit = -1;
-                }
-              else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
-                {
-                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
-                  timeunit = -1;
-                }
-            }
-          else if ( timetype == TAXIS_RELATIVE )
-            {
-              scanTimeString(ptu, &rdate, &rtime);
-
-              (*taxis).rdate = rdate;
-              (*taxis).rtime = rtime;
-
-              if ( CDI_Debug )
-                Message("rdate = %d  rtime = %d", rdate, rtime);
-            }
-        }
-    }
-
-  (*taxis).type = timetype;
-  (*taxis).unit = timeunit;
-
-  Free(tu);
-
-  if ( CDI_Debug )
-    Message("timetype = %d  unit = %d", timetype, timeunit);
-
-  return 0;
-}
-
-static
-void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint)
-{
-  nc_type atttype;
-  size_t nc_attlen;
-
-  *attint = 0;
-
-  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
-  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
-
-  if ( atttype != NC_CHAR )
-    {
-      int *pintatt = (int)nc_attlen > attlen
-        ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint;
-
-      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
-
-      if ( (int)nc_attlen > attlen )
-        {
-          memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
-          Free(pintatt);
-        }
-    }
-}
-
-static
-void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
-{
-  nc_type atttype;
-  size_t nc_attlen;
-
-  *attdouble = 0;
-
-  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
-  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
-
-  if ( atttype != NC_CHAR )
-    {
-      double *pdoubleatt = NULL;
-
-      if ( (int)nc_attlen > attlen )
-        pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
-      else
-        pdoubleatt = attdouble;
-
-      cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);
-
-      if ( (int)nc_attlen > attlen )
-        {
-          memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
-          Free(pdoubleatt);
-        }
-    }
-}
-
-static
-void cdfGetAttText(int fileID, int ncvarid,const char *attname, int attlen, char *atttext)
-{
-  nc_type atttype;
-  size_t nc_attlen;
-
-  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
-  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
-
-  if ( atttype == NC_CHAR )
-    {
-      char attbuf[65636];
-      if ( nc_attlen < sizeof(attbuf) )
-        {
-          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
-
-          if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
-
-          attbuf[nc_attlen++] = 0;
-          memcpy(atttext, attbuf, nc_attlen);
-        }
-      else
-        {
-          atttext[0] = 0;
-        }
-    }
-#if  defined  (HAVE_NETCDF4)
-  else if ( atttype == NC_STRING )
-    {
-      if ( nc_attlen == 1 )
-        {
-          char *attbuf = NULL;
-          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
-
-          size_t ssize = strlen(attbuf) + 1;
-
-          if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
-          memcpy(atttext, attbuf, ssize);
-          atttext[ssize - 1] = 0;
-          Free(attbuf);
-        }
-      else
-        {
-          atttext[0] = 0;
-        }
-    }
-#endif
-}
-
-static
-int xtypeIsText(int xtype)
-{
-  int isText = FALSE;
-
-  if ( xtype == NC_CHAR )
-    isText = TRUE;
-#if  defined  (HAVE_NETCDF4)
-  else if ( xtype == NC_STRING )
-    isText = TRUE;
-#endif
-
-  return isText;
-}
-
-static
-int xtypeIsFloat(int xtype)
-{
-  int isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE;
-  return isFloat;
-}
-
-static
-int cdfInqDatatype(int xtype, int lunsigned)
-{
-  int datatype = -1;
-
-#if  defined  (HAVE_NETCDF4)
-  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
-#endif
-
-  if      ( xtype == NC_BYTE   )  datatype = DATATYPE_INT8;
-  /* else if ( xtype == NC_CHAR   )  datatype = DATATYPE_UINT8; */
-  else if ( xtype == NC_SHORT  )  datatype = DATATYPE_INT16;
-  else if ( xtype == NC_INT    )  datatype = DATATYPE_INT32;
-  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
-  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
-#if  defined  (HAVE_NETCDF4)
-  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
-  else if ( xtype == NC_LONG   )  datatype = DATATYPE_INT32;
-  else if ( xtype == NC_USHORT )  datatype = DATATYPE_UINT16;
-  else if ( xtype == NC_UINT   )  datatype = DATATYPE_UINT32;
-  else if ( xtype == NC_INT64  )  datatype = DATATYPE_FLT64;
-  else if ( xtype == NC_UINT64 )  datatype = DATATYPE_FLT64;
-#endif
-
-  return datatype;
-}
-
-
-void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
-{
-  int vlistID1 = streamptr1->vlistID;
-  int tsID     = streamptr1->curTsID;
-  int vrecID   = streamptr1->tsteps[tsID].curRecID;
-  int recID    = streamptr1->tsteps[tsID].recIDs[vrecID];
-  int ivarID   = streamptr1->tsteps[tsID].records[recID].varID;
-  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
-  int datasize = gridInqSize(gridID);
-  int datatype = vlistInqVarDatatype(vlistID1, ivarID);
-  int memtype  = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT;
-
-  void *data
-    = Malloc((size_t)datasize
-             * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float)));
-
-  int nmiss;
-  cdf_read_record(streamptr1, memtype, data, &nmiss);
-  cdf_write_record(streamptr2, memtype, data, nmiss);
-
-  Free(data);
-}
-
-/* not used
-int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
-{
-  int tsID, recID;
-
-  recID = streamptr->tsteps[0].curRecID++;
-  printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
-  printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
-
-  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
-    {
-      streamptr->tsteps[0].curRecID = 0;
-    }
-
-  *varID   = streamptr->tsteps[0].records[recID].varID;
-  *levelID = streamptr->tsteps[0].records[recID].levelID;
-
-  streamptr->record->varID   = *varID;
-  streamptr->record->levelID = *levelID;
-
-  if ( CDI_Debug )
-    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
-
-  return (recID+1);
-}
-*/
-
-
-void cdfDefRecord(stream_t *streamptr)
-{
-  (void)streamptr;
-}
-
-#if defined(NC_SZIP_NN_OPTION_MASK)
-static
-void cdfDefVarSzip(int ncid, int ncvarid)
-{
-  int retval;
-  /* Set options_mask and bits_per_pixel. */
-  int options_mask = NC_SZIP_NN_OPTION_MASK;
-  int bits_per_pixel = 16;
-
-  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
-    {
-      if ( retval == NC_EINVAL )
-        {
-          static int lwarn = TRUE;
-
-          if ( lwarn )
-            {
-              lwarn = FALSE;
-              Warning("NetCDF4/Szip compression not compiled in!");
-            }
-        }
-      else
-        Error("nc_def_var_szip failed, status = %d", retval);
-    }
-}
-#endif
-
-static
-void cdfDefTimeValue(stream_t *streamptr, int tsID)
-{
-  int fileID = streamptr->fileID;
-
-  if ( CDI_Debug )
-    Message("streamID = %d, fileID = %d", streamptr->self, fileID);
-
-  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
-
-  if ( streamptr->ncmode == 1 )
-    {
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  size_t index = (size_t)tsID;
-
-  double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
-  if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
-
-  int ncvarid = streamptr->basetime.ncvarid;
-  cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
-
-  if ( taxis->has_bounds )
-    {
-      size_t start[2], count[2];
-
-      ncvarid = streamptr->basetime.ncvarboundsid;
-
-      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
-      start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
-      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
-
-      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
-      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
-      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
-    }
-
-  ncvarid = streamptr->basetime.leadtimeid;
-  if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
-    {
-      timevalue = taxis->fc_period;
-      cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
-    }
-
-  /*
-printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
-  */
-}
-
-static
-int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis)
-{
-  int time_bndsid = -1;
-  int dims[2];
-
-  dims[0] = nctimedimid;
-
-  /* fprintf(stderr, "time has bounds\n"); */
-
-  if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR )
-    cdf_def_dim(fileID, bndsName, 2, &dims[1]);
-
-  const char *bndsAttName, *bndsAttVal;
-  size_t bndsAttValLen;
-  char tmpstr[CDI_MAX_NAME];
-  if ( taxis->climatology )
-    {
-      static const char climatology_bndsName[] = "climatology_bnds",
-        climatology_bndsAttName[] = "climatology";
-      bndsAttName = climatology_bndsAttName;
-      bndsAttValLen = sizeof (climatology_bndsName) - 1;
-      bndsAttVal = climatology_bndsName;
-    }
-  else
-    {
-      size_t taxisnameLen = strlen(taxis_name);
-      memcpy(tmpstr, taxis_name, taxisnameLen);
-      tmpstr[taxisnameLen] = '_';
-      memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName));
-      size_t tmpstrLen = taxisnameLen + sizeof (bndsName);
-      static const char generic_bndsAttName[] = "bounds";
-      bndsAttName = generic_bndsAttName;
-      bndsAttValLen = tmpstrLen;
-      bndsAttVal = tmpstr;
-    }
-  cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid);
-  cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal);
-
-  return (time_bndsid);
-}
-
-static
-void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
-{
-  unitstr[0] = 0;
-
-  if ( taxis0->type == TAXIS_ABSOLUTE )
-    {
-      if ( taxis0->unit == TUNIT_YEAR )
-        sprintf(unitstr, "year as %s", "%Y.%f");
-      else if ( taxis0->unit == TUNIT_MONTH )
-        sprintf(unitstr, "month as %s", "%Y%m.%f");
-      else
-        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
-    }
-  else
-    {
-      int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
-      int rdate    = taxis->rdate;
-      int rtime    = taxis->rtime;
-      if ( rdate == -1 )
-        {
-          rdate  = taxis->vdate;
-          rtime  = taxis->vtime;
-        }
-
-      int year, month, day, hour, minute, second;
-      cdiDecodeDate(rdate, &year, &month, &day);
-      cdiDecodeTime(rtime, &hour, &minute, &second);
-
-      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
-      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
-      if ( timeunit == TUNIT_3HOURS  ||
-	   timeunit == TUNIT_6HOURS  ||
-	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
-
-      sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
-              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
-    }
-}
-
-static
-void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
-{
-  unitstr[0] = 0;
-
-  if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
-
-  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
-  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
-  if ( timeunit == TUNIT_3HOURS  ||
-       timeunit == TUNIT_6HOURS  ||
-       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
-
-  strcpy(unitstr, tunitNamePtr(timeunit));
-}
-
-static
-void cdfDefCalendar(int fileID, int ncvarid, int calendar)
-{
-  static const struct { int calCode; const char *calStr; } calTab[] = {
-    { CALENDAR_STANDARD, "standard" },
-    { CALENDAR_PROLEPTIC, "proleptic_gregorian" },
-    { CALENDAR_NONE, "none" },
-    { CALENDAR_360DAYS, "360_day" },
-    { CALENDAR_365DAYS, "365_day" },
-    { CALENDAR_366DAYS, "366_day" },
-  };
-  enum { calTabSize = sizeof calTab / sizeof calTab[0] };
-
-  for (size_t i = 0; i < calTabSize; ++i)
-    if (calTab[i].calCode == calendar)
-      {
-        const char *calstr = calTab[i].calStr;
-        size_t len = strlen(calstr);
-        cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
-        break;
-      }
-}
-
-
-void cdfDefTime(stream_t* streamptr)
-{
-  int time_varid;
-  int time_dimid;
-  int time_bndsid = -1;
-  static const char default_name[] = "time";
-
-  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
-
-  int fileID = streamptr->fileID;
-
-  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
-  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-  taxis_t *taxis = &streamptr->tsteps[0].taxis;
-
-  const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ;
-
-  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
-  streamptr->basetime.ncdimid = time_dimid;
-
-  cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid);
-
-  streamptr->basetime.ncvarid = time_varid;
-
-  {
-    static const char timeStr[] = "time";
-    cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr);
-  }
-
-  if ( taxis->longname && taxis->longname[0] )
-    cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);
-
-  if ( taxis->has_bounds )
-    {
-      time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
-      streamptr->basetime.ncvarboundsid = time_bndsid;
-    }
-
-  {
-    char unitstr[CDI_MAX_NAME];
-    cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
-    size_t len = strlen(unitstr);
-    if ( len )
-      {
-        cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
-        /*
-          if ( taxis->has_bounds )
-          cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
-        */
-      }
-  }
-
-  if ( taxis->calendar != -1 )
-    {
-      cdfDefCalendar(fileID, time_varid, taxis->calendar);
-      /*
-      if ( taxis->has_bounds )
-        cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
-      */
-    }
-
-  if ( taxis->type == TAXIS_FORECAST )
-    {
-      int leadtimeid;
-
-      cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid);
-
-      streamptr->basetime.leadtimeid = leadtimeid;
-
-      {
-        static const char stdname[] = "forecast_period";
-        cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname);
-      }
-
-      {
-        static const char lname[] = "Time elapsed since the start of the forecast";
-        cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname);
-      }
-
-      {
-          char unitstr[CDI_MAX_NAME];
-          cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
-          size_t len = strlen(unitstr);
-          if ( len )
-            cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
-      }
-    }
-
-  cdf_put_att_text(fileID, time_varid, "axis", 1, "T");
-
-  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
-}
-
-
-void cdfDefTimestep(stream_t *streamptr, int tsID)
-{
-  int vlistID = streamptr->vlistID;
-
-  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
-  cdfDefTimeValue(streamptr, tsID);
-}
-
-static
-void cdfDefComplex(stream_t *streamptr, int gridID)
-{
-  static const char axisname[] = "nc2";
-  int dimID = UNDEFID;
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  for ( int index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
-            {
-              dimID = streamptr->xdimID[index];
-              break;
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      size_t dimlen = 2;
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->xdimID[gridindex] = dimID;
-}
-
-static void
-cdfDefSPorFC(stream_t *streamptr, int gridID,
-             char *restrict axisname, int gridRefType)
-{
-  int index, iz = 0;
-  int dimID = UNDEFID;
-
-  int vlistID = streamptr->vlistID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID)/2;
-
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->ydimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == gridRefType )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
-              if ( dimlen == dimlen0 )
-                {
-                  dimID = streamptr->ydimID[index];
-                  break;
-                }
-              else
-                iz++;
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      int fileID  = streamptr->fileID;
-      if ( iz == 0 ) axisname[3] = '\0';
-      else           sprintf(&axisname[3], "%1d", iz+1);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->ydimID[gridindex] = dimID;
-}
-
-static
-void cdfDefSP(stream_t *streamptr, int gridID)
-{
-  /*
-  char longname[] = "Spherical harmonic coefficient";
-  */
-  char axisname[5] = "nspX";
-  cdfDefSPorFC(streamptr, gridID, axisname, GRID_SPECTRAL);
-}
-
-
-static
-void cdfDefFC(stream_t *streamptr, int gridID)
-{
-  char axisname[5] = "nfcX";
-  cdfDefSPorFC(streamptr, gridID, axisname, GRID_FOURIER);
-}
-
-static const struct cdfDefGridAxisInqs {
-  int (*axisSize)(int gridID);
-  void (*axisName)(int gridID, char *dimname);
-  const char *(*axisNamePtr)(int gridID);
-  void (*axisStdname)(int gridID, char *dimstdname);
-  void (*axisLongname)(int gridID, char *dimlongname);
-  void (*axisUnits)(int gridID, char *dimunits);
-  double (*axisVal)(int gridID, int index);
-  const double *(*axisValsPtr)(int gridID);
-  const double *(*axisBoundsPtr)(int gridID);
-} gridInqsX = {
-  .axisSize = gridInqXsize,
-  .axisName = gridInqXname,
-  .axisNamePtr = gridInqXnamePtr,
-  .axisStdname = gridInqXstdname,
-  .axisLongname = gridInqXlongname,
-  .axisUnits = gridInqXunits,
-  .axisVal = gridInqXval,
-  .axisValsPtr = gridInqXvalsPtr,
-  .axisBoundsPtr = gridInqXboundsPtr,
-}, gridInqsY = {
-  .axisSize = gridInqYsize,
-  .axisName = gridInqYname,
-  .axisNamePtr = gridInqYnamePtr,
-  .axisStdname = gridInqYstdname,
-  .axisLongname = gridInqYlongname,
-  .axisUnits = gridInqYunits,
-  .axisVal = gridInqYval,
-  .axisValsPtr = gridInqYvalsPtr,
-  .axisBoundsPtr = gridInqYboundsPtr,
-}, gridInqsZ = {
-  .axisStdname = zaxisInqStdname,
-  .axisLongname = zaxisInqLongname,
-  .axisUnits = zaxisInqUnits,
-};
-
-static void
-cdfPutGridStdAtts(int fileID, int ncvarid,
-                  int gridID, const struct cdfDefGridAxisInqs *inqs)
-{
-  size_t len;
-  {
-    char stdname[CDI_MAX_NAME];
-    inqs->axisStdname(gridID, stdname);
-    if ( (len = strlen(stdname)) )
-      cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
-  }
-  {
-    char longname[CDI_MAX_NAME];
-    inqs->axisLongname(gridID, longname);
-    if ( (len = strlen(longname)) )
-      cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
-  }
-  {
-    char units[CDI_MAX_NAME];
-    inqs->axisUnits(gridID, units);
-    if ( (len = strlen(units)) )
-      cdf_put_att_text(fileID, ncvarid, "units", len, units);
-  }
-}
-
-static void
-cdfDefTrajLatLon(stream_t *streamptr, int gridID,
-                 const struct cdfDefGridAxisInqs *inqs,
-                 int *dimID, const char *sizeName)
-{
-  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
-
-  int vlistID = streamptr->vlistID;
-  int dimlen = inqs->axisSize(gridID);
-  if ( dimlen != 1 )
-    Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID)));
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  int ncvarid = dimID[gridindex];
-
-  if ( ncvarid == UNDEFID )
-    {
-      int dimNcID = streamptr->basetime.ncvarid;
-      int fileID  = streamptr->fileID;
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      const char *axisname = inqs->axisNamePtr(gridID);
-      cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
-      cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs);
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  dimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
-}
-
-static
-void cdfDefTrajLon(stream_t *streamptr, int gridID)
-{
-  cdfDefTrajLatLon(streamptr, gridID, &gridInqsX, streamptr->xdimID, "Xsize");
-}
-
-
-static
-void cdfDefTrajLat(stream_t *streamptr, int gridID)
-{
-  cdfDefTrajLatLon(streamptr, gridID, &gridInqsY, streamptr->ydimID, "Ysize");
-}
-
-static
-int checkDimName(int fileID, size_t dimlen, char *dimname)
-{
-  /* check whether the dimenion name is already defined with the same length */
-  unsigned iz = 0;
-  int dimid = UNDEFID;
-  char name[CDI_MAX_NAME];
-
-  size_t len = strlen(dimname);
-  memcpy(name, dimname, len + 1);
-
-  do
-    {
-      if ( iz ) sprintf(name + len, "_%u", iz+1);
-
-      int dimid0, status = nc_inq_dimid(fileID, name, &dimid0);
-      if ( status != NC_NOERR )
-        break;
-      size_t dimlen0;
-      cdf_inq_dimlen(fileID, dimid0, &dimlen0);
-      if ( dimlen0 == dimlen )
-        {
-          dimid = dimid0;
-          break;
-        }
-      iz++;
-    }
-  while ( iz <= 99 );
-
-
-  if ( iz ) sprintf(dimname + len, "_%u", iz+1);
-
-  return dimid;
-}
-
-static
-void checkGridName(char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
-{
-  int ncdimid;
-  char axisname2[CDI_MAX_NAME];
-
-  /* check that the name is not already defined */
-  unsigned iz = 0;
-
-  size_t axisnameLen = strlen(axisname);
-  memcpy(axisname2, axisname, axisnameLen + 1);
-  do
-    {
-      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
-
-      int status = nc_inq_varid(fileID, axisname2, &ncdimid);
-
-      if ( status != NC_NOERR )
-        {
-          if ( iz )
-            {
-              /* check that the name does not exist for other grids */
-              for ( int index = 0; index < ngrids; index++ )
-                {
-                  int gridID0 = vlistGrid(vlistID, index);
-                  if ( gridID != gridID0 )
-                    {
-                       /* mode X or Y */
-                      const char *(*query)(int)
-                        = mode == 'X' ? gridInqXnamePtr : gridInqYnamePtr;
-                      const char *axisname0 = query(gridID0);
-                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
-                    }
-                }
-            }
-          break;
-        }
-      nextSuffix:
-      ++iz;
-    }
-  while ( iz <= 99 );
-
-
-  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
-}
-
-static
-int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis)
-{
-  char axisname2[CDI_MAX_NAME];
-
-  /* check that the name is not already defined */
-  unsigned iz = 0;
-
-  size_t axisnameLen = strlen(axisname);
-  memcpy(axisname2, axisname, axisnameLen + 1);
-  do
-    {
-      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
-
-      int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid);
-
-      if ( status != NC_NOERR )
-        {
-          if ( iz )
-            {
-              /* check that the name does not exist for other zaxes */
-              for ( int index = 0; index < nzaxis; index++ )
-                {
-                  int zaxisID0 = vlistZaxis(vlistID, index);
-                  if ( zaxisID != zaxisID0 )
-                    {
-                      const char *axisname0 = zaxisInqNamePtr(zaxisID0);
-                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
-                    }
-                }
-            }
-          break;
-        }
-      nextSuffix:
-      ++iz;
-    }
-  while (iz <= 99);
-
-
-  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
-
-  return (int)iz;
-}
-
-static void
-cdfDefAxisCommon(stream_t *streamptr, int gridID, int ndims,
-                 const struct cdfDefGridAxisInqs *gridAxisInq,
-                 int *axisDimIDs, int dimKey, char axisLetter,
-                 void (*finishCyclicBounds)(double *pbounds, size_t dimlen,
-                                            const double *pvals),
-                 int *ncAxisVarIDs)
-{
-  int dimID = UNDEFID;
-  int ngrids = 0;
-  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  if ( ndims ) ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridAxisInq->axisSize(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
-
-  const char *axisname = gridAxisInq->axisNamePtr(gridID);
-  size_t axisnameLen = strlen(axisname);
-
-  if ( axisname[0] == 0 ) Error("axis name undefined!");
-
-  for ( int index = 0; index < ngrids; index++ )
-    {
-      if ( axisDimIDs[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN    ||
-               gridtype0 == GRID_LONLAT      ||
-               gridtype0 == GRID_CURVILINEAR ||
-               gridtype0 == GRID_GENERIC )
-            {
-              size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0);
-              if ( dimlen == dimlen0 )
-                {
-                  double (*inqVal)(int gridID, int index)
-                    = gridAxisInq->axisVal;
-                  if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) &&
-                       IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) )
-                  {
-                    dimID = axisDimIDs[index];
-                    break;
-                  }
-                }
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      const double *pvals = gridAxisInq->axisValsPtr(gridID);
-
-      /* enough to append _ plus up to 100 decimal and trailing \0 */
-      char extendedAxisname[axisnameLen + 4 + 1];
-      memcpy(extendedAxisname, axisname, axisnameLen + 1);
-      checkGridName(extendedAxisname, fileID, vlistID, gridID, ngrids, axisLetter);
-      size_t extendedAxisnameLen
-        = axisnameLen + strlen(extendedAxisname + axisnameLen);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      if ( ndims )
-        {
-          char dimname[CDI_MAX_NAME+3];
-          dimname[0] = 0;
-
-          if ( pvals == NULL )
-            cdiGridInqString(gridID, dimKey, CDI_MAX_NAME, dimname);
-
-          if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname);
-          dimID = checkDimName(fileID, dimlen, dimname);
-
-          if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
-        }
-
-      bool gen_bounds = false;
-      int grid_is_cyclic = gridIsCircular(gridID);
-      double *pbounds = NULL;
-      if ( pvals )
-        {
-          cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid);
-
-          cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq);
-          {
-            char axisStr[2] = { axisLetter, '\0' };
-            cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr);
-          }
-
-          pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID);
-
-          if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
-            {
-              gen_bounds = true;
-              pbounds = (double*) Malloc(2*dimlen*sizeof(double));
-              for ( size_t i = 0; i < dimlen-1; ++i )
-                {
-                  pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
-                  pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
-                }
-              finishCyclicBounds(pbounds, dimlen, pvals);
-            }
-          if ( pbounds )
-            {
-              size_t nvertex = 2;
-              if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
-                cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
-            }
-          if ( pbounds && nvdimID != UNDEFID )
-            {
-              char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)];
-              memcpy(boundsname, axisname, extendedAxisnameLen);
-              boundsname[extendedAxisnameLen] = '_';
-              memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName);
-              int dimIDs[2] = { dimID, nvdimID };
-              cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid);
-              cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname);
-            }
-        }
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      if ( ncvarid  != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
-      if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
-      if ( gen_bounds ) Free(pbounds);
-
-      if ( ndims == 0 ) ncAxisVarIDs[gridindex] = ncvarid;
-    }
-
-  axisDimIDs[gridindex] = dimID;
-}
-
-static void
-finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals)
-{
-  pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5;
-  pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5;
-}
-
-static
-void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
-{
-  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsX, streamptr->xdimID,
-                   CDI_GRID_XDIMNAME, 'X', finishCyclicXBounds,
-                   streamptr->ncxvarID);
-}
-
-static void
-finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals)
-{
-  pbounds[0] = copysign(90.0, pvals[0]);
-  pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]);
-}
-
-static
-void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
-{
-  cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsY, streamptr->ydimID,
-                   CDI_GRID_YDIMNAME, 'Y', finishCyclicYBounds,
-                   streamptr->ncyvarID);
-}
-
-static
-void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype)
-{
-#if  defined  (HAVE_NETCDF4)
-  if ( gridsize > 1 && comptype == COMPRESS_ZIP && (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) )
-    {
-      nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
-      cdfDefVarDeflate(fileID, ncvarid, 1);
-    }
-#endif
-}
-
-static
-void cdfDefCurvilinear(stream_t *streamptr, int gridID)
-{
-  int xdimID = UNDEFID;
-  int ydimID = UNDEFID;
-  int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
-  int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID);
-  size_t xdimlen = (size_t)gridInqXsize(gridID);
-  size_t ydimlen = (size_t)gridInqYsize(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
-
-  for ( int index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_CURVILINEAR )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0);
-              if ( dimlen == dimlen0 )
-                if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
-                     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
-                  {
-                    xdimID = streamptr->xdimID[index];
-                    ydimID = streamptr->ydimID[index];
-                    ncxvarid = streamptr->ncxvarID[index];
-                    ncyvarid = streamptr->ncyvarID[index];
-                    break;
-                  }
-            }
-        }
-    }
-
-  if ( xdimID == UNDEFID || ydimID == UNDEFID )
-    {
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-      {
-        char xdimname[CDI_MAX_NAME+3];
-        xdimname[0] = 0;
-        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
-        if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; }
-        xdimID = checkDimName(fileID, xdimlen, xdimname);
-        if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
-      }
-      {
-        char ydimname[CDI_MAX_NAME+3];
-        ydimname[0] = 0;
-        cdiGridInqString(gridID, CDI_GRID_YDIMNAME, CDI_MAX_NAME, ydimname);
-        if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; }
-        ydimID = checkDimName(fileID, ydimlen, ydimname);
-        if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
-      }
-
-      int nvdimID = UNDEFID;
-      int dimIDs[3];
-      if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
-        {
-          char vdimname[CDI_MAX_NAME+3];
-          vdimname[0] = 0;
-          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
-          if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4");
-          size_t nvertex = 4;
-          nvdimID = checkDimName(fileID, nvertex, vdimname);
-          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
-        }
-
-      dimIDs[0] = ydimID;
-      dimIDs[1] = xdimID;
-      dimIDs[2] = nvdimID;
-
-      if ( gridInqXvalsPtr(gridID) )
-        {
-          char xaxisname[CDI_MAX_NAME];
-          gridInqXname(gridID, xaxisname);
-          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-
-          cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
-
-          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
-
-          /* attribute for Panoply */
-          cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon");
-
-          if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
-            {
-              size_t xaxisnameLen = strlen(xaxisname);
-              xaxisname[xaxisnameLen] = '_';
-              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
-              cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
-
-              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
-            }
-        }
-
-      if ( gridInqYvalsPtr(gridID) )
-        {
-          char yaxisname[CDI_MAX_NAME];
-          gridInqYname(gridID, yaxisname);
-          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-
-          cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
-
-          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
-
-          /* attribute for Panoply */
-          cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat");
-
-          if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
-            {
-              size_t yaxisnameLen = strlen(yaxisname);
-              yaxisname[yaxisnameLen] = '_';
-              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
-              cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
-
-              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
-            }
-        }
-
-      if ( gridInqAreaPtr(gridID) )
-        {
-          static const char yaxisname_[] = "cell_area";
-          static const char units[] = "m2";
-          static const char longname[] = "area of grid cell";
-          static const char stdname[] = "cell_area";
-
-          cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid);
-
-          cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
-          cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
-          cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units);
-        }
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      if ( ncxvarid  != UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  gridInqXvalsPtr(gridID));
-      if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID));
-      if ( ncyvarid  != UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  gridInqYvalsPtr(gridID));
-      if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID));
-      if ( ncavarid  != UNDEFID ) cdf_put_var_double(fileID, ncavarid,  gridInqAreaPtr(gridID));
-    }
-
-  streamptr->xdimID[gridindex] = xdimID;
-  streamptr->ydimID[gridindex] = ydimID;
-  streamptr->ncxvarID[gridindex] = ncxvarid;
-  streamptr->ncyvarID[gridindex] = ncyvarid;
-  streamptr->ncavarID[gridindex] = ncavarid;
-}
-
-static
-void cdfDefRgrid(stream_t *streamptr, int gridID)
-{
-  int dimID = UNDEFID;
-
-  int vlistID = streamptr->vlistID;
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID);
-
-  int iz = 0;
-  for ( int index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0);
-
-              if ( dimlen == dimlen0 )
-                {
-                  dimID = streamptr->xdimID[index];
-                  break;
-                }
-              iz++;
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      int fileID  = streamptr->fileID;
-      static bool lwarn = true;
-      if ( lwarn )
-        {
-          Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
-          Warning("The further processing of the resulting file is unsupported!");
-          lwarn = false;
-        }
-
-      char axisname[7] = "rgridX";
-      if ( iz == 0 ) axisname[5] = '\0';
-      else           sprintf(&axisname[5], "%1d", iz+1);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->xdimID[gridindex] = dimID;
-}
-
-static
-void cdfDefGdim(stream_t *streamptr, int gridID)
-{
-  int iz = 0;
-  int dimID = UNDEFID;
-
-  int vlistID = streamptr->vlistID;
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID);
-
-  if ( gridInqYsize(gridID) == 0 )
-    for ( int index = 0; index < ngrids; index++ )
-      {
-        if ( streamptr->xdimID[index] != UNDEFID )
-          {
-            int gridID0 = vlistGrid(vlistID, index);
-            int gridtype0 = gridInqType(gridID0);
-            if ( gridtype0 == GRID_GENERIC )
-              {
-                size_t dimlen0 = (size_t)gridInqSize(gridID0);
-                if ( dimlen == dimlen0 )
-                  {
-                    dimID = streamptr->xdimID[index];
-                    break;
-                  }
-                else
-                  iz++;
-              }
-          }
-      }
-
-  if ( gridInqXsize(gridID) == 0 )
-    for ( int index = 0; index < ngrids; index++ )
-      {
-        if ( streamptr->ydimID[index] != UNDEFID )
-          {
-            int gridID0 = vlistGrid(vlistID, index);
-            int gridtype0 = gridInqType(gridID0);
-            if ( gridtype0 == GRID_GENERIC )
-              {
-                size_t dimlen0 = (size_t)gridInqSize(gridID0);
-                if ( dimlen == dimlen0 )
-                  {
-                    dimID = streamptr->ydimID[index];
-                    break;
-                  }
-                else
-                  iz++;
-              }
-          }
-      }
-
-  if ( dimID == UNDEFID )
-    {
-      int fileID  = streamptr->fileID;
-      char dimname[CDI_MAX_NAME];
-      strcpy(dimname, "gsize");
-
-      dimID = checkDimName(fileID, dimlen, dimname);
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-    }
-
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  streamptr->xdimID[gridindex] = dimID;
-}
-
-static
-void cdfDefGridReference(stream_t *streamptr, int gridID)
-{
-  int fileID  = streamptr->fileID;
-  int number = gridInqNumber(gridID);
-
-  if ( number > 0 )
-    {
-      cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number);
-    }
-
-  const char *gridfile = gridInqReferencePtr(gridID);
-  if ( gridfile && gridfile[0] != 0 )
-    cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
-}
-
-static
-void cdfDefGridUUID(stream_t *streamptr, int gridID)
-{
-  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
-
-  gridInqUUID(gridID, uuidOfHGrid);
-  if ( !cdiUUIDIsNull(uuidOfHGrid) )
-    {
-      char uuidOfHGridStr[37];
-      cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
-      if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
-        {
-          int fileID  = streamptr->fileID;
-          //if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-          cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfHGrid", 36, uuidOfHGridStr);
-          //if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
-        }
-    }
-}
-
-static
-void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
-{
-  unsigned char uuidOfVGrid[CDI_UUID_SIZE];
-  zaxisInqUUID(zaxisID, uuidOfVGrid);
-
-  if ( uuidOfVGrid[0] != 0 )
-    {
-      char uuidOfVGridStr[37];
-      cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
-      if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
-        {
-          int fileID  = streamptr->fileID;
-          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-          cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfVGrid", 36, uuidOfVGridStr);
-          if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
-        }
-    }
-}
-
-static
-void cdfDefUnstructured(stream_t *streamptr, int gridID)
-{
-  int dimID = UNDEFID;
-  int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
-  int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  nc_type xtype = NC_DOUBLE;
-
-  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int ngrids = vlistNgrids(vlistID);
-
-  size_t dimlen = (size_t)gridInqSize(gridID);
-  int gridindex = vlistGridIndex(vlistID, gridID);
-
-  for ( int index = 0; index < ngrids; index++ )
-    {
-      if ( streamptr->xdimID[index] != UNDEFID )
-        {
-          int gridID0 = vlistGrid(vlistID, index);
-          int gridtype0 = gridInqType(gridID0);
-          if ( gridtype0 == GRID_UNSTRUCTURED )
-            {
-              size_t dimlen0 = (size_t)gridInqSize(gridID0);
-              if ( dimlen == dimlen0 )
-		if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) &&
-		     IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
-		     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
-		  {
-		    dimID = streamptr->xdimID[index];
-                    ncxvarid = streamptr->ncxvarID[index];
-                    ncyvarid = streamptr->ncyvarID[index];
-                    ncavarid = streamptr->ncavarID[index];
-		    break;
-		  }
-            }
-        }
-    }
-
-  if ( dimID == UNDEFID )
-    {
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-      {
-        char xdimname[CDI_MAX_NAME+3];
-        xdimname[0] = 0;
-        cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname);
-        if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells");
-        dimID = checkDimName(fileID, dimlen, xdimname);
-        if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID);
-      }
-
-      size_t nvertex = (size_t)gridInqNvertex(gridID);
-      if ( nvertex > 0 )
-        {
-          char vdimname[CDI_MAX_NAME+3];
-          vdimname[0] = 0;
-          cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname);
-          if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices");
-          nvdimID = checkDimName(fileID, nvertex, vdimname);
-          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
-        }
-
-      cdfDefGridReference(streamptr, gridID);
-
-      cdfDefGridUUID(streamptr, gridID);
-
-      if ( gridInqXvalsPtr(gridID) )
-        {
-          char xaxisname[CDI_MAX_NAME];
-          gridInqXname(gridID, xaxisname);
-          checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X');
-          cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
-
-          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
-
-          if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
-            {
-              int dimIDs[2] = { dimID, nvdimID };
-              size_t xaxisnameLen = strlen(xaxisname);
-              xaxisname[xaxisnameLen] = '_';
-              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
-              cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
-
-              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
-            }
-        }
-
-      if ( gridInqYvalsPtr(gridID) )
-        {
-          char yaxisname[CDI_MAX_NAME];
-          gridInqYname(gridID, yaxisname);
-          checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y');
-          cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
-
-          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
-
-          if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
-            {
-              int dimIDs[2] = { dimID, nvdimID };
-              size_t yaxisnameLen = strlen(yaxisname);
-              yaxisname[yaxisnameLen] = '_';
-              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
-              cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
-
-              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
-            }
-        }
-
-      if ( gridInqAreaPtr(gridID) )
-        {
-          static const char yaxisname_[] = "cell_area";
-          static const char units[] = "m2";
-          static const char longname[] = "area of grid cell";
-          static const char stdname[] = "cell_area";
-
-          cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid);
-
-          cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
-          cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
-          cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units);
-        }
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      if ( ncxvarid  != UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  gridInqXvalsPtr(gridID));
-      if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID));
-      if ( ncyvarid  != UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  gridInqYvalsPtr(gridID));
-      if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID));
-      if ( ncavarid  != UNDEFID ) cdf_put_var_double(fileID, ncavarid,  gridInqAreaPtr(gridID));
-    }
-
-  streamptr->xdimID[gridindex] = dimID;
-  streamptr->ncxvarID[gridindex] = ncxvarid;
-  streamptr->ncyvarID[gridindex] = ncyvarid;
-  streamptr->ncavarID[gridindex] = ncavarid;
-}
-
-struct attTxtTab2
-{
-  const char *attName, *attVal;
-  size_t valLen;
-};
-
-static
-void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
-{
-  int type = zaxisInqType(zaxisID);
-
-  if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
-    {
-      int ilev = zaxisInqVctSize(zaxisID)/2;
-      if ( ilev == 0 ) return;
-
-      int mlev = ilev - 1;
-      size_t start;
-      size_t count = 1;
-      int ncdimid, ncdimid2;
-      int hyaiid, hybiid, hyamid, hybmid;
-      double mval;
-
-      if ( streamptr->vct.ilev > 0 )
-        {
-          if ( streamptr->vct.ilev != ilev )
-            Error("more than one VCT for each file unsupported!");
-          return;
-        }
-
-      int fileID = streamptr->fileID;
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      cdf_def_dim(fileID, "nhym", (size_t)mlev, &ncdimid);
-      cdf_def_dim(fileID, "nhyi", (size_t)ilev, &ncdimid2);
-
-      streamptr->vct.mlev   = mlev;
-      streamptr->vct.ilev   = ilev;
-      streamptr->vct.mlevID = ncdimid;
-      streamptr->vct.ilevID = ncdimid2;
-
-      cdf_def_var(fileID, "hyai", NC_DOUBLE, 1, &ncdimid2, &hyaiid);
-      cdf_def_var(fileID, "hybi", NC_DOUBLE, 1, &ncdimid2, &hybiid);
-      cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid,  &hyamid);
-      cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid,  &hybmid);
-
-      {
-        static const char lname_n[] = "long_name",
-          lname_v_ai[] = "hybrid A coefficient at layer interfaces",
-          units_n[] = "units",
-          units_v_ai[] = "Pa",
-          lname_v_bi[] = "hybrid B coefficient at layer interfaces",
-          units_v_bi[] = "1",
-          lname_v_am[] = "hybrid A coefficient at layer midpoints",
-          units_v_am[] = "Pa",
-          lname_v_bm[] = "hybrid B coefficient at layer midpoints",
-          units_v_bm[] = "1";
-        static const struct attTxtTab2 tab[]
-          = {
-          { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 },
-          { units_n, units_v_ai, sizeof (units_v_ai) - 1 },
-          { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 },
-          { units_n, units_v_bi, sizeof (units_v_bi) - 1 },
-          { lname_n, lname_v_am, sizeof (lname_v_am) - 1 },
-          { units_n, units_v_am, sizeof (units_v_am) - 1 },
-          { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 },
-          { units_n, units_v_bm, sizeof (units_v_bm) - 1 },
-        };
-        enum { tabLen = sizeof (tab) / sizeof (tab[0]) };
-        int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid,
-                            hyamid, hyamid, hybmid, hybmid };
-        for ( size_t i = 0; i < tabLen; ++i )
-          cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal);
-      }
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      const double *vctptr = zaxisInqVctPtr(zaxisID);
-
-      cdf_put_var_double(fileID, hyaiid, vctptr);
-      cdf_put_var_double(fileID, hybiid, vctptr+ilev);
-
-      for ( int i = 0; i < mlev; i++ )
-        {
-          start = (size_t)i;
-          mval = (vctptr[i] + vctptr[i+1]) * 0.5;
-          cdf_put_vara_double(fileID, hyamid, &start, &count, &mval);
-          mval = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5;
-          cdf_put_vara_double(fileID, hybmid, &start, &count, &mval);
-        }
-    }
-}
-
-static
-void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
-{
-  int type = zaxisInqType(zaxisID);
-
-  if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
-    {
-      int ilev = zaxisInqVctSize(zaxisID)/2;
-      if ( ilev == 0 ) return;
-
-      int mlev = ilev - 1;
-      int hyaiid = 0, hybiid = 0, hyamid, hybmid;
-
-      if ( streamptr->vct.ilev > 0 )
-        {
-          if ( streamptr->vct.ilev != ilev )
-            Error("more than one VCT for each file unsupported!");
-          return;
-        }
-
-      int fileID = streamptr->fileID;
-
-      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-      int dimIDs[2];
-      dimIDs[0] = nclevID;
-      dimIDs[1] = ncbndsID;
-
-      streamptr->vct.mlev   = mlev;
-      streamptr->vct.ilev   = ilev;
-      streamptr->vct.mlevID = nclevID;
-      streamptr->vct.ilevID = nclevID;
-
-      cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs,  &hyamid);
-      cdf_def_var(fileID, "b",  NC_DOUBLE, 1, dimIDs,  &hybmid);
-
-      {
-        static const char lname[] = "vertical coordinate formula term: ap(k)";
-        cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname);
-      }
-      {
-        static const char units[] = "Pa";
-        cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units);
-      }
-      {
-        static const char lname[] = "vertical coordinate formula term: b(k)";
-        cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname);
-      }
-      {
-        static const char units[] = "1";
-        cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units);
-      }
-
-      if ( ncbndsID != -1 )
-        {
-          cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid);
-          cdf_def_var(fileID, "b_bnds",  NC_DOUBLE, 2, dimIDs, &hybiid);
-          {
-            static const char lname[] = "vertical coordinate formula term: ap(k+1/2)";
-            cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname);
-          }
-          {
-            static const char units[] = "Pa";
-            cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units);
-          }
-          {
-            static const char lname[] = "vertical coordinate formula term: b(k+1/2)";
-            cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname);
-          }
-          {
-            static const char units[] = "1";
-            cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units);
-          }
-        }
-
-      cdf_enddef(fileID);
-      streamptr->ncmode = 2;
-
-      const double *vctptr = zaxisInqVctPtr(zaxisID);
-      double tarray[ilev*2];
-
-      if ( ncbndsID != -1 )
-        {
-          for ( int i = 0; i < mlev; ++i )
-            {
-              tarray[2*i  ] = vctptr[i];
-              tarray[2*i+1] = vctptr[i+1];
-            }
-          cdf_put_var_double(fileID, hyaiid, tarray);
-
-          for ( int i = 0; i < mlev; ++i )
-            {
-              tarray[2*i  ] = vctptr[ilev+i];
-              tarray[2*i+1] = vctptr[ilev+i+1];
-            }
-          cdf_put_var_double(fileID, hybiid, tarray);
-        }
-
-      for ( int i = 0; i < mlev; ++i )
-        tarray[i] = (vctptr[i] + vctptr[i+1]) * 0.5;
-      cdf_put_var_double(fileID, hyamid, tarray);
-
-      for ( int i = 0; i < mlev; ++i )
-        tarray[i] = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5;
-      cdf_put_var_double(fileID, hybmid, tarray);
-    }
-}
-
-struct attTxtTab { const char *txt; size_t txtLen; };
-
-static
-void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
-{
-  int fileID  = streamptr->fileID;
-
-  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-  cdf_def_dim(fileID, axisname, dimlen, dimID);
-  cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
-
-  {
-    static const char sname[] = "hybrid_sigma_pressure";
-    cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname);
-  }
-  {
-    static const char *attName[] = {
-      "long_name",
-      "formula",
-      "formula_terms"
-    };
-    enum { nAtt = sizeof (attName) / sizeof (attName[0]) };
-    static const char lname_m[] = "hybrid level at layer midpoints",
-      formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)",
-      fterms_m[] = "ap: hyam b: hybm ps: aps",
-      lname_i[] = "hybrid level at layer interfaces",
-      formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)",
-      fterms_i[] = "ap: hyai b: hybi ps: aps";
-    static const struct attTxtTab tab[2][nAtt] = {
-      {
-        { lname_i, sizeof (lname_i) - 1 },
-        { formula_i, sizeof (formula_i) - 1 },
-        { fterms_i, sizeof (fterms_i) - 1 }
-      },
-      {
-        { lname_m, sizeof (lname_m) - 1 },
-        { formula_m, sizeof (formula_m) - 1 },
-        { fterms_m, sizeof (fterms_m) - 1 }
-      }
-    };
-
-    size_t tabSelect = type == ZAXIS_HYBRID;
-    for (size_t i = 0; i < nAtt; ++i)
-      cdf_put_att_text(fileID, ncvarid, attName[i],
-                       tab[tabSelect][i].txtLen, tab[tabSelect][i].txt);
-  }
-
-  {
-    static const char units[] = "level";
-    cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units);
-  }
-  {
-    static const char direction[] = "down";
-    cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction);
-  }
-
-  cdf_enddef(fileID);
-  streamptr->ncmode = 2;
-
-  cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID));
-
-  cdf_def_vct_echam(streamptr, zaxisID);
-
-  if ( *dimID == UNDEFID )
-    {
-      if ( type == ZAXIS_HYBRID )
-        streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID;
-      else
-        streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID;
-    }
-}
-
-static
-void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
-{
-  char psname[CDI_MAX_NAME];
-  psname[0] = 0;
-  zaxisInqPsName(zaxisID, psname);
-  if ( psname[0] == 0 ) strcpy(psname, "ps");
-
-  int fileID = streamptr->fileID;
-  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-  strcpy(axisname, "lev");
-
-  cdf_def_dim(fileID, axisname, dimlen, dimID);
-  cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
-
-  {
-    static const char sname[] = "standard_name",
-      sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
-      lname[] = "long_name",
-      lname_v[] = "hybrid sigma pressure coordinate",
-      formula[] = "formula",
-      formula_v[] = "p = ap + b*ps",
-      fterms[] = "formula_terms",
-      fterms_v[] = "ap: ap b: b ps: ",
-      units[] = "units",
-      units_v[] = "1",
-      axis[] = "axis",
-      axis_v[] = "Z",
-      direction[] = "positive",
-      direction_v[] = "down";
-    struct attTxtTab2 tab[] = {
-      { sname, sname_v, sizeof (sname_v) - 1 },
-      { lname, lname_v, sizeof (lname_v) - 1 },
-      { formula, formula_v, sizeof (formula_v) - 1 },
-      { fterms, fterms_v, sizeof (fterms_v) - 1 },
-      { units, units_v, sizeof (units_v) - 1 },
-      { axis, axis_v, sizeof (axis_v) - 1 },
-      { direction, direction_v, sizeof (direction_v) - 1 },
-    };
-    enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
-    for (size_t i = 0; i < nAtt; ++i)
-      cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
-  }
-
-  int ncbvarid = UNDEFID;
-  int nvdimID = UNDEFID;
-
-  double lbounds[dimlen], ubounds[dimlen], levels[dimlen];
-
-  zaxisInqLevels(zaxisID, levels);
-
-  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-    {
-      zaxisInqLbounds(zaxisID, lbounds);
-      zaxisInqUbounds(zaxisID, ubounds);
-    }
-  else
-    {
-      for ( size_t i = 0; i < dimlen; ++i ) lbounds[i] = levels[i];
-      for ( size_t i = 0; i < dimlen-1; ++i ) ubounds[i] = levels[i+1];
-      ubounds[dimlen-1] = levels[dimlen-1] + 1;
-    }
-
-  //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-    {
-      size_t nvertex = 2;
-      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
-        cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
-
-      if ( nvdimID != UNDEFID )
-        {
-          size_t axisnameLen = strlen(axisname);
-          axisname[axisnameLen] = '_';
-          memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
-          axisnameLen += sizeof (bndsName);
-          int dimIDs[2] = { *dimID, nvdimID };
-          cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
-          cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname);
-          {
-            static const char sname[] = "standard_name",
-              sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
-              formula[] = "formula",
-              formula_v[] = "p = ap + b*ps";
-            struct attTxtTab2 tab[] = {
-              { sname, sname_v, sizeof (sname_v) - 1 },
-              { formula, formula_v, sizeof (formula_v) - 1 },
-            };
-            enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
-            for (size_t i = 0; i < nAtt; ++i)
-              cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
-          }
-          {
-            char txt[CDI_MAX_NAME];
-            size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname));
-            cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt);
-          }
-          {
-            static const char units[] = "1";
-            cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units);
-          }
-        }
-    }
-
-  cdf_enddef(fileID);
-  streamptr->ncmode = 2;
-
-  cdf_put_var_double(fileID, ncvarid, levels);
-
-  if ( ncbvarid != UNDEFID )
-    {
-      double zbounds[2*dimlen];
-      for ( size_t i = 0; i < dimlen; ++i )
-        {
-          zbounds[2*i  ] = lbounds[i];
-          zbounds[2*i+1] = ubounds[i];
-        }
-      cdf_put_var_double(fileID, ncbvarid, zbounds);
-    }
-
-  cdf_def_vct_cf(streamptr, zaxisID, *dimID, nvdimID);
-
-  if ( *dimID == UNDEFID )
-    {
-      if ( type == ZAXIS_HYBRID )
-        streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID;
-      else
-        streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID;
-    }
-}
-
-static
-void cdf_def_zaxis_hybrid(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
-{
-  if ( (!CDI_cmor_mode && cdiConvention == CDI_CONVENTION_ECHAM) || type == ZAXIS_HYBRID_HALF )
-    cdf_def_zaxis_hybrid_echam(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname);
-  else
-    cdf_def_zaxis_hybrid_cf(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname);
-}
-
-static
-void cdfDefZaxis(stream_t *streamptr, int zaxisID)
-{
-  /*  char zaxisname0[CDI_MAX_NAME]; */
-  char axisname[CDI_MAX_NAME];
-  int dimID = UNDEFID;
-  int dimIDs[2];
-  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvdimID = UNDEFID;
-  int xtype = NC_DOUBLE;
-
-  if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-
-  int nzaxis = vlistNzaxis(vlistID);
-
-  size_t dimlen = (size_t)zaxisInqSize(zaxisID);
-  int type   = zaxisInqType(zaxisID);
-
-  int is_scalar = FALSE;
-  if ( dimlen == 1 )
-    {
-      is_scalar = zaxisInqScalar(zaxisID);
-      if ( !is_scalar && CDI_cmor_mode )
-        {
-          is_scalar = TRUE;
-          zaxisDefScalar(zaxisID);
-        }
-    }
-
-  int ndims = 1;
-  if ( is_scalar ) ndims = 0;
-
-  if ( dimlen == 1 )
-    switch (type)
-      {
-      case ZAXIS_SURFACE:
-      case ZAXIS_CLOUD_BASE:
-      case ZAXIS_CLOUD_TOP:
-      case ZAXIS_ISOTHERM_ZERO:
-      case ZAXIS_TOA:
-      case ZAXIS_SEA_BOTTOM:
-      case ZAXIS_ATMOSPHERE:
-      case ZAXIS_MEANSEA:
-      case ZAXIS_LAKE_BOTTOM:
-      case ZAXIS_SEDIMENT_BOTTOM:
-      case ZAXIS_SEDIMENT_BOTTOM_TA:
-      case ZAXIS_SEDIMENT_BOTTOM_TW:
-      case ZAXIS_MIX_LAYER:
-        return;
-      }
-
-  zaxisInqName(zaxisID, axisname);
-
-  if ( dimID == UNDEFID )
-    {
-      checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis);
-
-      char dimname[CDI_MAX_NAME+3];
-      dimname[0] = 0;
-      //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname);
-      if ( dimname[0] == 0 ) strcpy(dimname, axisname);
-
-      if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID);
-
-      if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
-        {
-          cdf_def_zaxis_hybrid(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, &dimID, axisname);
-        }
-      else
-        {
-          dimID = checkDimName(fileID, dimlen, dimname);
-
-          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
-          if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
-
-          cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
-
-          cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ);
-
-          {
-            int positive = zaxisInqPositive(zaxisID);
-            static const char positive_up[] = "up",
-              positive_down[] = "down";
-            static const struct attTxtTab tab[2] = {
-              { positive_up, sizeof (positive_up) - 1 },
-              { positive_down, sizeof (positive_down) - 1 },
-            };
-            if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN )
-              {
-                size_t select = positive == POSITIVE_DOWN;
-                cdf_put_att_text(fileID, ncvarid, "positive",
-                                 tab[select].txtLen, tab[select].txt);
-              }
-          }
-          cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z");
-
-	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-            {
-              size_t nvertex = 2;
-	      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
-		cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
-
-	      if ( nvdimID != UNDEFID )
-		{
-                  size_t axisnameLen = strlen(axisname);
-                  axisname[axisnameLen] = '_';
-                  memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
-		  dimIDs[0] = dimID;
-		  dimIDs[ndims] = nvdimID;
-		  cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid);
-		  cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
-		}
-	    }
-
-          cdf_enddef(fileID);
-          streamptr->ncmode = 2;
-
-          cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID));
-
-          if ( ncbvarid != UNDEFID )
-	    {
-              double lbounds[dimlen], ubounds[dimlen], zbounds[2*dimlen];
-	      zaxisInqLbounds(zaxisID, lbounds);
-	      zaxisInqUbounds(zaxisID, ubounds);
-	      for ( size_t i = 0; i < dimlen; ++i )
-		{
-		  zbounds[2*i  ] = lbounds[i];
-		  zbounds[2*i+1] = ubounds[i];
-		}
-
-	      cdf_put_var_double(fileID, ncbvarid, zbounds);
-	    }
-
-          if ( ndims == 0 ) streamptr->nczvarID[zaxisindex] = ncvarid;
-        }
-    }
-
-  if ( dimID != UNDEFID )
-    streamptr->zaxisID[zaxisindex] = dimID;
-}
-
-static
-void cdfDefPole(stream_t *streamptr, int gridID)
-{
-  int ncvarid = UNDEFID;
-  static const char varname[] = "rotated_pole";
-  static const char mapname[] = "rotated_latitude_longitude";
-
-  int fileID  = streamptr->fileID;
-
-  double ypole = gridInqYpole(gridID);
-  double xpole = gridInqXpole(gridID);
-  double angle = gridInqAngle(gridID);
-
-  cdf_redef(fileID);
-
-  int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
-  if ( ncerrcode == NC_NOERR )
-    {
-      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname);
-      cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
-      cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
-      if ( IS_NOT_EQUAL(angle, 0) )
-        cdf_put_att_double(fileID, ncvarid, "north_pole_grid_longitude", NC_DOUBLE, 1, &angle);
-    }
-
-  cdf_enddef(fileID);
-}
-
-
-static
-void cdfDefMapping(stream_t *streamptr, int gridID)
-{
-  int ncvarid = UNDEFID;
-  int fileID  = streamptr->fileID;
-
-  if ( gridInqType(gridID) == GRID_SINUSOIDAL )
-    {
-      static const char varname[] = "sinusoidal";
-      static const char mapname[] = "sinusoidal";
-
-      cdf_redef(fileID);
-
-      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
-      if ( ncerrcode == NC_NOERR )
-        {
-          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
-          /*
-          cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
-          cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
-          */
-        }
-
-      cdf_enddef(fileID);
-    }
-  else if ( gridInqType(gridID) == GRID_LAEA )
-    {
-      static const char varname[] = "laea";
-      static const char mapname[] = "lambert_azimuthal_equal_area";
-
-      cdf_redef(fileID);
-
-      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
-      if ( ncerrcode == NC_NOERR )
-        {
-          double a, lon_0, lat_0;
-
-          gridInqLaea(gridID, &a, &lon_0, &lat_0);
-
-          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
-          cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &a);
-          cdf_put_att_double(fileID, ncvarid, "longitude_of_projection_origin", NC_DOUBLE, 1, &lon_0);
-          cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0);
-        }
-
-      cdf_enddef(fileID);
-    }
-  else if ( gridInqType(gridID) == GRID_LCC2 )
-    {
-      static const char varname[] = "Lambert_Conformal";
-      static const char mapname[] = "lambert_conformal_conic";
-
-      cdf_redef(fileID);
-
-      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
-      if ( ncerrcode == NC_NOERR )
-        {
-          double radius, lon_0, lat_0, lat_1, lat_2;
-
-          gridInqLcc2(gridID, &radius, &lon_0, &lat_0, &lat_1, &lat_2);
-
-          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
-          if ( radius > 0 )
-            cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &radius);
-          cdf_put_att_double(fileID, ncvarid, "longitude_of_central_meridian", NC_DOUBLE, 1, &lon_0);
-          cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0);
-          if ( IS_EQUAL(lat_1, lat_2) )
-            cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 1, &lat_1);
-          else
-            {
-              double lat_1_2[2];
-              lat_1_2[0] = lat_1;
-              lat_1_2[1] = lat_2;
-              cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 2, lat_1_2);
-            }
-        }
-
-      cdf_enddef(fileID);
-    }
-}
-
-
-static
-void cdfDefGrid(stream_t *streamptr, int gridID)
-{
-  int vlistID = streamptr->vlistID;
-  int gridindex = vlistGridIndex(vlistID, gridID);
-  if ( streamptr->xdimID[gridindex] != UNDEFID ) return;
-
-  int gridtype = gridInqType(gridID);
-  int size     = gridInqSize(gridID);
-
-  if ( CDI_Debug )
-    Message("gridtype = %d  size = %d", gridtype, size);
-
-  if ( gridtype == GRID_GAUSSIAN ||
-       gridtype == GRID_LONLAT   ||
-       gridtype == GRID_GENERIC )
-    {
-      if ( gridtype == GRID_GENERIC )
-        {
-          if ( size == 1 && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 )
-            {
-              /* no grid information */
-            }
-          else
-            {
-              int lx = 0, ly = 0;
-              if ( gridInqXsize(gridID) > 0 /*&& gridInqXvals(gridID, NULL) > 0*/ )
-                {
-                  cdfDefXaxis(streamptr, gridID, 1);
-                  lx = 1;
-                }
-
-              if ( gridInqYsize(gridID) > 0 /*&& gridInqYvals(gridID, NULL) > 0*/ )
-                {
-                  cdfDefYaxis(streamptr, gridID, 1);
-                  ly = 1;
-                }
-
-              if ( lx == 0 && ly == 0 ) cdfDefGdim(streamptr, gridID);
-            }
-        }
-      else
-        {
-          int ndims = 1;
-          if ( gridtype == GRID_LONLAT && size == 1 && gridInqHasDims(gridID) == FALSE )
-            ndims = 0;
-
-          if ( gridInqXsize(gridID) > 0 ) cdfDefXaxis(streamptr, gridID, ndims);
-          if ( gridInqYsize(gridID) > 0 ) cdfDefYaxis(streamptr, gridID, ndims);
-        }
-
-      if ( gridIsRotated(gridID) ) cdfDefPole(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_CURVILINEAR )
-    {
-      cdfDefCurvilinear(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_UNSTRUCTURED )
-    {
-      cdfDefUnstructured(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_GAUSSIAN_REDUCED )
-    {
-      cdfDefRgrid(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_SPECTRAL )
-    {
-      cdfDefComplex(streamptr, gridID);
-      cdfDefSP(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_FOURIER )
-    {
-      cdfDefComplex(streamptr, gridID);
-      cdfDefFC(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_TRAJECTORY )
-    {
-      cdfDefTrajLon(streamptr, gridID);
-      cdfDefTrajLat(streamptr, gridID);
-    }
-  else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 )
-    {
-      cdfDefXaxis(streamptr, gridID, 1);
-      cdfDefYaxis(streamptr, gridID, 1);
-
-      cdfDefMapping(streamptr, gridID);
-    }
-  /*
-  else if ( gridtype == GRID_LCC )
-    {
-      cdfDefLcc(streamptr, gridID);
-    }
-  */
-  else
-    {
-      Error("Unsupported grid type: %s", gridNamePtr(gridtype));
-    }
-}
-
-static
-void scale_add(size_t size, double *data, double addoffset, double scalefactor)
-{
-  int laddoffset;
-  int lscalefactor;
-
-  laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-  lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
-  if ( laddoffset || lscalefactor )
-    {
-      for (size_t i = 0; i < size; ++i )
-        {
-          if ( lscalefactor ) data[i] *= scalefactor;
-          if ( laddoffset )   data[i] += addoffset;
-        }
-    }
-}
-
-static
-void cdfCreateRecords(stream_t *streamptr, int tsID)
-{
-  if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return;
-
-  if ( streamptr->tsteps[tsID].nallrecs > 0 ) return;
-
-  int vlistID  = streamptr->vlistID;
-
-  tsteps_t* sourceTstep = streamptr->tsteps;
-  tsteps_t* destTstep = sourceTstep + tsID;
-
-  int nvars = vlistNvars(vlistID);
-  int nrecs = vlistNrecs(vlistID);
-
-  if ( nrecs <= 0 ) return;
-
-  if ( tsID == 0 )
-    {
-      int nvrecs = nrecs; /* use all records at first timestep */
-
-      streamptr->nrecs += nrecs;
-
-      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
-      destTstep->nrecs      = nrecs;
-      destTstep->nallrecs   = nrecs;
-      destTstep->recordSize = nrecs;
-      destTstep->curRecID   = UNDEFID;
-      destTstep->recIDs     = (int *) Malloc((size_t)nvrecs*sizeof (int));;
-      for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
-
-      record_t *records = destTstep->records;
-
-      for ( int varID = 0, recID = 0; varID < nvars; varID++ )
-        {
-          int zaxisID = vlistInqVarZaxis(vlistID, varID);
-          int nlev    = zaxisInqSize(zaxisID);
-          for ( int levelID = 0; levelID < nlev; levelID++ )
-            {
-              recordInitEntry(&records[recID]);
-              records[recID].varID   = (short)varID;
-              records[recID].levelID = (short)levelID;
-              recID++;
-            }
-        }
-    }
-  else if ( tsID == 1 )
-    {
-      int nvrecs = 0;
-      for ( int varID = 0; varID < nvars; varID++ )
-        {
-          if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
-            {
-              int zaxisID = vlistInqVarZaxis(vlistID, varID);
-              nvrecs += zaxisInqSize(zaxisID);
-            }
-        }
-
-      streamptr->nrecs += nvrecs;
-
-      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
-      destTstep->nrecs      = nvrecs;
-      destTstep->nallrecs   = nrecs;
-      destTstep->recordSize = nrecs;
-      destTstep->curRecID   = UNDEFID;
-
-      memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
-
-      if ( nvrecs )
-        {
-          destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int));
-          for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ )
-            {
-              int varID = destTstep->records[recID].varID;
-              if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
-                {
-                  destTstep->recIDs[vrecID++] = recID;
-                }
-            }
-        }
-    }
-  else
-    {
-      if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1);
-
-      int nvrecs = streamptr->tsteps[1].nrecs;
-
-      streamptr->nrecs += nvrecs;
-
-      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
-      destTstep->nrecs      = nvrecs;
-      destTstep->nallrecs   = nrecs;
-      destTstep->recordSize = nrecs;
-      destTstep->curRecID   = UNDEFID;
-
-      memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
-
-      destTstep->recIDs     = (int *) Malloc((size_t)nvrecs * sizeof(int));
-
-      memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int));
-    }
-}
-
-
-static
-int cdfTimeDimID(int fileID, int ndims, int nvars)
-{
-  for ( int dimid = 0; dimid < ndims; dimid++ )
-    {
-      char dimname[80];
-      cdf_inq_dimname(fileID, dimid, dimname);
-      if ( memcmp(dimname, "time", 4) == 0 )
-        return dimid;
-    }
-
-
-  for ( int varid = 0; varid < nvars; varid++ )
-    {
-      int nvdims, nvatts, dimids[9];
-      cdf_inq_var(fileID, varid, NULL, NULL, &nvdims, dimids, &nvatts);
-      if ( nvdims == 1 )
-        {
-          for ( int iatt = 0; iatt < nvatts; iatt++ )
-            {
-              char sbuf[CDI_MAX_NAME];
-              cdf_inq_attname(fileID, varid, iatt, sbuf);
-              if ( strncmp(sbuf, "units", 5) == 0 )
-                {
-                  cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
-                  strtolower(sbuf);
-
-                  if ( isTimeUnits(sbuf) )
-                    return dimids[0];
-                }
-            }
-        }
-    }
-
-  return UNDEFID;
-}
-
-static
-void init_ncdims(long ndims, ncdim_t *ncdims)
-{
-  for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ )
-    {
-      ncdims[ncdimid].ncvarid      = UNDEFID;
-      ncdims[ncdimid].dimtype      = UNDEFID;
-      ncdims[ncdimid].len          = 0;
-      ncdims[ncdimid].name[0]      = 0;
-    }
-}
-
-static
-void init_ncvars(long nvars, ncvar_t *ncvars)
-{
-  for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid )
-    {
-      ncvars[ncvarid].ncid            = UNDEFID;
-      ncvars[ncvarid].ignore          = FALSE;
-      ncvars[ncvarid].isvar           = UNDEFID;
-      ncvars[ncvarid].islon           = FALSE;
-      ncvars[ncvarid].islat           = FALSE;
-      ncvars[ncvarid].islev           = FALSE;
-      ncvars[ncvarid].istime          = FALSE;
-      ncvars[ncvarid].warn            = FALSE;
-      ncvars[ncvarid].tsteptype       = TSTEP_CONSTANT;
-      ncvars[ncvarid].param           = UNDEFID;
-      ncvars[ncvarid].code            = UNDEFID;
-      ncvars[ncvarid].tabnum          = 0;
-      ncvars[ncvarid].calendar        = FALSE;
-      ncvars[ncvarid].climatology     = FALSE;
-      ncvars[ncvarid].bounds          = UNDEFID;
-      ncvars[ncvarid].lformula        = FALSE;
-      ncvars[ncvarid].lformulaterms   = FALSE;
-      ncvars[ncvarid].gridID          = UNDEFID;
-      ncvars[ncvarid].zaxisID         = UNDEFID;
-      ncvars[ncvarid].gridtype        = UNDEFID;
-      ncvars[ncvarid].zaxistype       = UNDEFID;
-      ncvars[ncvarid].xdim            = UNDEFID;
-      ncvars[ncvarid].ydim            = UNDEFID;
-      ncvars[ncvarid].zdim            = UNDEFID;
-      ncvars[ncvarid].xvarid          = UNDEFID;
-      ncvars[ncvarid].yvarid          = UNDEFID;
-      ncvars[ncvarid].zvarid          = UNDEFID;
-      ncvars[ncvarid].tvarid          = UNDEFID;
-      ncvars[ncvarid].psvarid         = UNDEFID;
-      ncvars[ncvarid].p0varid         = UNDEFID;
-      ncvars[ncvarid].ncoordvars      = 0;
-      for ( int i = 0; i < MAX_COORDVARS; ++i )
-        ncvars[ncvarid].coordvarids[i]  = UNDEFID;
-      ncvars[ncvarid].nauxvars      = 0;
-      for ( int i = 0; i < MAX_AUXVARS; ++i )
-        ncvars[ncvarid].auxvarids[i]  = UNDEFID;
-      ncvars[ncvarid].cellarea        = UNDEFID;
-      ncvars[ncvarid].tableID         = UNDEFID;
-      ncvars[ncvarid].xtype           = 0;
-      ncvars[ncvarid].ndims           = 0;
-      ncvars[ncvarid].gmapid          = UNDEFID;
-      ncvars[ncvarid].vctsize         = 0;
-      ncvars[ncvarid].vct             = NULL;
-      ncvars[ncvarid].truncation      = 0;
-      ncvars[ncvarid].position        = 0;
-      ncvars[ncvarid].positive        = 0;
-      ncvars[ncvarid].chunked         = 0;
-      ncvars[ncvarid].chunktype       = UNDEFID;
-      ncvars[ncvarid].defmissval      = 0;
-      ncvars[ncvarid].deffillval      = 0;
-      ncvars[ncvarid].missval         = 0;
-      ncvars[ncvarid].fillval         = 0;
-      ncvars[ncvarid].addoffset       = 0;
-      ncvars[ncvarid].scalefactor     = 1;
-      ncvars[ncvarid].name[0]         = 0;
-      ncvars[ncvarid].longname[0]     = 0;
-      ncvars[ncvarid].stdname[0]      = 0;
-      ncvars[ncvarid].units[0]        = 0;
-      ncvars[ncvarid].extra[0]        = 0;
-      ncvars[ncvarid].natts           = 0;
-      ncvars[ncvarid].atts            = NULL;
-      ncvars[ncvarid].deflate         = 0;
-      ncvars[ncvarid].lunsigned       = 0;
-      ncvars[ncvarid].lvalidrange     = 0;
-      ncvars[ncvarid].validrange[0]   = VALIDMISS;
-      ncvars[ncvarid].validrange[1]   = VALIDMISS;
-      ncvars[ncvarid].ensdata         = NULL;
-    }
-}
-
-static
-void cdfSetVar(ncvar_t *ncvars, int ncvarid, short isvar)
-{
-  if ( ncvars[ncvarid].isvar != UNDEFID &&
-       ncvars[ncvarid].isvar != isvar   &&
-       ncvars[ncvarid].warn  == FALSE )
-    {
-      if ( ! ncvars[ncvarid].ignore )
-        Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name);
-
-      ncvars[ncvarid].warn = TRUE;
-      isvar = FALSE;
-    }
-
-  ncvars[ncvarid].isvar = isvar;
-}
-
-static
-void cdfSetDim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype)
-{
-  if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID &&
-       ncvars[ncvarid].dimtype[dimid] != dimtype )
-    {
-      Warning("Inconsistent dimension definition for %s! dimid = %d;  type = %d;  newtype = %d",
-              ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype);
-    }
-
-  ncvars[ncvarid].dimtype[dimid] = dimtype;
-}
-
-static
-bool isLonAxis(const char *units, const char *stdname)
-{
-  bool status = false;
-  char lc_units[16];
-
-  memcpy(lc_units, units, 15);
-  lc_units[15] = 0;
-  strtolower(lc_units);
-
-  if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
-        (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) )
-    {
-      status = true;
-    }
-
-  if ( status == false &&
-       memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) &&
-       memcmp(lc_units, "degree", 6) == 0 )
-    {
-      int ioff = 6;
-      if ( lc_units[ioff] == 's' ) ioff++;
-      if ( lc_units[ioff] == '_' ) ioff++;
-      if ( lc_units[ioff] == 'e' ) status = true;
-    }
-
-  return status;
-}
-
-static
-bool isLatAxis(const char *units, const char *stdname)
-{
-  bool status = false;
-  char lc_units[16];
-
-  memcpy(lc_units, units, 15);
-  lc_units[15] = 0;
-  strtolower(lc_units);
-
-  if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
-        (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) )
-    {
-      status = true;
-    }
-
-  if ( status == false &&
-       memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) &&
-       memcmp(lc_units, "degree", 6) == 0 )
-    {
-      int ioff = 6;
-      if ( lc_units[ioff] == 's' ) ioff++;
-      if ( lc_units[ioff] == '_' ) ioff++;
-      if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true;
-    }
-
-  return status;
-}
-
-static
-bool isDBLAxis(/*const char *units,*/ const char *longname)
-{
-  bool status = false;
-
-  if ( strcmp(longname, "depth below land")         == 0 ||
-       strcmp(longname, "depth_below_land")         == 0 ||
-       strcmp(longname, "levels below the surface") == 0 )
-    {
-      /*
-      if ( strcmp(ncvars[ncvarid].units, "cm") == 0 ||
-           strcmp(ncvars[ncvarid].units, "dm") == 0 ||
-           strcmp(ncvars[ncvarid].units, "m")  == 0 )
-      */
-        status = true;
-    }
-
-  return status;
-}
-
-static
-bool unitsIsHeight(const char *units)
-{
-  bool status = false;
-  int u0 = units[0];
-
-  if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) ||
-       (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) )
-    {
-      status = true;
-    }
-
-  return status;
-}
-
-static
-bool isDepthAxis(const char *stdname, const char *longname)
-{
-  bool status = false;
-
-  if ( strcmp(stdname, "depth") == 0 )
-    status = true;
-  else
-    if ( strcmp(longname, "depth_below_sea") == 0 ||
-         strcmp(longname, "depth below sea") == 0 )
-      {
-        status = true;
-      }
-
-  return status;
-}
-
-static
-bool isHeightAxis(const char *stdname, const char *longname)
-{
-  bool status = false;
-
-  if ( strcmp(stdname, "height") == 0 )
-    status = true;
-  else
-    if ( strcmp(longname, "height") == 0 ||
-         strcmp(longname, "height above the surface") == 0 )
-      {
-        status = true;
-      }
-
-  return status;
-}
-
-static
-bool unitsIsPressure(const char *units)
-{
-  bool status = false;
-
-  if ( strncmp(units, "millibar", 8) == 0 ||
-       strncmp(units, "mb", 2)       == 0 ||
-       strncmp(units, "hectopas", 8) == 0 ||
-       strncmp(units, "hPa", 3)      == 0 ||
-       strncmp(units, "Pa", 2)       == 0 )
-    {
-      status = true;
-    }
-
-  return status;
-}
-
-static
-int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid)
-{
-  int status = 0;
-  *apvarid = -1;
-  *bvarid  = -1;
-  *psvarid = -1;
-  *avarid  = -1;
-  *p0varid = -1;
-  enum { attstringlen = 8192 }; char attstring[attstringlen];
-  cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
-  if ( strcmp(attstring, "p = ap + b*ps") == 0 )
-    {
-      status = 1;
-      int lstop = FALSE;
-      int dimvarid;
-      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
-      char *pstring = attstring;
-
-      for ( int i = 0; i < 3; i++ )
-        {
-          while ( isspace((int) *pstring) ) pstring++;
-          if ( *pstring == 0 ) break;
-          char *tagname = pstring;
-          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-          if ( *pstring == 0 ) lstop = TRUE;
-          *pstring++ = 0;
-
-          while ( isspace((int) *pstring) ) pstring++;
-          if ( *pstring == 0 ) break;
-          char *varname = pstring;
-          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-          if ( *pstring == 0 ) lstop = TRUE;
-          *pstring++ = 0;
-
-          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
-          if ( status_nc == NC_NOERR )
-            {
-              if      ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
-              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
-              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
-            }
-          else if ( strcmp(tagname, "ps:") != 0 )
-            {
-              Warning("%s - %s", nc_strerror(status_nc), varname);
-            }
-
-          if ( lstop ) break;
-        }
-    }
-  else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 )
-    {
-      status = 2;
-      int lstop = FALSE;
-      int dimvarid;
-      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
-      char *pstring = attstring;
-
-      for ( int i = 0; i < 4; i++ )
-        {
-          while ( isspace((int) *pstring) ) pstring++;
-          if ( *pstring == 0 ) break;
-          char *tagname = pstring;
-          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-          if ( *pstring == 0 ) lstop = TRUE;
-          *pstring++ = 0;
-
-          while ( isspace((int) *pstring) ) pstring++;
-          if ( *pstring == 0 ) break;
-          char *varname = pstring;
-          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-          if ( *pstring == 0 ) lstop = TRUE;
-          *pstring++ = 0;
-
-          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
-          if ( status_nc == NC_NOERR )
-            {
-              if      ( strcmp(tagname, "a:")  == 0 ) *avarid  = dimvarid;
-              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
-              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
-              else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid;
-            }
-          else if ( strcmp(tagname, "ps:") != 0 )
-            {
-              Warning("%s - %s", nc_strerror(status_nc), varname);
-            }
-
-          if ( lstop ) break;
-        }
-    }
-
-  return status;
-}
-
-static
-bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
-{
-  bool status = false;
-  int ncfvarid = ncvarid;
-  ncvar_t *ncvar = &ncvars[ncvarid];
-
-  if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 )
-    {
-      cdiConvention = CDI_CONVENTION_CF;
-
-      status = true;
-      ncvar->zaxistype = ZAXIS_HYBRID;
-      int dimid = ncvar->dimids[0];
-      size_t dimlen = ncdims[dimid].len;
-
-      int ret;
-      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1;
-      if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-        ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1);
-      if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
-      if ( bvarid1  != -1 ) ncvars[bvarid1].isvar  = FALSE;
-      if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
-      if ( avarid1  != -1 ) ncvars[avarid1].isvar = FALSE;
-      if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1;
-
-      if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
-        {
-          ncfvarid = ncvar->bounds;
-          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1;
-          ret = 0;
-          if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
-            ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2);
-          if ( ret == 1 ) avarid2 = apvarid2;
-          if ( avarid2 != -1 && bvarid2 != -1 )
-            {
-              ncvars[avarid2].isvar = FALSE;
-              ncvars[bvarid2].isvar  = FALSE;
-
-              if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 )
-                {
-                  double px = 1;
-                  if ( ret == 2 && p0varid1 == p0varid2 )
-                    cdf_get_var_double(ncid, p0varid2, &px);
-
-                  double abuf[dimlen*2], bbuf[dimlen*2];
-                  cdf_get_var_double(ncid, avarid2, abuf);
-                  cdf_get_var_double(ncid, bvarid2, bbuf);
-                  /*
-                  for ( int i = 0; i < dimlen; ++i )
-                    printf("%d  %g %g    %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]);
-                  */
-                  size_t vctsize = (dimlen+1)*2;
-                  double *vct = (double *) Malloc(vctsize * sizeof(double));
-                  for ( size_t i = 0; i < dimlen; ++i )
-                    {
-                      vct[i] = abuf[i*2];
-                      vct[i+dimlen+1] = bbuf[i*2];
-                    }
-                  vct[dimlen]     = abuf[dimlen*2-1];
-                  vct[dimlen*2+1] = bbuf[dimlen*2-1];
-
-                  if ( ret == 2 && IS_NOT_EQUAL(px, 1) )
-                    for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px;
-
-                  ncvar->vct = vct;
-                  ncvar->vctsize = vctsize;
-                }
-            }
-        }
-    }
-
-  return status;
-}
-
-
-static
-int isGaussGrid(size_t ysize, double yinc, const double *yvals)
-{
-  int lgauss = FALSE;
-  double *yv, *yw;
-
-  if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */
-    {
-      size_t i;
-      yv = (double *) Malloc(ysize*sizeof(double));
-      yw = (double *) Malloc(ysize*sizeof(double));
-      gaussaw(yv, yw, ysize);
-      Free(yw);
-      for ( i = 0; i < ysize; i++ )
-        yv[i] = asin(yv[i])/M_PI*180.0;
-
-      for ( i = 0; i < ysize; i++ )
-        if ( fabs(yv[i] - yvals[i]) >
-             ((yv[0] - yv[1])/500) ) break;
-
-      if ( i == ysize ) lgauss = TRUE;
-
-      /* check S->N */
-      if ( lgauss == FALSE )
-        {
-          for ( i = 0; i < ysize; i++ )
-            if ( fabs(yv[i] - yvals[ysize-i-1]) >
-                 ((yv[0] - yv[1])/500) ) break;
-
-          if ( i == ysize ) lgauss = TRUE;
-        }
-
-      Free(yv);
-    }
-
-  return (lgauss);
-}
-
-static
-void printNCvars(const ncvar_t *ncvars, int nvars, const char *oname)
-{
-  char axis[7];
-  int ncvarid, i;
-  int ndim;
-  static const char iaxis[] = {'t', 'z', 'y', 'x'};
-
-  fprintf(stderr, "%s:\n", oname);
-
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      ndim = 0;
-      if ( ncvars[ncvarid].isvar )
-        {
-          axis[ndim++] = 'v';
-          axis[ndim++] = ':';
-          for ( i = 0; i < ncvars[ncvarid].ndims; i++ )
-            {/*
-              if      ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0];
-              else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1];
-              else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2];
-              else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3];
-              else
-             */
-              if      ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0];
-              else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1];
-              else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2];
-              else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3];
-              else                                             axis[ndim++] = '?';
-            }
-        }
-      else
-        {
-          axis[ndim++] = 'c';
-          axis[ndim++] = ':';
-          if      ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0];
-          else if ( ncvars[ncvarid].islev  ) axis[ndim++] = iaxis[1];
-          else if ( ncvars[ncvarid].islat  ) axis[ndim++] = iaxis[2];
-          else if ( ncvars[ncvarid].islon  ) axis[ndim++] = iaxis[3];
-          else                               axis[ndim++] = '?';
-        }
-
-      axis[ndim++] = 0;
-
-      fprintf(stderr, "%3d %3d  %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name);
-    }
-}
-
-static
-void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
-                          int timedimid, int modelID, int format)
-{
-  int ncid;
-  int ncdimid;
-  int nvdims, nvatts;
-  int *dimidsp;
-  int iatt;
-  nc_type xtype, atttype;
-  size_t attlen;
-  char name[CDI_MAX_NAME];
-  char attname[CDI_MAX_NAME];
-  const int attstringlen = 8192; char attstring[8192];
-
-  int nchecked_vars = 0;
-  enum { max_check_vars = 9 };
-  char *checked_vars[max_check_vars];
-  for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL;
-
-  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      ncid    = ncvars[ncvarid].ncid;
-      dimidsp = ncvars[ncvarid].dimids;
-
-      cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
-      strcpy(ncvars[ncvarid].name, name);
-
-      for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ )
-        ncvars[ncvarid].dimtype[ncdimid] = -1;
-
-      ncvars[ncvarid].xtype = xtype;
-      ncvars[ncvarid].ndims = nvdims;
-
-#if  defined  (HAVE_NETCDF4)
-      if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
-        {
-          int shuffle, deflate, deflate_level;
-          size_t chunks[nvdims];
-          int storage_in;
-          nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level);
-          if ( deflate > 0 ) ncvars[ncvarid].deflate = 1;
-
-          if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR )
-            {
-              if ( storage_in == NC_CHUNKED )
-                {
-                  ncvars[ncvarid].chunked = 1;
-                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
-                  if ( CDI_Debug )
-                    {
-                      fprintf(stderr, "%s: chunking %d %d %d  chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED);
-                      for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
-                      fprintf(stderr, "\n");
-                    }
-                  {
-                    char *buf = ncvars[ncvarid].extra;
-                    size_t pos = strlen(buf);
-                    static const char prefix[] = "chunks=";
-                    memcpy(buf + pos, prefix, sizeof (prefix));
-                    pos += sizeof (prefix) - 1;
-                    for ( int i = nvdims-1; i >= 0; --i )
-                      {
-                        pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i],
-                                                i > 0 ? "x" : ""));
-                      }
-                    buf[pos] = ' '; buf[pos + 1] = 0;
-                  }
-                }
-            }
-        }
-#endif
-
-      if ( nvdims > 0 )
-        {
-          if ( timedimid == dimidsp[0] )
-            {
-              ncvars[ncvarid].tsteptype = TSTEP_INSTANT;
-              cdfSetDim(ncvars, ncvarid, 0, T_AXIS);
-            }
-          else
-            {
-              for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ )
-                {
-                  if ( timedimid == dimidsp[ncdimid] )
-                    {
-                      Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
-                      ncvars[ncvarid].isvar = FALSE;
-                    }
-                }
-            }
-        }
-
-      for ( iatt = 0; iatt < nvatts; iatt++ )
-        {
-          cdf_inq_attname(ncid, ncvarid, iatt, attname);
-          cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
-          cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
-
-          if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname);
-            }
-          else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname);
-            }
-          else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
-            }
-          else if ( strcmp(attname, "calendar") == 0 )
-            {
-              ncvars[ncvarid].calendar = TRUE;
-            }
-          else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
-            {
-	      char paramstr[32];
-	      int pnum = 0, pcat = 255, pdis = 255;
-              cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr);
-	      sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis);
-	      ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) )
-            {
-              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code);
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
-            {
-              int tablenum;
-              cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
-              if ( tablenum > 0 )
-                {
-                  ncvars[ncvarid].tabnum = tablenum;
-                  ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL);
-                  if ( ncvars[ncvarid].tableID == CDI_UNDEFID )
-                    ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL);
-                }
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              if ( memcmp(attstring, "Triangular", attlen) == 0 )
-                ncvars[ncvarid].gridtype = GRID_SPECTRAL;
-            }
-          else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              strtolower(attstring);
-
-              if      ( strcmp(attstring, "gaussian reduced") == 0 )
-                ncvars[ncvarid].gridtype = GRID_GAUSSIAN_REDUCED;
-              else if ( strcmp(attstring, "gaussian") == 0 )
-                ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
-              else if ( strncmp(attstring, "spectral", 8) == 0 )
-                ncvars[ncvarid].gridtype = GRID_SPECTRAL;
-              else if ( strncmp(attstring, "fourier", 7) == 0 )
-                ncvars[ncvarid].gridtype = GRID_FOURIER;
-              else if ( strcmp(attstring, "trajectory") == 0 )
-                ncvars[ncvarid].gridtype = GRID_TRAJECTORY;
-              else if ( strcmp(attstring, "generic") == 0 )
-                ncvars[ncvarid].gridtype = GRID_GENERIC;
-              else if ( strcmp(attstring, "cell") == 0 )
-                ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
-              else if ( strcmp(attstring, "unstructured") == 0 )
-                ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
-              else if ( strcmp(attstring, "curvilinear") == 0 )
-                ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
-              else if ( strcmp(attstring, "sinusoidal") == 0 )
-                ;
-              else if ( strcmp(attstring, "laea") == 0 )
-                ;
-              else if ( strcmp(attstring, "lcc2") == 0 )
-                ;
-              else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear
-                ;
-              else
-                {
-                  static int warn = TRUE;
-                  if ( warn )
-                    {
-                      warn = FALSE;
-                      Warning("NetCDF attribute grid_type='%s' unsupported!", attstring);
-                    }
-                }
-
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              strtolower(attstring);
-
-              if      ( strcmp(attstring, "toa") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_TOA;
-              else if ( strcmp(attstring, "cloudbase") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_BASE;
-              else if ( strcmp(attstring, "cloudtop") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_TOP;
-              else if ( strcmp(attstring, "isotherm0") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_ISOTHERM_ZERO;
-              else if ( strcmp(attstring, "seabottom") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_SEA_BOTTOM;
-              else if ( strcmp(attstring, "lakebottom") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_LAKE_BOTTOM;
-              else if ( strcmp(attstring, "sedimentbottom") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM;
-              else if ( strcmp(attstring, "sedimentbottomta") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;
-              else if ( strcmp(attstring, "sedimentbottomtw") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;
-              else if ( strcmp(attstring, "mixlayer") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_MIX_LAYER;
-              else if ( strcmp(attstring, "atmosphere") == 0 )
-                ncvars[ncvarid].zaxistype = ZAXIS_ATMOSPHERE;
-              else
-                {
-                  static int warn = TRUE;
-                  if ( warn )
-                    {
-                      warn = FALSE;
-                      Warning("NetCDF attribute level_type='%s' unsupported!", attstring);
-                    }
-                }
-
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
-            {
-              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
-            }
-          else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) )
-            {
-              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
-            }
-          else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) )
-            {
-              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position);
-            }
-          else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
-            {
-	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
-	      /*
-		if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
-		if ( ncvars[ncvarid].addoffset != 0 )
-		Warning("attribute add_offset not supported for atttype %d", atttype);
-	      */
-	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
-            }
-          else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
-            {
-	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
-	      /*
-		if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
-		if ( ncvars[ncvarid].scalefactor != 1 )
-		Warning("attribute scale_factor not supported for atttype %d", atttype);
-	      */
-	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
-            }
-          else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              int ncboundsid;
-              int status = nc_inq_varid(ncid, attstring, &ncboundsid);
-              if ( status == NC_NOERR )
-                {
-                  ncvars[ncvarid].climatology = TRUE;
-                  ncvars[ncvarid].bounds = ncboundsid;
-                  cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
-                  cdfSetVar(ncvars, ncvarid, FALSE);
-                }
-              else
-                Warning("%s - %s", nc_strerror(status), attstring);
-            }
-          else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              int ncboundsid;
-              int status = nc_inq_varid(ncid, attstring, &ncboundsid);
-              if ( status == NC_NOERR )
-                {
-                  ncvars[ncvarid].bounds = ncboundsid;
-                  cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
-                  cdfSetVar(ncvars, ncvarid, FALSE);
-                }
-              else
-                Warning("%s - %s", nc_strerror(status), attstring);
-            }
-          else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 )
-            {
-              ncvars[ncvarid].lformulaterms = TRUE;
-            }
-          else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 )
-            {
-              ncvars[ncvarid].lformula = TRUE;
-            }
-          else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              char *pstring = attstring;
-
-              while ( isspace((int) *pstring) ) pstring++;
-              char *cell_measures = pstring;
-              while ( isalnum((int) *pstring) ) pstring++;
-              *pstring++ = 0;
-              while ( isspace((int) *pstring) ) pstring++;
-              char *cell_var = pstring;
-              while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
-              *pstring++ = 0;
-              /*
-              printf("cell_measures >%s<\n", cell_measures);
-              printf("cell_var >%s<\n", cell_var);
-              */
-              if ( memcmp(cell_measures, "area", 4) == 0 )
-                {
-                  int nc_cell_id;
-                  int status = nc_inq_varid(ncid, cell_var, &nc_cell_id);
-                  if ( status == NC_NOERR )
-                    {
-                      ncvars[ncvarid].cellarea = nc_cell_id;
-                      /* ncvars[nc_cell_id].isvar = UNDEFID; */
-                      cdfSetVar(ncvars, nc_cell_id, FALSE);
-                    }
-                  else
-                    Warning("%s - %s", nc_strerror(status), cell_var);
-                }
-              else
-                {
-                  Warning("%s has an unexpected contents: %s", attname, cell_measures);
-                }
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          /*
-          else if ( strcmp(attname, "coordinates") == 0 )
-            {
-              char *pstring, *xvarname = NULL, *yvarname = NULL;
-
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              pstring = attstring;
-
-              while ( isspace((int) *pstring) ) pstring++;
-              xvarname = pstring;
-              while ( isgraph((int) *pstring) ) pstring++;
-              *pstring++ = 0;
-              while ( isspace((int) *pstring) ) pstring++;
-              yvarname = pstring;
-              while ( isgraph((int) *pstring) ) pstring++;
-              *pstring++ = 0;
-
-              cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid);
-              cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid);
-
-              cdfSetVar(ncvars, ncvars[ncvarid].xvarid, FALSE);
-              cdfSetVar(ncvars, ncvars[ncvarid].yvarid, FALSE);
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          */
-          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
-            {
-              int lstop = FALSE;
-              int dimvarid;
-
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              char *pstring = attstring;
-
-              for ( int i = 0; i < MAX_COORDVARS; i++ )
-                {
-                  while ( isspace((int) *pstring) ) pstring++;
-                  if ( *pstring == 0 ) break;
-                  char *varname = pstring;
-                  while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-                  if ( *pstring == 0 ) lstop = TRUE;
-                  *pstring++ = 0;
-
-                  int status = nc_inq_varid(ncid, varname, &dimvarid);
-                  if ( status == NC_NOERR )
-                    {
-                      cdfSetVar(ncvars, dimvarid, FALSE);
-                      if ( cdiIgnoreAttCoordinates == FALSE )
-                        {
-                          ncvars[ncvarid].coordvarids[i] = dimvarid;
-                          ncvars[ncvarid].ncoordvars++;
-                        }
-                    }
-                  else
-                    {
-                      int k;
-                      for ( k = 0; k < nchecked_vars; ++k )
-                        if ( strcmp(checked_vars[k], varname) == 0 ) break;
-
-                      if ( k == nchecked_vars )
-                        {
-                          if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname);
-                          Warning("%s - %s", nc_strerror(status), varname);
-                        }
-                    }
-
-                  if ( lstop ) break;
-                }
-
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
-            {
-              int lstop = FALSE;
-              int dimvarid;
-
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              char *pstring = attstring;
-
-              for ( int i = 0; i < MAX_AUXVARS; i++ )
-                {
-                  while ( isspace((int) *pstring) ) pstring++;
-                  if ( *pstring == 0 ) break;
-                  char *varname = pstring;
-                  while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
-                  if ( *pstring == 0 ) lstop = TRUE;
-                  *pstring++ = 0;
-
-                  int status = nc_inq_varid(ncid, varname, &dimvarid);
-                  if ( status == NC_NOERR )
-                    {
-                      cdfSetVar(ncvars, dimvarid, FALSE);
-                      //  if ( cdiIgnoreAttCoordinates == FALSE )
-                        {
-                          ncvars[ncvarid].auxvarids[i] = dimvarid;
-                          ncvars[ncvarid].nauxvars++;
-                        }
-                    }
-                  else
-                    Warning("%s - %s", nc_strerror(status), varname);
-
-                  if ( lstop ) break;
-                }
-
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              int nc_gmap_id;
-              int status = nc_inq_varid(ncid, attstring, &nc_gmap_id);
-              if ( status == NC_NOERR )
-                {
-                  ncvars[ncvarid].gmapid = nc_gmap_id;
-                  cdfSetVar(ncvars, ncvars[ncvarid].gmapid, FALSE);
-                }
-              else
-                Warning("%s - %s", nc_strerror(status), attstring);
-
-              cdfSetVar(ncvars, ncvarid, TRUE);
-            }
-          else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              strtolower(attstring);
-
-              if    ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN;
-              else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP;
-
-              if ( ncvars[ncvarid].ndims == 1 )
-                {
-                  cdfSetVar(ncvars, ncvarid, FALSE);
-                  cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
-                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
-                }
-            }
-          else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) )
-            {
-	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval);
-	      ncvars[ncvarid].deffillval = TRUE;
-	      /* cdfSetVar(ncvars, ncvarid, TRUE); */
-            }
-          else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
-            {
-	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
-	      ncvars[ncvarid].defmissval = TRUE;
-	      /* cdfSetVar(ncvars, ncvarid, TRUE); */
-            }
-          else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 )
-            {
-              if ( ncvars[ncvarid].lvalidrange == FALSE )
-                {
-                  extern int cdiIgnoreValidRange;
-                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
-                  if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
-                    {
-                      cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
-                      ncvars[ncvarid].lvalidrange = TRUE;
-                      if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 )
-                        ncvars[ncvarid].lunsigned = TRUE;
-                      /* cdfSetVar(ncvars, ncvarid, TRUE); */
-                    }
-                  else if ( lignore )
-                    {
-                      Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name);
-                    }
-                }
-            }
-          else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 )
-            {
-              if ( ncvars[ncvarid].lvalidrange == FALSE )
-                {
-                  extern int cdiIgnoreValidRange;
-                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
-                  if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
-                    {
-                      cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
-                      ncvars[ncvarid].lvalidrange = TRUE;
-                    }
-                  else if ( lignore )
-                    {
-                      Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name);
-                    }
-                }
-            }
-          else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 )
-            {
-              if ( ncvars[ncvarid].lvalidrange == FALSE )
-                {
-                  extern int cdiIgnoreValidRange;
-                  int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
-                  if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
-                    {
-                      cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
-                      ncvars[ncvarid].lvalidrange = TRUE;
-                    }
-                  else if ( lignore )
-                    {
-                      Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name);
-                    }
-                }
-            }
-          else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-              strtolower(attstring);
-
-              if ( memcmp(attstring, "true", 4) == 0 )
-                {
-                  ncvars[ncvarid].lunsigned = TRUE;
-                  /*
-                  ncvars[ncvarid].lvalidrange = TRUE;
-                  ncvars[ncvarid].validrange[0] = 0;
-                  ncvars[ncvarid].validrange[1] = 255;
-                  */
-                }
-	      /* cdfSetVar(ncvars, ncvarid, TRUE); */
-            }
-          else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
-            {
-	      cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-	      strtolower(attstring);
-
-	      if ( memcmp(attstring, "ignore", 6) == 0 )
-		{
-		  ncvars[ncvarid].ignore = TRUE;
-		  cdfSetVar(ncvars, ncvarid, FALSE);
-		}
-            }
-          else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
-            {
-              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-	      attlen = strlen(attstring);
-
-	      if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 )
-		{
-		    Warning("Unexpected axis attribute length for %s, ignored!", name);
-		}
-              else if ( nvdims == 0 && attlen == 1 )
-                {
-                  if ( attstring[0] == 'z' || attstring[0] == 'Z' )
-                    {
-                      cdfSetVar(ncvars, ncvarid, FALSE);
-                      ncvars[ncvarid].islev = TRUE;
-                    }
-                }
-	      else
-		{
-		  strtolower(attstring);
-                  int i;
-		  for ( i = 0; i < (int)attlen; ++i )
-		    {
-		      if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' &&
-			   attstring[i] != 'y' && attstring[i] != 'x' )
-			{
-			  Warning("Unexpected character in axis attribute for %s, ignored!", name);
-			  break;
-			}
-		    }
-
-		  if ( i == (int) attlen && (int) attlen == nvdims )
-		    {
-		      while ( attlen-- )
-			{
-			  if ( (int) attstring[attlen] == 't' )
-			    {
-			      if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
-			      cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS);
-			    }
-			  else if ( (int) attstring[attlen] == 'z' )
-			    {
-                              ncvars[ncvarid].zdim = dimidsp[attlen];
-                              cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS);
-
-                              if ( ncvars[ncvarid].ndims == 1 )
-                                {
-                                  cdfSetVar(ncvars, ncvarid, FALSE);
-                                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
-                                }
-			    }
-			  else if ( (int) attstring[attlen] == 'y' )
-			    {
-			      ncvars[ncvarid].ydim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS);
-
-			      if ( ncvars[ncvarid].ndims == 1 )
-				{
-				  cdfSetVar(ncvars, ncvarid, FALSE);
-				  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS;
-				}
-			    }
-			  else if ( (int) attstring[attlen] == 'x' )
-			    {
-			      ncvars[ncvarid].xdim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS);
-
-			      if ( ncvars[ncvarid].ndims == 1 )
-				{
-				  cdfSetVar(ncvars, ncvarid, FALSE);
-				  ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS;
-				}
-			    }
-			}
-		    }
-		}
-	    }
-	  else if ( ( strcmp(attname, "realization") == 0 )         ||
-	            ( strcmp(attname, "ensemble_members") == 0 )    ||
-	            ( strcmp(attname, "forecast_init_type") == 0 )    )
-	    {
-	      int temp;
-
-	      if( ncvars[ncvarid].ensdata == NULL )
-		ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) );
-
-	      cdfGetAttInt(ncid, ncvarid, attname, 1, &temp);
-
-	      if( strcmp(attname, "realization") == 0 )
-		ncvars[ncvarid].ensdata->ens_index = temp;
-	      else if( strcmp(attname, "ensemble_members") == 0 )
-		ncvars[ncvarid].ensdata->ens_count = temp;
-	      else if( strcmp(attname, "forecast_init_type") == 0 )
-		ncvars[ncvarid].ensdata->forecast_init_type = temp;
-
-	      cdfSetVar(ncvars, ncvarid, TRUE);
-	    }
-	  else
-	    {
-	      if ( ncvars[ncvarid].natts == 0 )
-		ncvars[ncvarid].atts
-                  = (int *) Malloc((size_t)nvatts * sizeof (int));
-
-	      ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
-	      /*
-	      int attrint;
-	      double attrflt;
-	      nc_type attrtype;
-	      cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
-	      cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
-	      if ( attlen == 1 && (attrtype == NC_INT || attrtype == NC_SHORT) )
-		{
-		  cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint);
-		  printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint);
-		}
-	      else if ( attlen == 1 && (attrtype == NC_FLOAT || attrtype == NC_DOUBLE) )
-		{
-		  cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt);
-		  printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt);
-		}
-	      else if ( attrtype == NC_CHAR )
-		{
-		  cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-		  attstring[attlen] = 0;
-		  printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring);
-		}
-	      else
-		printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
-	      */
-	    }
-	}
-    }
-
-  for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]);
-}
-
-static
-void setDimType(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
-{
-  int ndims;
-  int ncvarid, ncdimid;
-  int i;
-
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].isvar == TRUE )
-	{
-	  int lxdim = 0, lydim = 0, lzdim = 0/* , ltdim = 0 */;
-	  ndims = ncvars[ncvarid].ndims;
-	  for ( i = 0; i < ndims; i++ )
-	    {
-	      ncdimid = ncvars[ncvarid].dimids[i];
-	      if      ( ncdims[ncdimid].dimtype == X_AXIS ) cdfSetDim(ncvars, ncvarid, i, X_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdfSetDim(ncvars, ncvarid, i, T_AXIS);
-	    }
-
-	  if ( CDI_Debug )
-	    {
-	      Message("var %d %s", ncvarid, ncvars[ncvarid].name);
-	      for ( i = 0; i < ndims; i++ )
-		printf("  dim%d type=%d  ", i, ncvars[ncvarid].dimtype[i]);
-	      printf("\n");
-	    }
-
-	  for ( i = 0; i < ndims; i++ )
-	    {
-	      if      ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = TRUE;
-	      else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = TRUE;
-	      else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = TRUE;
-	      /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = TRUE; */
-	    }
-
-          if ( lxdim == FALSE && ncvars[ncvarid].xvarid != UNDEFID )
-            {
-              if (  ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = TRUE;
-            }
-
-          if ( lydim == FALSE && ncvars[ncvarid].yvarid != UNDEFID )
-            {
-              if (  ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = TRUE;
-            }
-
-          //   if ( ndims > 1 )
-            for ( i = ndims-1; i >= 0; i-- )
-              {
-                if ( ncvars[ncvarid].dimtype[i] == -1 )
-                  {
-                    if ( lxdim == FALSE )
-                      {
-                        cdfSetDim(ncvars, ncvarid, i, X_AXIS);
-                        lxdim = TRUE;
-                      }
-                    else if ( lydim == FALSE && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED )
-                      {
-                        cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
-                        lydim = TRUE;
-                      }
-                    else if ( lzdim == FALSE )
-                      {
-                        cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
-                        lzdim = TRUE;
-                      }
-                  }
-              }
-	}
-    }
-}
-
-/* verify coordinate vars - first scan (dimname == varname) */
-static
-void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid)
-{
-  int ncdimid, ncvarid;
-
-  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
-    {
-      ncvarid = ncdims[ncdimid].ncvarid;
-      if ( ncvarid != -1 )
-	{
-	  if ( ncvars[ncvarid].dimids[0] == timedimid )
-	    {
-              ncvars[ncvarid].istime = TRUE;
-	      ncdims[ncdimid].dimtype = T_AXIS;
-	      continue;
-	    }
-
-          if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue;
-
-	  if ( ncvars[ncvarid].units[0] != 0 )
-	    {
-	      if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
-		{
-		  ncvars[ncvarid].islon = TRUE;
-		  cdfSetVar(ncvars, ncvarid, FALSE);
-		  cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
-		  ncdims[ncdimid].dimtype = X_AXIS;
-		}
-	      else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
-		{
-		  ncvars[ncvarid].islat = TRUE;
-		  cdfSetVar(ncvars, ncvarid, FALSE);
-		  cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
-		  ncdims[ncdimid].dimtype = Y_AXIS;
-		}
-	      else if ( unitsIsPressure(ncvars[ncvarid].units) )
-		{
-		  ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
-		}
-	      else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
-		{
-		  if      ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
-		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
-		  else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
-		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
-		  else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
-		}
-	      else if ( isDBLAxis(ncvars[ncvarid].longname) )
-                {
-                  ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
-		}
-	      else if ( unitsIsHeight(ncvars[ncvarid].units) )
-		{
-		  if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
-		    ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
-		  else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
-		}
-	    }
-          else
-            {
-              if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 ||
-                    strcmp(ncvars[ncvarid].longname, "generalized height") == 0) &&
-                   strcmp(ncvars[ncvarid].stdname, "height") == 0 )
-                  ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE;
-            }
-
-	  if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
-               ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
-	    {
-	      if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
-		{
-		  ncvars[ncvarid].islon = TRUE;
-		  cdfSetVar(ncvars, ncvarid, FALSE);
-		  cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
-		  ncdims[ncdimid].dimtype = X_AXIS;
-		  continue;
-		}
-	      else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
-		{
-		  ncvars[ncvarid].islat = TRUE;
-		  cdfSetVar(ncvars, ncvarid, FALSE);
-		  cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
-		  ncdims[ncdimid].dimtype = Y_AXIS;
-		  continue;
-		}
-	    }
-
-	  if ( ncvars[ncvarid].zaxistype != UNDEFID )
-	    {
-              ncvars[ncvarid].islev = TRUE;
-	      cdfSetVar(ncvars, ncvarid, FALSE);
-	      cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
-	      ncdims[ncdimid].dimtype = Z_AXIS;
-	    }
-	}
-    }
-}
-
-/* verify coordinate vars - second scan (all other variables) */
-static
-void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
-{
-  int ncvarid;
-
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].isvar == 0 )
-	{
-	  if ( ncvars[ncvarid].units[0] != 0 )
-	    {
-	      if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
-		{
-		  ncvars[ncvarid].islon = TRUE;
-		  continue;
-		}
-	      else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
-		{
-		  ncvars[ncvarid].islat = TRUE;
-		  continue;
-		}
-	      else if ( unitsIsPressure(ncvars[ncvarid].units) )
-		{
-		  ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
-		  continue;
-		}
-	      else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
-		{
-		  if      ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
-		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
-		  else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
-		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
-		  else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
-		    ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
-		  continue;
-		}
-	      else if ( isDBLAxis(ncvars[ncvarid].longname) )
-		{
-                  ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
-		  continue;
-		}
-	      else if ( unitsIsHeight(ncvars[ncvarid].units) )
-		{
-		  if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
-		    ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
-		  else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
-		    ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
-		  continue;
-		}
-            }
-
-	  /* not needed anymore for rotated grids */
-	  if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
-               ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
-	    {
-	      if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
-		{
-		  ncvars[ncvarid].islon = TRUE;
-		  continue;
-		}
-	      else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
-		{
-		  ncvars[ncvarid].islat = TRUE;
-		  continue;
-		}
-	    }
-	}
-    }
-}
-
-#if defined (PROJECTION_TEST)
-static
-void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID)
-{
-  int iatt, nvatts;
-  size_t attlen;
-  char attname[CDI_MAX_NAME];
-  nc_type xtype;
-
-  cdf_inq_varnatts(ncfileID, ncvarID, &nvatts);
-
-  for ( iatt = 0; iatt < nvatts; iatt++ )
-    {
-      cdf_inq_attname(ncfileID, ncvarID, iatt, attname);
-      cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype);
-      cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen);
-
-      //  printf("%s %d\n", attname, (int)attlen);
-    }
-
-}
-#endif
-
-static
-void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
-{
-  if ( ncvar->chunked )
-    {
-      int ndims = ncvar->ndims;
-
-      if ( grid->type == GRID_UNSTRUCTURED )
-        {
-          if ( ncvar->chunks[ndims-1] == grid->size )
-            ncvar->chunktype = CHUNK_GRID;
-          else
-            ncvar->chunktype = CHUNK_AUTO;
-        }
-      else
-        {
-          if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 &&
-               grid->xsize == ncvar->chunks[ndims-1] &&
-               grid->ysize == ncvar->chunks[ndims-2] )
-            ncvar->chunktype = CHUNK_GRID;
-          else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] )
-            ncvar->chunktype = CHUNK_LINES;
-          else
-            ncvar->chunktype = CHUNK_AUTO;
-        }
-    }
-}
-
-static struct gridVirtTable cdfLazyGridVtable;
-static double *cdfPendingLoad;
-#ifdef HAVE_LIBPTHREAD
-static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT;
-#else
-static bool cdfLazyInitialized;
-#endif
-
-struct cdfLazyGrid
-{
-  grid_t base;
-  const struct gridVirtTable *baseVtable;
-  struct {
-    int datasetNCId, varNCId;
-  } cellAreaGet, xBoundsGet, yBoundsGet;
-  struct xyValGet {
-    double scalefactor, addoffset;
-    size_t start[3], count[3], size, dimsize;
-    int datasetNCId, varNCId;
-    short ndims;
-  } xValsGet, yValsGet;
-#ifdef HAVE_LIBPTHREAD
-  pthread_mutex_t loadSerialize;
-#endif
-};
-
-#ifdef HAVE_LIBPTHREAD
-#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize))
-#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize))
-#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize))
-#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL)
-#else
-#define lock_lazy_load(plGrid)
-#define unlock_lazy_load(plGrid)
-#define destroy_lazy_load_lock(plGrid)
-#define init_lazy_load_lock(plGrid)
-#endif
-
-static void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid)
-{
-  lazyGrid->base.extraData = NULL;
-  if (lazyGrid->base.area == cdfPendingLoad)
-    lazyGrid->base.area = NULL;
-  if (lazyGrid->base.xvals == cdfPendingLoad)
-    lazyGrid->base.xvals = NULL;
-  if (lazyGrid->base.yvals == cdfPendingLoad)
-    lazyGrid->base.yvals = NULL;
-  if (lazyGrid->base.xbounds == cdfPendingLoad)
-    lazyGrid->base.xbounds = NULL;
-  if (lazyGrid->base.ybounds == cdfPendingLoad)
-    lazyGrid->base.ybounds = NULL;
-  destroy_lazy_load_lock(lazyGrid);
-}
-
-static void cdfLazyGridDelete(grid_t *grid)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy;
-  cdfLazyGridDestroy(cdfGrid);
-  baseDestroy(grid);
-}
-
-static void cdfLazyGridDestroyOnce(void)
-{
-  /*
-#ifdef HAVE_MMAP
-  size_t pgSize = cdiGetPageSize(false);
-  munmap(cdfPendingLoad, pgSize);
-#endif
-  */
-}
-
-static void
-cdfLazyGridDefArea(grid_t *grid, const double *area)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(cdfGrid);
-  if (grid->area == cdfPendingLoad)
-    grid->area = NULL;
-  cdfGrid->cellAreaGet.datasetNCId = -1;
-  cdfGrid->cellAreaGet.varNCId = -1;
-  cdfGrid->baseVtable->defArea(grid, area);
-  unlock_lazy_load(cdfGrid);
-}
-
-
-static const double *
-cdfLazyGridInqAreaPtr(grid_t *grid)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  if (grid->area == cdfPendingLoad)
-    {
-      grid->area = (double *)Malloc((size_t)grid->size * sizeof(double));
-      cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId,
-                         lazyGrid->cellAreaGet.varNCId, grid->area);
-    }
-  unlock_lazy_load(lazyGrid);
-  return lazyGrid->baseVtable->inqAreaPtr(grid);
-}
-
-static void
-cdfLazyGridInqArea(grid_t *grid, double *area)
-{
-  grid->vtable->inqAreaPtr(grid);
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lazyGrid->baseVtable->inqArea(grid, area);
-}
-
-
-static void
-cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp)
-{
-  double *grid_vals
-    = (double *)Malloc(valsGet->size * sizeof (double));
-  *valsp = grid_vals;
-  if ( valsGet->ndims == 3 )
-    cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId,
-                        valsGet->start, valsGet->count, grid_vals);
-  else
-    cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals);
-  scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor);
-}
-
-static const double *
-cdfLazyGridInqXValsPtr(grid_t *grid)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  if (grid->xvals == cdfPendingLoad)
-    cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->xvals);
-  unlock_lazy_load(lazyGrid);
-  return lazyGrid->baseVtable->inqXValsPtr(grid);
-}
-
-static const double *
-cdfLazyGridInqYValsPtr(grid_t *grid)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  if (grid->yvals == cdfPendingLoad)
-    cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->yvals);
-  unlock_lazy_load(lazyGrid);
-  return lazyGrid->baseVtable->inqYValsPtr(grid);
-}
-
-static double
-cdfLazyGridInqXYVal(grid_t *grid, size_t index,
-                    const struct xyValGet *valsGet, double *vals,
-                    const double *(*inqValsPtr)(grid_t *gridptr))
-{
-  size_t size = valsGet->size;
-  double v;
-  if ( vals == cdfPendingLoad )
-    {
-      /* prevent full load if only first/last values get inspected */
-      if ( index == 0 || index == size - 1 )
-        {
-          size_t indexND[3];
-          if ( valsGet->ndims == 3 )
-            {
-              indexND[0] = 0;
-              indexND[1] = index / valsGet->count[2];
-              indexND[2] = index % valsGet->count[2];
-            }
-          else if ( valsGet->ndims == 2)
-            {
-              indexND[0] = index / (size_t)grid->xsize;
-              indexND[1] = index % (size_t)grid->xsize;
-            }
-          else
-            indexND[0] = index;
-          cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId,
-                              indexND, &v);
-        }
-      else
-        {
-          const double *grid_vals = inqValsPtr(grid);
-          v = grid_vals[index];
-        }
-    }
-  else if ( vals )
-    v = vals[index];
-  else
-    v = 0.0;
-  return v;
-}
-
-static void
-cdfLazyGridDefXVals(grid_t *grid, const double *vals)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(cdfGrid);
-  if (grid->xvals == cdfPendingLoad)
-    grid->xvals = NULL;
-  cdfGrid->xValsGet.datasetNCId = -1;
-  cdfGrid->xValsGet.varNCId = -1;
-  cdfGrid->baseVtable->defXVals(grid, vals);
-  unlock_lazy_load(cdfGrid);
-}
-
-static void
-cdfLazyGridDefYVals(grid_t *grid, const double *vals)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(cdfGrid);
-  if (grid->yvals == cdfPendingLoad)
-    grid->yvals = NULL;
-  cdfGrid->yValsGet.datasetNCId = -1;
-  cdfGrid->yValsGet.varNCId = -1;
-  cdfGrid->baseVtable->defYVals(grid, vals);
-  unlock_lazy_load(cdfGrid);
-}
-
-static double
-cdfLazyGridInqXVal(grid_t *grid, int index)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet,
-                                  grid->xvals, grid->vtable->inqXValsPtr);
-  unlock_lazy_load(lazyGrid);
-  return rv;
-}
-
-static double
-cdfLazyGridInqYVal(grid_t *grid, int index)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet,
-                                  grid->yvals, grid->vtable->inqYValsPtr);
-  unlock_lazy_load(lazyGrid);
-  return rv;
-}
-
-static bool
-cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
-                       struct cdfLazyGrid *lazyGridTest)
-{
-  struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet,
-    *valsGetYRef = &lazyGridRef->yValsGet,
-    *valsGetXTest = &lazyGridTest->xValsGet,
-    *valsGetYTest = &lazyGridTest->yValsGet;
-  if (valsGetXRef->datasetNCId == -1
-      || valsGetXTest->datasetNCId == -1
-      || valsGetYRef->datasetNCId == -1
-      || valsGetYTest->datasetNCId == -1)
-    return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base,
-                                                  &lazyGridTest->base);
-  return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId
-    ||   valsGetXRef->varNCId     != valsGetXTest->varNCId
-    ||   valsGetYRef->datasetNCId != valsGetYTest->datasetNCId
-    ||   valsGetYRef->varNCId     != valsGetYTest->varNCId;
-}
-
-static bool
-cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
-{
-  bool diff;
-  struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
-  if (gridTest->vtable == &cdfLazyGridVtable)
-    diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
-  else
-    diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest);
-  return diff;
-}
-
-static bool
-cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest)
-{
-  bool diff;
-  struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
-  if (gridTest->vtable == &cdfLazyGridVtable)
-    diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
-  else
-    diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest);
-  return diff;
-}
-
-
-static const double *
-cdfLazyGridInqXBoundsPtr(grid_t *grid)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  if (grid->xbounds == cdfPendingLoad)
-    {
-      grid->xbounds = (double *)Malloc((size_t)grid->nvertex
-                                       * (size_t)grid->size * sizeof(double));
-      cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId,
-                         lazyGrid->xBoundsGet.varNCId, grid->xbounds);
-    }
-  unlock_lazy_load(lazyGrid);
-  return lazyGrid->baseVtable->inqXBoundsPtr(grid);
-}
-
-static void
-cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(cdfGrid);
-  if (grid->xbounds == cdfPendingLoad)
-    grid->xbounds = NULL;
-  cdfGrid->xBoundsGet.datasetNCId = -1;
-  cdfGrid->xBoundsGet.varNCId = -1;
-  cdfGrid->baseVtable->defXBounds(grid, xbounds);
-  unlock_lazy_load(cdfGrid);
-}
-
-static void
-cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds)
-{
-  struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(cdfGrid);
-  if (grid->ybounds == cdfPendingLoad)
-    grid->ybounds = NULL;
-  cdfGrid->yBoundsGet.datasetNCId = -1;
-  cdfGrid->yBoundsGet.varNCId = -1;
-  cdfGrid->baseVtable->defYBounds(grid, ybounds);
-  unlock_lazy_load(cdfGrid);
-}
-
-static const double *
-cdfLazyGridInqYBoundsPtr(grid_t *grid)
-{
-  struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
-  lock_lazy_load(lazyGrid);
-  if (grid->ybounds == cdfPendingLoad)
-    {
-      grid->ybounds = (double *)Malloc((size_t)grid->nvertex
-                                       * (size_t)grid->size * sizeof(double));
-      cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId,
-                         lazyGrid->yBoundsGet.varNCId, grid->ybounds);
-    }
-  unlock_lazy_load(lazyGrid);
-  return lazyGrid->baseVtable->inqYBoundsPtr(grid);
-}
-
-static void
-cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup)
-{
-  struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup,
-    *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig;
-  lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
-  lazyGridDup->baseVtable = lazyGridOrig->baseVtable;
-  lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet;
-  lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet;
-  lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet;
-  lazyGridDup->xValsGet = lazyGridOrig->xValsGet;
-  lazyGridDup->yValsGet = lazyGridOrig->yValsGet;
-  init_lazy_load_lock(lazyGridDup);
-}
-
-static void
-cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup)
-{
-  size_t nrowlon = (size_t)gridptrOrig->nrowlon;
-  size_t gridsize = (size_t)gridptrOrig->size;
-  int gridtype = gridptrOrig->type;
-  int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
-  if ( nrowlon )
-    {
-      gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
-      memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
-    }
-
-  if ( gridptrOrig->xvals != NULL && gridptrOrig->xvals != cdfPendingLoad )
-    {
-      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->xsize;
-
-      gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
-    }
-
-  if ( gridptrOrig->yvals != NULL && gridptrOrig->yvals != cdfPendingLoad )
-    {
-      size_t size  = irregular ? gridsize : (size_t)gridptrOrig->ysize;
-
-      gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
-    }
-
-  if ( gridptrOrig->xbounds != NULL && gridptrOrig->xbounds != cdfPendingLoad )
-    {
-      size_t size  = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
-        * (size_t)gridptrOrig->nvertex;
-
-      gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
-    }
-
-  if ( gridptrOrig->ybounds != NULL && gridptrOrig->ybounds != cdfPendingLoad )
-    {
-      size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
-        * (size_t)gridptrOrig->nvertex;
-
-      gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
-      memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
-    }
-
-  {
-    if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad )
-      {
-        size_t size = gridsize;
-
-        gridptrDup->area = (double *)Malloc(size * sizeof (double));
-        memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double));
-      }
-  }
-
-  if ( gridptrOrig->mask != NULL )
-    {
-      size_t size = gridsize;
-
-      gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
-      memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
-    }
-
-  if ( gridptrOrig->mask_gme != NULL )
-    {
-      size_t size = gridsize;
-
-      gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
-      memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
-    }
-}
-
-static grid_t *
-cdfLazyGridCopy(grid_t *gridptrOrig)
-{
-  struct cdfLazyGrid *lazyGridDup
-    = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup));
-  gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
-  gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base);
-  return &lazyGridDup->base;
-}
-
-static void
-cdfLazyGridInitOnce(void)
-{
-  cdfLazyGridVtable = cdiGridVtable;
-  cdfLazyGridVtable.destroy = cdfLazyGridDelete;
-  cdfLazyGridVtable.copy = cdfLazyGridCopy;
-  cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields;
-  cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields;
-  cdfLazyGridVtable.defArea = cdfLazyGridDefArea;
-  cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr;
-  cdfLazyGridVtable.inqArea = cdfLazyGridInqArea;
-  cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr;
-  cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr;
-  cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal;
-  cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal;
-  cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals;
-  cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals;
-  cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull;
-  cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO;
-  cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds;
-  cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds;
-  cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr;
-  cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr;
-  /* create inaccessible memory area, if possible, this serves as
-   * dummy value for pointers to data not yet loaded */
-  /*
-#ifdef HAVE_MMAP
-  {
-    size_t pgSize = cdiGetPageSize(false);
-    static const char devZero[] = "/dev/zero";
-    int fd = open(devZero, O_RDWR);
-    if (fd == -1)
-      SysError("Could not open %s to map anonymous memory", devZero);
-    void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0);
-    if (cdfInvalid == MAP_FAILED)
-      SysError("Could not mmap anonymous memory");
-    cdfPendingLoad = cdfInvalid;
-    int rc = close(fd);
-    if (rc == -1)
-      SysError("Could not close %s file handle %d after mapping anonymous"
-               " memory", devZero, fd);
-  }
-#else
-  */
-  cdfPendingLoad = (double *)&cdfPendingLoad;
-  //#endif
-  atexit(cdfLazyGridDestroyOnce);
-#ifndef HAVE_LIBPTHREAD
-  cdfLazyInitialized = true;
-#endif
-}
-
-static void
-cdfBaseGridInit(grid_t *grid, int gridtype)
-{
-  grid_init(grid);
-  cdiGridTypeInit(grid, gridtype, 0);
-}
-
-static void
-cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype)
-{
-#ifdef HAVE_LIBPTHREAD
-  pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce);
-#else
-  if (cdfLazyInitialized) ; else cdfLazyGridInitOnce();
-#endif
-  cdfBaseGridInit(&grid->base, gridtype);
-  grid->baseVtable = grid->base.vtable;
-  grid->cellAreaGet.datasetNCId = -1;
-  grid->cellAreaGet.varNCId = -1;
-  grid->xValsGet.datasetNCId = -1;
-  grid->xValsGet.varNCId = -1;
-  grid->yValsGet.datasetNCId = -1;
-  grid->yValsGet.varNCId = -1;
-  grid->xBoundsGet.datasetNCId = -1;
-  grid->xBoundsGet.varNCId = -1;
-  grid->yBoundsGet.datasetNCId = -1;
-  grid->yBoundsGet.varNCId = -1;
-  grid->base.vtable = &cdfLazyGridVtable;
-  init_lazy_load_lock(grid);
-}
-
-static void
-cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
-{
-  struct cdfLazyGrid *restrict grid = *gridpptr;
-  if (!grid)
-    *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid));
-  cdfLazyGridInit(grid, gridtype);
-}
-
-static void
-cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
-{
-  struct cdfLazyGrid *restrict grid = *gridpptr;
-  if (!grid)
-    *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t));
-  cdfBaseGridInit((grid_t*)grid, gridtype);
-}
-
-
-/* define all input grids */
-static
-void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used)
-{
-  int ltwarn = TRUE;
-  struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL;
-#define grid (&lazyGrid->base)
-#define proj (&lazyProj->base)
-
-  for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid )
-    {
-      if ( ncvars[ncvarid].isvar && ncvars[ncvarid].gridID == UNDEFID )
-	{
-          int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
-	  int xdimid = -1, ydimid = -1;
-          int vdimid = -1;
-	  int islon = 0, islat = 0;
-	  int nxdims = 0, nydims = 0;
-          size_t size = 0;
-          size_t xsize = 0, ysize = 0;
-	  double yinc = 0;
-          struct addIffNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 },
-            gridAdded  = { .Id = CDI_UNDEFID, .isNew = 0 };
-
-	  int ndims = ncvars[ncvarid].ndims;
-	  for ( int i = 0; i < ndims; i++ )
-	    {
-	      if ( ncvars[ncvarid].dimtype[i] == X_AXIS && nxdims < 2 )
-		{
-		  xdimids[nxdims] = ncvars[ncvarid].dimids[i];
-		  nxdims++;
-		}
-	      else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS && nydims < 2 )
-		{
-		  ydimids[nydims] = ncvars[ncvarid].dimids[i];
-		  nydims++;
-		}
-	    }
-
-	  if ( nxdims == 2 )
-	    {
-	      xdimid = xdimids[1];
-	      ydimid = xdimids[0];
-	    }
-	  else if ( nydims == 2 )
-	    {
-	      xdimid = ydimids[1];
-	      ydimid = ydimids[0];
-	    }
-	  else
-	    {
-	      xdimid = xdimids[0];
-	      ydimid = ydimids[0];
-	    }
-
-	  int xvarid = ncvars[ncvarid].xvarid != UNDEFID
-	    ? ncvars[ncvarid].xvarid
-            : (xdimid != UNDEFID ? ncdims[xdimid].ncvarid : -1);
-          int yvarid = ncvars[ncvarid].yvarid != UNDEFID
-            ? ncvars[ncvarid].yvarid
-            : (ydimid != UNDEFID ? ncdims[ydimid].ncvarid : -1);
-
-	  /*
-	  if ( xdimid != UNDEFID )
-	    xvarid = ncdims[xdimid].ncvarid;
-	  if ( xvarid == UNDEFID && ncvars[ncvarid].xvarid != UNDEFID )
-	    xvarid = ncvars[ncvarid].xvarid;
-
-	  if ( ydimid != UNDEFID )
-	    yvarid = ncdims[ydimid].ncvarid;
-	  if ( yvarid == UNDEFID && ncvars[ncvarid].yvarid != UNDEFID )
-	    yvarid = ncvars[ncvarid].yvarid;
-	  */
-
-	  if ( xdimid != UNDEFID ) xsize = ncdims[xdimid].len;
-	  if ( ydimid != UNDEFID ) ysize = ncdims[ydimid].len;
-
-	  if ( ydimid == UNDEFID && yvarid != UNDEFID )
-	    {
-	      if ( ncvars[yvarid].ndims == 1 )
-		{
-		  ydimid = ncvars[yvarid].dimids[0];
-		  ysize  = ncdims[ydimid].len;
-		}
-	    }
-
-	  if ( ncvars[ncvarid].gridtype == UNDEFID || ncvars[ncvarid].gridtype == GRID_GENERIC )
-	    if ( xdimid != UNDEFID && xdimid == ydimid && nydims == 0 ) ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
-
-          if (CDI_netcdf_lazy_grid_load)
-            {
-              cdfLazyGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
-              cdfLazyGridRenew(&lazyProj, GRID_PROJECTION);
-            }
-          else
-            {
-              cdfBaseGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
-              cdfBaseGridRenew(&lazyProj, GRID_PROJECTION);
-            }
-
-	  grid->prec  = DATATYPE_FLT64;
-	  grid->trunc = ncvars[ncvarid].truncation;
-
-	  if ( ncvars[ncvarid].gridtype == GRID_TRAJECTORY )
-	    {
-	      if ( ncvars[ncvarid].xvarid == UNDEFID )
-		Error("Longitude coordinate undefined for %s!", ncvars[ncvarid].name);
-	      if ( ncvars[ncvarid].yvarid == UNDEFID )
-		Error("Latitude coordinate undefined for %s!", ncvars[ncvarid].name);
-	    }
-	  else
-	    {
-	      size_t start[3], count[3];
-	      int ltgrid = FALSE;
-
-	      if ( xvarid != UNDEFID && yvarid != UNDEFID )
-		{
-		  if ( ncvars[xvarid].ndims != ncvars[yvarid].ndims )
-		    {
-		      Warning("Inconsistent grid structure for variable %s!", ncvars[ncvarid].name);
-		      ncvars[ncvarid].xvarid = UNDEFID;
-		      ncvars[ncvarid].yvarid = UNDEFID;
-		      xvarid = UNDEFID;
-		      yvarid = UNDEFID;
-		    }
-
-		  if ( ncvars[xvarid].ndims > 2 || ncvars[yvarid].ndims > 2 )
-		    {
-		      if ( ncvars[xvarid].ndims == 3 && ncvars[xvarid].dimids[0] == timedimid &&
-			   ncvars[yvarid].ndims == 3 && ncvars[yvarid].dimids[0] == timedimid )
-			{
-			  if ( ltwarn )
-			    Warning("Time varying grids unsupported, using grid at time step 1!");
-			  ltgrid = TRUE;
-			  ltwarn = FALSE;
-			  start[0] = start[1] = start[2] = 0;
-			  count[0] = 1; count[1] = ysize; count[2] = xsize;
-			}
-		      else
-			{
-			  Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvars[ncvarid].name);
-			  ncvars[ncvarid].xvarid = UNDEFID;
-			  ncvars[ncvarid].yvarid = UNDEFID;
-			  xvarid = UNDEFID;
-			  yvarid = UNDEFID;
-			}
-		    }
-		}
-
-              if ( xvarid != UNDEFID )
-                {
-                  if ( ncvars[xvarid].ndims > 3 || (ncvars[xvarid].ndims == 3 && ltgrid == FALSE) )
-                    {
-                      Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims);
-                      //ncvars[ncvarid].xvarid = UNDEFID;
-                      xvarid = UNDEFID;
-                    }
-                }
-
-              if ( yvarid != UNDEFID )
-                {
-                  if ( ncvars[yvarid].ndims > 3 || (ncvars[yvarid].ndims == 3 && ltgrid == FALSE) )
-                    {
-                      Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims);
-                      //ncvars[ncvarid].yvarid = UNDEFID;
-                      yvarid = UNDEFID;
-                    }
-                }
-
-              if ( xvarid != UNDEFID )
-		{
-                  bool skipvar = true;
-		  islon = ncvars[xvarid].islon;
-		  ndims = ncvars[xvarid].ndims;
-		  if ( ndims == 2 || ndims == 3 )
-		    {
-		      ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
-		      size = xsize*ysize;
-		      /* Check size of 2 dimensional coordinate variables */
-                      int dimid = ncvars[xvarid].dimids[ndims-2];
-                      size_t dimsize1 = ncdims[dimid].len;
-                      dimid = ncvars[xvarid].dimids[ndims-1];
-                      size_t dimsize2 = ncdims[dimid].len;
-                      skipvar = dimsize1*dimsize2 != size;
-		    }
-		  else if ( ndims == 1 )
-		    {
-		      size = xsize;
-		      /* Check size of 1 dimensional coordinate variables */
-                      int dimid = ncvars[xvarid].dimids[0];
-                      size_t dimsize = ncdims[dimid].len;
-                      skipvar = dimsize != size;
-		    }
-		  else if ( ndims == 0 && xsize == 0 )
-		    {
-                      size = xsize = 1;
-                      skipvar = false;
-		    }
-
-                  if ( skipvar )
-                    {
-                      Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
-                      ncvars[ncvarid].isvar = -1;
-                      continue;
-                    }
-
-		  if ( ncvars[xvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
-                  if (CDI_netcdf_lazy_grid_load)
-                    {
-                      lazyGrid->xValsGet = (struct xyValGet){
-                        .scalefactor = ncvars[xvarid].scalefactor,
-                        .addoffset = ncvars[xvarid].addoffset,
-                        .start = { start[0], start[1], start[2] },
-                        .count = { count[0], count[1], count[2] },
-                        .size = size,
-                        .datasetNCId = ncvars[xvarid].ncid,
-                        .varNCId = xvarid,
-                        .ndims = (short)ndims,
-                      };
-                      grid->xvals = cdfPendingLoad;
-                    }
-                  else
-                    {
-                      grid->xvals = (double *) Malloc(size*sizeof(double));
-                      if ( ltgrid )
-                        cdf_get_vara_double(ncvars[xvarid].ncid, xvarid,
-                                            start, count, grid->xvals);
-                      else
-                        cdf_get_var_double(ncvars[xvarid].ncid, xvarid,
-                                           grid->xvals);
-                      scale_add(size, grid->xvals,
-                                ncvars[xvarid].addoffset,
-                                ncvars[xvarid].scalefactor);
-                    }
-		  strcpy(grid->xname, ncvars[xvarid].name);
-		  strcpy(grid->xlongname, ncvars[xvarid].longname);
-		  strcpy(grid->xunits, ncvars[xvarid].units);
-		  /* don't change the name !!! */
-		  /*
-		  if ( (len = strlen(grid->xname)) > 2 )
-		    if ( grid->xname[len-2] == '_' && isdigit((int) grid->xname[len-1]) )
-		      grid->xname[len-2] = 0;
-		  */
-		}
-
-	      if ( yvarid != UNDEFID )
-		{
-                  bool skipvar = true;
-		  islat = ncvars[yvarid].islat;
-		  ndims = ncvars[yvarid].ndims;
-		  if ( ndims == 2 || ndims == 3 )
-		    {
-		      ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
-		      size = xsize*ysize;
-		      /* Check size of 2 dimensional coordinate variables */
-		      {
-			int dimid;
-			size_t dimsize1, dimsize2;
-			dimid = ncvars[yvarid].dimids[ndims-2];
-			dimsize1 = ncdims[dimid].len;
-			dimid = ncvars[yvarid].dimids[ndims-1];
-			dimsize2 = ncdims[dimid].len;
-			skipvar = dimsize1*dimsize2 != size;
-		      }
-		    }
-		  else if ( ndims == 1 )
-		    {
-		      if ( (int) ysize == 0 ) size = xsize;
-		      else                    size = ysize;
-
-		      /* Check size of 1 dimensional coordinate variables */
-		      {
-			int dimid;
-			size_t dimsize;
-			dimid = ncvars[yvarid].dimids[0];
-			dimsize = ncdims[dimid].len;
-			skipvar = dimsize != size;
-		      }
-		    }
-		  else if ( ndims == 0 && ysize == 0 )
-		    {
-                      size = ysize = 1;
-                      skipvar = false;
-		    }
-
-                  if ( skipvar )
-                    {
-                      Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
-                      ncvars[ncvarid].isvar = -1;
-                      continue;
-                    }
-
-		  if ( ncvars[yvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
-                  /* see below for when it's impossible to operate
-                   * without y values */
-                  if ( !CDI_netcdf_lazy_grid_load
-                       || ((ncvars[ncvarid].gridtype == UNDEFID ||
-                            ncvars[ncvarid].gridtype == GRID_GENERIC)
-                           && islat && (islon || xsize == 0)) )
-                    {
-                      grid->yvals = (double *) Malloc(size*sizeof(double));
-
-                      if ( ltgrid )
-                        cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid->yvals);
-                      else
-                        cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid->yvals);
-
-                      scale_add(size, grid->yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor);
-
-                      /* don't change the name !!! */
-                      /*
-                        if ( (len = strlen(grid->yname)) > 2 )
-                        if ( grid->yname[len-2] == '_' && isdigit((int) grid->yname[len-1]) )
-                        grid->yname[len-2] = 0;
-                      */
-                      if ( islon && (int) ysize > 1 )
-                        {
-                          yinc = fabs(grid->yvals[0] - grid->yvals[1]);
-                          for ( size_t i = 2; i < ysize; i++ )
-                            if ( (fabs(grid->yvals[i-1] - grid->yvals[i]) - yinc) > (yinc/1000) )
-                              {
-                                yinc = 0;
-                                break;
-                              }
-                        }
-                    }
-                  else
-                    {
-                      lazyGrid->yValsGet = (struct xyValGet){
-                        .scalefactor = ncvars[yvarid].scalefactor,
-                        .addoffset = ncvars[yvarid].addoffset,
-                        .start = { start[0], start[1], start[2] },
-                        .count = { count[0], count[1], count[2] },
-                        .size = size,
-                        .datasetNCId = ncvars[yvarid].ncid,
-                        .varNCId = yvarid,
-                        .ndims = (short)ndims,
-                      };
-                      grid->yvals = cdfPendingLoad;
-                    }
-                  strcpy(grid->yname, ncvars[yvarid].name);
-                  strcpy(grid->ylongname, ncvars[yvarid].longname);
-                  strcpy(grid->yunits, ncvars[yvarid].units);
-		}
-
-	      if      ( (int) ysize == 0 ) size = xsize;
-	      else if ( (int) xsize == 0 ) size = ysize;
-	      else if ( ncvars[ncvarid].gridtype == GRID_UNSTRUCTURED ) size = xsize;
-	      else                         size = xsize*ysize;
-	    }
-
-	  if ( ncvars[ncvarid].gridtype == UNDEFID ||
-	       ncvars[ncvarid].gridtype == GRID_GENERIC )
-	    {
-	      if ( islat && (islon || xsize == 0) )
-		{
-		  if ( isGaussGrid(ysize, yinc, grid->yvals) )
-                    {
-                      ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
-                      grid->np = (int)(ysize/2);
-                    }
-                  else
-		    ncvars[ncvarid].gridtype = GRID_LONLAT;
-		}
-	      else if ( islon && !islat && ysize == 0 )
-		{
-		  ncvars[ncvarid].gridtype = GRID_LONLAT;
-		}
-	      else
-		ncvars[ncvarid].gridtype = GRID_GENERIC;
-	    }
-
-	  switch (ncvars[ncvarid].gridtype)
-	    {
-	    case GRID_GENERIC:
-	    case GRID_LONLAT:
-	    case GRID_GAUSSIAN:
-	    case GRID_UNSTRUCTURED:
-	    case GRID_CURVILINEAR:
-	      {
-		grid->size  = (int)size;
-		grid->xsize = (int)xsize;
-		grid->ysize = (int)ysize;
-		if ( xvarid != UNDEFID )
-		  {
-		    grid->xdef  = 1;
-		    if ( ncvars[xvarid].bounds != UNDEFID )
-		      {
-			int nbdims = ncvars[ncvars[xvarid].bounds].ndims;
-			if ( nbdims == 2 || nbdims == 3 )
-			  {
-                            vdimid = ncvars[ncvars[xvarid].bounds].dimids[nbdims-1];
-			    size_t nvertex = ncdims[vdimid].len;
-			    grid->nvertex = (int)nvertex;
-                            if (CDI_netcdf_lazy_grid_load)
-                              {
-                                lazyGrid->xBoundsGet.datasetNCId
-                                  = ncvars[xvarid].ncid;
-                                lazyGrid->xBoundsGet.varNCId
-                                  = ncvars[xvarid].bounds;
-                                grid->xbounds = cdfPendingLoad;
-                              }
-                            else
-                              {
-                                grid->xbounds
-                                  = (double *)Malloc(nvertex * size
-                                                     * sizeof(double));
-                                cdf_get_var_double(ncvars[xvarid].ncid,
-                                                   ncvars[xvarid].bounds,
-                                                   grid->xbounds);
-                              }
-			  }
-		      }
-		  }
-		if ( yvarid != UNDEFID )
-		  {
-		    grid->ydef  = 1;
-		    if ( ncvars[yvarid].bounds != UNDEFID )
-		      {
-			int nbdims = ncvars[ncvars[yvarid].bounds].ndims;
-			if ( nbdims == 2 || nbdims == 3 )
-			  {
-			    /* size_t nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len;
-			    if ( nvertex != grid->nvertex )
-			      Warning("nvertex problem! nvertex x %d, nvertex y %d",
-				      grid->nvertex, (int) nvertex);
-			    */
-                            if (CDI_netcdf_lazy_grid_load)
-                              {
-                                lazyGrid->yBoundsGet.datasetNCId
-                                  = ncvars[yvarid].ncid;
-                                lazyGrid->yBoundsGet.varNCId
-                                  = ncvars[yvarid].bounds;
-                                grid->ybounds = cdfPendingLoad;
-                              }
-                            else
-                              {
-                                vdimid = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
-                                size_t nvertex = ncdims[vdimid].len;
-                                /*
-                                  if ( nvertex != grid->nvertex )
-                                  Warning("nvertex problem! nvertex x %d, nvertex y %d",
-                                  grid->nvertex, (int) nvertex);
-                                */
-                                grid->ybounds
-                                  = (double *)Malloc(nvertex * size
-                                                     * sizeof(double));
-                                cdf_get_var_double(ncvars[yvarid].ncid,
-                                                   ncvars[yvarid].bounds,
-                                                   grid->ybounds);
-                              }
-			  }
-		      }
-		  }
-
-		if ( ncvars[ncvarid].cellarea != UNDEFID )
-                  {
-                    if (CDI_netcdf_lazy_grid_load)
-                      {
-                        grid->area = cdfPendingLoad;
-                        lazyGrid->cellAreaGet.datasetNCId
-                          = ncvars[ncvarid].ncid;
-                        lazyGrid->cellAreaGet.varNCId
-                          = ncvars[ncvarid].cellarea;
-                      }
-                    else
-                      {
-                        grid->area = (double *) Malloc(size*sizeof(double));
-                        cdf_get_var_double(ncvars[ncvarid].ncid,
-                                           ncvars[ncvarid].cellarea,
-                                           grid->area);
-                      }
-                  }
-
-		break;
-	      }
-	    case GRID_SPECTRAL:
-	      {
-		grid->size = (int)size;
-		grid->lcomplex = 1;
-		break;
-	      }
-	    case GRID_FOURIER:
-	      {
-		grid->size = (int)size;
-		break;
-	      }
-	    case GRID_TRAJECTORY:
-	      {
-		grid->size = 1;
-		break;
-	      }
-	    }
-
-          if ( grid->type != ncvars[ncvarid].gridtype )
-            {
-              int gridtype = ncvars[ncvarid].gridtype;
-              grid->type = gridtype;
-              cdiGridTypeInit(grid, gridtype, grid->size);
-            }
-
-	  if ( grid->size == 0 )
-	    {
-	      if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
-		   (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == Z_AXIS) ||
-		   (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS && ncvars[ncvarid].dimtype[1] == Z_AXIS) )
-		{
-		  grid->type  = GRID_GENERIC;
-		  grid->size  = 1;
-		  grid->xsize = 0;
-		  grid->ysize = 0;
-		}
-	      else
-		{
-		  Warning("Variable %s has an unsupported grid, skipped!", ncvars[ncvarid].name);
-		  ncvars[ncvarid].isvar = -1;
-		  continue;
-		}
-	    }
-
-	  if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) )
-            grid->type   = GRID_UNSTRUCTURED;
-
-	  if ( number_of_grid_used != UNDEFID && grid->type == GRID_UNSTRUCTURED )
-            grid->number = number_of_grid_used;
-
-	  if ( ncvars[ncvarid].gmapid >= 0 && ncvars[ncvarid].gridtype != GRID_CURVILINEAR )
-	    {
-              int nvatts;
-	      cdf_inq_varnatts(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, &nvatts);
-
-	      for ( int iatt = 0; iatt < nvatts; iatt++ )
-		{
-                  size_t attlen;
-                  char attname[CDI_MAX_NAME];
-		  cdf_inq_attname(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, iatt, attname);
-		  cdf_inq_attlen(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, &attlen);
-
-		  if ( strcmp(attname, "grid_mapping_name") == 0 )
-		    {
-                      enum {
-                        attstringlen = 8192,
-                      };
-                      char attstring[attstringlen];
-
-		      cdfGetAttText(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, attstringlen, attstring);
-		      strtolower(attstring);
-
-		      if ( strcmp(attstring, "rotated_latitude_longitude") == 0 )
-			grid->isRotated = TRUE;
-		      else if ( strcmp(attstring, "sinusoidal") == 0 )
-			grid->type = GRID_SINUSOIDAL;
-		      else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 )
-			grid->type = GRID_LAEA;
-		      else if ( strcmp(attstring, "lambert_conformal_conic") == 0 )
-			grid->type = GRID_LCC2;
-		      else if ( strcmp(attstring, "lambert_cylindrical_equal_area") == 0 )
-			{
-			  proj->type = GRID_PROJECTION;
-			  proj->name = strdup(attstring);
-			}
-		    }
-		  else if ( strcmp(attname, "earth_radius") == 0 )
-		    {
-                      double datt;
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
-		      grid->laea_a = datt;
-		      grid->lcc2_a = datt;
-		    }
-		  else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )
-		    {
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->laea_lon_0);
-		    }
-		  else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )
-		    {
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->lcc2_lon_0);
-		    }
-		  else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )
-		    {
-                      double datt;
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
-		      grid->laea_lat_0 = datt;
-		      grid->lcc2_lat_0 = datt;
-		    }
-		  else if ( strcmp(attname, "standard_parallel") == 0 )
-		    {
-		      if ( attlen == 1 )
-			{
-                          double datt;
-			  cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
-			  grid->lcc2_lat_1 = datt;
-			  grid->lcc2_lat_2 = datt;
-			}
-		      else
-			{
-			  double datt2[2];
-			  cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 2, datt2);
-			  grid->lcc2_lat_1 = datt2[0];
-			  grid->lcc2_lat_2 = datt2[1];
-			}
-		    }
-		  else if ( strcmp(attname, "grid_north_pole_latitude") == 0 )
-		    {
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->ypole);
-		    }
-		  else if ( strcmp(attname, "grid_north_pole_longitude") == 0 )
-		    {
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->xpole);
-		    }
-		  else if ( strcmp(attname, "north_pole_grid_longitude") == 0 )
-		    {
-		      cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->angle);
-		    }
-		}
-	    }
-
-          if ( grid->type == GRID_UNSTRUCTURED )
-            {
-              int zdimid = UNDEFID;
-              int xdimidx = -1, ydimidx = -1;
-
-              for ( int i = 0; i < ndims; i++ )
-                {
-                  if      ( ncvars[ncvarid].dimtype[i] == X_AXIS ) xdimidx = i;
-                  else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) ydimidx = i;
-                  else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) zdimid = ncvars[ncvarid].dimids[i];
-                }
-
-              if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID )
-                {
-                  if ( grid->xsize > grid->ysize && grid->ysize < 1000 )
-                    {
-                      ncvars[ncvarid].dimtype[ydimidx] = Z_AXIS;
-                      ydimid = UNDEFID;
-                      grid->size  = grid->xsize;
-                      grid->ysize = 0;
-                    }
-                  else if ( grid->ysize > grid->xsize && grid->xsize < 1000 )
-                    {
-                      ncvars[ncvarid].dimtype[xdimidx] = Z_AXIS;
-                      xdimid = ydimid;
-                      ydimid = UNDEFID;
-                      grid->size  = grid->ysize;
-                      grid->xsize = grid->ysize;
-                      grid->ysize = 0;
-                    }
-                }
-
-              if ( grid->size != grid->xsize )
-                {
-                  Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
-                  ncvars[ncvarid].isvar = -1;
-                  continue;
-                }
-
-              if ( ncvars[ncvarid].position > 0 ) grid->position = ncvars[ncvarid].position;
-              if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16);
-            }
-
-#if defined (PROJECTION_TEST)
-	  if ( proj->type == GRID_PROJECTION )
-	    {
-	      if ( grid->type == GRID_GENERIC )
-		{
-		  grid->type = GRID_CURVILINEAR;
-		}
-
-	      if ( grid->type == GRID_CURVILINEAR )
-		{
-                  proj->size  = grid->size;
-                  proj->xsize = grid->xsize;
-                  proj->ysize = grid->ysize;
-		}
-
-	      //  grid->proj = gridGenerate(proj);
-	    }
-#endif
-
-	  if ( CDI_Debug )
-	    {
-	      Message("grid: type = %d, size = %d, nx = %d, ny %d",
-		      grid->type, grid->size, grid->xsize, grid->ysize);
-	      Message("proj: type = %d, size = %d, nx = %d, ny %d",
-		      proj->type, proj->size, proj->xsize, proj->ysize);
-	    }
-
-#if defined (PROJECTION_TEST)
-	  if ( proj->type == GRID_PROJECTION )
-	    {
-              projAdded = cdiVlistAddGridIfNew(vlistID, proj, 1);
-              ncvars[ncvarid].gridID = projAdded.Id;
-	      copy_numeric_projatts(ncvars[ncvarid].gridID, ncvars[ncvarid].gmapid, ncvars[ncvarid].ncid);
-	    }
-	  else
-#endif
-            {
-              gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1);
-              ncvars[ncvarid].gridID = gridAdded.Id;
-            }
-
-          if ( grid->type == GRID_UNSTRUCTURED )
-            {
-              if ( gridfile[0] != 0 ) gridDefReference(ncvars[ncvarid].gridID, gridfile);
-            }
-
-          if ( ncvars[ncvarid].chunked ) grid_set_chunktype(grid, &ncvars[ncvarid]);
-
-	  int gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID);
-	  streamptr->xdimID[gridindex] = xdimid;
-	  streamptr->ydimID[gridindex] = ydimid;
-          if ( xdimid == -1 && ydimid == -1 && grid->size == 1 )
-            gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
-
-          if ( xdimid != -1 )
-            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name);
-          if ( ydimid != -1 )
-            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name);
-          if ( vdimid != -1 )
-            cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name);
-
-	  if ( CDI_Debug )
-	    Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
-
-	  for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
-	    if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].gridID == UNDEFID )
-	      {
-		int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID;
-                int xdimidx = -1, ydimidx = -1;
-		int ndims2 = ncvars[ncvarid2].ndims;
-
-		for ( int i = 0; i < ndims2; i++ )
-		  {
-		    if ( ncvars[ncvarid2].dimtype[i] == X_AXIS )
-		      { xdimid2 = ncvars[ncvarid2].dimids[i]; xdimidx = i; }
-		    else if ( ncvars[ncvarid2].dimtype[i] == Y_AXIS )
-		      { ydimid2 = ncvars[ncvarid2].dimids[i]; ydimidx = i; }
-		    else if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
-		      { zdimid2 = ncvars[ncvarid2].dimids[i]; }
-		  }
-
-                if ( ncvars[ncvarid2].gridtype == UNDEFID && grid->type == GRID_UNSTRUCTURED )
-                  {
-                    if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID )
-                      {
-                        ncvars[ncvarid2].dimtype[ydimidx] = Z_AXIS;
-                        ydimid2 = UNDEFID;
-                      }
-
-                    if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID )
-                      {
-                        ncvars[ncvarid2].dimtype[xdimidx] = Z_AXIS;
-                        xdimid2 = ydimid2;
-                        ydimid2 = UNDEFID;
-                      }
-                  }
-
-                if ( xdimid == xdimid2 &&
-		    (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) )
-		  {
-		    int same_grid = ncvars[ncvarid].xvarid == ncvars[ncvarid2].xvarid
-                      && ncvars[ncvarid].yvarid == ncvars[ncvarid2].yvarid
-                      && ncvars[ncvarid].position == ncvars[ncvarid2].position;
-                    /*
-		    if ( xvarid != -1 && ncvars[ncvarid2].xvarid != UNDEFID &&
-			 xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
-
-		    if ( yvarid != -1 && ncvars[ncvarid2].yvarid != UNDEFID &&
-			 yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
-                    */
-
-		    if ( same_grid )
-		      {
-			if ( CDI_Debug )
-			  Message("Same gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid2, ncvars[ncvarid2].name);
-			ncvars[ncvarid2].gridID = ncvars[ncvarid].gridID;
-			ncvars[ncvarid2].chunktype = ncvars[ncvarid].chunktype;
-		      }
-		  }
-	      }
-
-          if (gridAdded.isNew)
-            lazyGrid = NULL;
-          if (projAdded.isNew)
-            lazyProj = NULL;
-	}
-    }
-  if (lazyGrid)
-    {
-      if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyGrid);
-      grid_free(grid);
-      Free(grid);
-    }
-  if (lazyProj)
-    {
-      if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyProj);
-      grid_free(proj);
-      Free(proj);
-    }
-#undef proj
-#undef grid
-}
-
-/* define all input zaxes */
-static
-void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars,
-		      size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid)
-{
-  int ncvarid, ncvarid2;
-  int i, ilev;
-  int zaxisindex;
-  int nbdims, nvertex, nlevel;
-  int psvarid = -1;
-  char *pname, *plongname, *punits;
-  size_t vctsize = vctsize_echam;
-  double *vct = vct_echam;
-
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].zaxisID == UNDEFID )
-	{
-          int is_scalar = FALSE;
-	  int with_bounds = FALSE;
-	  int zdimid = UNDEFID;
-	  int zvarid = UNDEFID;
-	  int zsize = 1;
-	  double *lbounds = NULL;
-	  double *ubounds = NULL;
-
-          int positive = 0;
-	  int ndims = ncvars[ncvarid].ndims;
-
-          if ( ncvars[ncvarid].zvarid != -1 && ncvars[ncvars[ncvarid].zvarid].ndims == 0 )
-            {
-              zvarid = ncvars[ncvarid].zvarid;
-              is_scalar = TRUE;
-            }
-          else
-            {
-              for ( i = 0; i < ndims; i++ )
-                {
-                  if ( ncvars[ncvarid].dimtype[i] == Z_AXIS )
-                    zdimid = ncvars[ncvarid].dimids[i];
-                }
-
-              if ( zdimid != UNDEFID )
-                {
-                  zvarid = ncdims[zdimid].ncvarid;
-                  zsize  = (int)ncdims[zdimid].len;
-                }
-            }
-
-	  if ( CDI_Debug ) Message("nlevs = %d", zsize);
-
-	  double *zvar = (double *) Malloc((size_t)zsize * sizeof (double));
-
-	  int zaxisType = UNDEFID;
-	  if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype;
-	  if ( zaxisType == UNDEFID )  zaxisType = ZAXIS_GENERIC;
-
-	  int zprec = DATATYPE_FLT64;
-
-	  if ( zvarid != UNDEFID )
-	    {
-	      positive  = ncvars[zvarid].positive;
-	      pname     = ncvars[zvarid].name;
-	      plongname = ncvars[zvarid].longname;
-	      punits    = ncvars[zvarid].units;
-	      if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32;
-	      /* don't change the name !!! */
-	      /*
-	      if ( (len = strlen(pname)) > 2 )
-		if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) )
-		  pname[len-2] = 0;
-	      */
-              psvarid = -1;
-              if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct )
-                {
-                  vct = ncvars[zvarid].vct;
-                  vctsize = ncvars[zvarid].vctsize;
-
-                  if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid;
-                }
-
-	      cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar);
-
-	      if ( ncvars[zvarid].bounds != UNDEFID )
-		{
-		  nbdims = ncvars[ncvars[zvarid].bounds].ndims;
-		  if ( nbdims == 2 )
-		    {
-		      nlevel  = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
-		      nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
-		      if ( nlevel == zsize && nvertex == 2 )
-			{
-			  with_bounds = TRUE;
-			  lbounds = (double *) Malloc((size_t)nlevel*sizeof(double));
-			  ubounds = (double *) Malloc((size_t)nlevel*sizeof(double));
-			  double zbounds[2*nlevel];
-			  cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
-			  for ( i = 0; i < nlevel; ++i )
-			    {
-			      lbounds[i] = zbounds[i*2];
-			      ubounds[i] = zbounds[i*2+1];
-			    }
-			}
-		    }
-		}
-	    }
-	  else
-	    {
-	      pname     = NULL;
-	      plongname = NULL;
-	      punits    = NULL;
-
-	      if ( zsize == 1 )
-		{
-                  if ( ncvars[ncvarid].zaxistype != UNDEFID )
-                    zaxisType = ncvars[ncvarid].zaxistype;
-                  else
-                    zaxisType = ZAXIS_SURFACE;
-
-		  zvar[0] = 0;
-		  /*
-		  if ( zdimid == UNDEFID )
-		    zvar[0] = 9999;
-		  else
-		    zvar[0] = 0;
-		  */
-		}
-	      else
-		{
-		  for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
-		}
-	    }
-
-      	  ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds,
-						(int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
-
-	  if ( uuidOfVGrid[0] != 0 )
-            {
-              // printf("uuidOfVGrid: defined\n");
-              zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid);
-            }
-
-          if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvars[ncvarid].zaxisID, ncvars[psvarid].name);
-
-          if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
-          if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID);
-
-          if ( zdimid != -1 )
-            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name);
-          /*
-          if ( vdimid != -1 )
-            cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name);
-          */
-	  Free(zvar);
-	  Free(lbounds);
-	  Free(ubounds);
-
-	  zaxisindex = vlistZaxisIndex(vlistID, ncvars[ncvarid].zaxisID);
-	  streamptr->zaxisID[zaxisindex]  = zdimid;
-
-	  if ( CDI_Debug )
-	    Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid, ncvars[ncvarid].name);
-
-	  for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
-	    if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ )
-	      {
-                int zvarid2 = UNDEFID;
-                if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 )
-                  zvarid2 = ncvars[ncvarid2].zvarid;
-
-		int zdimid2 = UNDEFID;
-		ndims = ncvars[ncvarid2].ndims;
-		for ( i = 0; i < ndims; i++ )
-		  {
-		    if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
-		      zdimid2 = ncvars[ncvarid2].dimids[i];
-		  }
-
-		if ( zdimid == zdimid2 /* && zvarid == zvarid2 */)
-		  {
-                    if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ||
-                         (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) ||
-                         (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) ||
-                         (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) )
-                      {
-                        if ( CDI_Debug )
-                          Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid2, ncvars[ncvarid2].name);
-                        ncvars[ncvarid2].zaxisID = ncvars[ncvarid].zaxisID;
-                      }
-                  }
-	      }
-	}
-    }
-}
-
-struct varinfo
-{
-  int      ncvarid;
-  const char *name;
-};
-
-static
-int cmpvarname(const void *s1, const void *s2)
-{
-  const struct varinfo *x = (const struct varinfo *)s1,
-    *y = (const struct varinfo *)s2;
-  return (strcmp(x->name, y->name));
-}
-
-/* define all input data variables */
-static
-void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars)
-{
-  if ( CDI_Debug )
-    {
-      for(int i = 0; i < nvars; i++) Message("varids[%d] = %d", i, varids[i]);
-    }
-  if ( streamptr->sortname )
-    {
-      struct varinfo *varInfo
-        = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo));
-
-      for ( int varID = 0; varID < nvars; varID++ )
-	{
-	  int ncvarid = varids[varID];
-	  varInfo[varID].ncvarid = ncvarid;
-	  varInfo[varID].name = ncvars[ncvarid].name;
-	}
-      qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname);
-      for ( int varID = 0; varID < nvars; varID++ )
-	{
-	  varids[varID] = varInfo[varID].ncvarid;
-	}
-      Free(varInfo);
-      if ( CDI_Debug )
-        {
-          for(int i = 0; i < nvars; i++) Message("sorted varids[%d] = %d", i, varids[i]);
-        }
-    }
-
-  for ( int varID1 = 0; varID1 < nvars; varID1++ )
-    {
-      int ncvarid = varids[varID1];
-      int gridID  = ncvars[ncvarid].gridID;
-      int zaxisID = ncvars[ncvarid].zaxisID;
-
-      stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID);
-      int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype);
-
-#if  defined  (HAVE_NETCDF4)
-      if ( ncvars[ncvarid].deflate )
-	vlistDefVarCompType(vlistID, varID, COMPRESS_ZIP);
-
-      if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID )
-        vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype);
-#endif
-
-      streamptr->vars[varID1].defmiss = 0;
-      streamptr->vars[varID1].ncvarid = ncvarid;
-
-      vlistDefVarName(vlistID, varID, ncvars[ncvarid].name);
-      if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param);
-      if ( ncvars[ncvarid].code != UNDEFID )  vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code);
-      if ( ncvars[ncvarid].code != UNDEFID )
-	{
-	  int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255);
-	  vlistDefVarParam(vlistID, varID, param);
-	}
-      if ( ncvars[ncvarid].longname[0] )  vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname);
-      if ( ncvars[ncvarid].stdname[0] )   vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname);
-      if ( ncvars[ncvarid].units[0] )     vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units);
-
-      if ( ncvars[ncvarid].lvalidrange )
-        vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange);
-
-      if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) )
-	vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset);
-      if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) )
-	vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor);
-
-      vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned));
-
-      vlistDefVarInstitut(vlistID, varID, instID);
-      vlistDefVarModel(vlistID, varID, modelID);
-      if ( ncvars[ncvarid].tableID != UNDEFID )
-	vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID);
-
-      if ( ncvars[ncvarid].deffillval == FALSE && ncvars[ncvarid].defmissval == TRUE )
-        {
-          ncvars[ncvarid].deffillval = TRUE;
-          ncvars[ncvarid].fillval    = ncvars[ncvarid].missval;
-        }
-
-      if ( ncvars[ncvarid].deffillval == TRUE )
-        vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval);
-
-      if ( CDI_Debug )
-	Message("varID = %d  gridID = %d  zaxisID = %d", varID,
-		vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID));
-
-      int gridindex = vlistGridIndex(vlistID, gridID);
-      int xdimid = streamptr->xdimID[gridindex];
-      int ydimid = streamptr->ydimID[gridindex];
-
-      int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-      int zdimid = streamptr->zaxisID[zaxisindex];
-
-      int ndims = ncvars[ncvarid].ndims;
-      int iodim = 0;
-      int ixyz = 0;
-      int ipow10[4] = {1, 10, 100, 1000};
-
-      if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++;
-
-      if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid )
-        {
-          if ( xdimid == ncvars[ncvarid].dimids[ndims-1] )
-            {
-              ixyz = 321;
-            }
-          else
-            {
-              ixyz = 213;
-            }
-        }
-      else
-        {
-          for ( int idim = iodim; idim < ndims; idim++ )
-            {
-              if      ( xdimid == ncvars[ncvarid].dimids[idim] )
-                ixyz += 1*ipow10[ndims-idim-1];
-              else if ( ydimid == ncvars[ncvarid].dimids[idim] )
-                ixyz += 2*ipow10[ndims-idim-1];
-              else if ( zdimid == ncvars[ncvarid].dimids[idim] )
-                ixyz += 3*ipow10[ndims-idim-1];
-            }
-        }
-
-      vlistDefVarXYZ(vlistID, varID, ixyz);
-      /*
-      printf("ixyz %d\n", ixyz);
-      printf("ndims %d\n", ncvars[ncvarid].ndims);
-      for ( int i = 0; i < ncvars[ncvarid].ndims; ++i )
-        printf("dimids: %d %d\n", i, ncvars[ncvarid].dimids[i]);
-      printf("xdimid, ydimid %d %d\n", xdimid, ydimid);
-      */
-      if ( ncvars[ncvarid].ensdata != NULL )
-        {
-          vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index,
-                               ncvars[ncvarid].ensdata->ens_count,
-                               ncvars[ncvarid].ensdata->forecast_init_type );
-          Free(ncvars[ncvarid].ensdata);
-          ncvars[ncvarid].ensdata = NULL;
-        }
-
-      if ( ncvars[ncvarid].extra[0] != 0 )
-        {
-          vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
-        }
-    }
-
-  for ( int varID = 0; varID < nvars; varID++ )
-    {
-      int ncvarid = varids[varID];
-      int ncid = ncvars[ncvarid].ncid;
-
-      if ( ncvars[ncvarid].natts )
-	{
-	  int attnum;
-	  int iatt;
-	  nc_type attrtype;
-	  size_t attlen;
-	  char attname[CDI_MAX_NAME];
-	  const int attstringlen = 8192; char attstring[8192];
-	  int nvatts = ncvars[ncvarid].natts;
-
-	  for ( iatt = 0; iatt < nvatts; iatt++ )
-	    {
-	      attnum = ncvars[ncvarid].atts[iatt];
-	      cdf_inq_attname(ncid, ncvarid, attnum, attname);
-	      cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
-	      cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
-
-	      if ( attrtype == NC_SHORT || attrtype == NC_INT )
-		{
-		  int attint[attlen];
-		  cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
-		  if ( attrtype == NC_SHORT )
-		    vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint);
-		  else
-		    vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT32, (int)attlen, attint);
-		}
-	      else if ( attrtype == NC_FLOAT || attrtype == NC_DOUBLE )
-		{
-		  double attflt[attlen];
-		  cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
-		  if ( attrtype == NC_FLOAT )
-		    vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt);
-		  else
-		    vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT64, (int)attlen, attflt);
-		}
-	      else if ( xtypeIsText(attrtype) )
-		{
-		  cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
-		  vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring);
-		}
-	      else
-		{
-		  if ( CDI_Debug ) printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
-		}
-	    }
-
-	  if (ncvars[ncvarid].vct) Free(ncvars[ncvarid].vct);
-	  if (ncvars[ncvarid].atts) Free(ncvars[ncvarid].atts);
-          ncvars[ncvarid].vct = NULL;
-          ncvars[ncvarid].atts = NULL;
-	}
-    }
-
-  /* release mem of not freed attributes */
-  for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ )
-    if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts);
-
-  if ( varids ) Free(varids);
-
-  for ( int varID = 0; varID < nvars; varID++ )
-    {
-      if ( vlistInqVarCode(vlistID, varID) == -varID-1 )
-	{
-	  const char *pname = vlistInqVarNamePtr(vlistID, varID);
-	  size_t len = strlen(pname);
-	  if ( len > 3 && isdigit((int) pname[3]) )
-	    {
-	      if ( memcmp("var", pname, 3) == 0 )
-		{
-		  vlistDefVarCode(vlistID, varID, atoi(pname+3));
-                  // vlistDestroyVarName(vlistID, varID);
-		}
-	    }
-	  else if ( len > 4 && isdigit((int) pname[4]) )
-	    {
-	      if ( memcmp("code", pname, 4) == 0 )
-		{
-		  vlistDefVarCode(vlistID, varID, atoi(pname+4));
-		  // vlistDestroyVarName(vlistID, varID);
-		}
-	    }
-	  else if ( len > 5 && isdigit((int) pname[5]) )
-	    {
-	      if ( memcmp("param", pname, 5) == 0 )
-		{
-		  int pnum = -1, pcat = 255, pdis = 255;
-		  sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis);
-		  vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis));
-                  // vlistDestroyVarName(vlistID, varID);
-		}
-	    }
-	}
-    }
-
-  for ( int varID = 0; varID < nvars; varID++ )
-    {
-      int varInstID  = vlistInqVarInstitut(vlistID, varID);
-      int varModelID = vlistInqVarModel(vlistID, varID);
-      int varTableID = vlistInqVarTable(vlistID, varID);
-      int code = vlistInqVarCode(vlistID, varID);
-      if ( cdiDefaultTableID != UNDEFID )
-	{
-	  if ( tableInqParNamePtr(cdiDefaultTableID, code) )
-	    {
-	      vlistDestroyVarName(vlistID, varID);
-	      vlistDestroyVarLongname(vlistID, varID);
-	      vlistDestroyVarUnits(vlistID, varID);
-
-	      if ( varTableID != UNDEFID )
-		{
-		  vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code));
-		  if ( tableInqParLongnamePtr(cdiDefaultTableID, code) )
-		    vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code));
-		  if ( tableInqParUnitsPtr(cdiDefaultTableID, code) )
-		    vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code));
-		}
-	      else
-		{
-		  varTableID = cdiDefaultTableID;
-		}
-	    }
-
-	  if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID;
-	  if ( cdiDefaultInstID  != UNDEFID ) varInstID  = cdiDefaultInstID;
-	}
-      if ( varInstID  != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID);
-      if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID);
-      if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID);
-    }
-}
-
-static
-void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, int *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used)
-{
-  nc_type xtype;
-  size_t attlen;
-  char attname[CDI_MAX_NAME];
-  enum { attstringlen = 65636 };
-  char attstring[attstringlen];
-  int iatt;
-
-  for ( iatt = 0; iatt < ngatts; iatt++ )
-    {
-      cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname);
-      cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
-      cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
-
-      if ( xtypeIsText(xtype) )
-	{
-	  cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring);
-
-          size_t attstrlen = strlen(attstring);
-
-	  if ( attlen > 0 && attstring[0] != 0 )
-	    {
-	      if ( strcmp(attname, "history") == 0 )
-		{
-		  streamptr->historyID = iatt;
-		}
-	      else if ( strcmp(attname, "institution") == 0 )
-		{
-		  *instID = institutInq(0, 0, NULL, attstring);
-		  if ( *instID == UNDEFID )
-		    *instID = institutDef(0, 0, NULL, attstring);
-		}
-	      else if ( strcmp(attname, "source") == 0 )
-		{
-		  *modelID = modelInq(-1, 0, attstring);
-		  if ( *modelID == UNDEFID )
-		    *modelID = modelDef(-1, 0, attstring);
-		}
-	      else if ( strcmp(attname, "Source") == 0 )
-		{
-		  if ( strncmp(attstring, "UCLA-LES", 8) == 0 )
-		    *ucla_les = TRUE;
-		}
-	      /*
-	      else if ( strcmp(attname, "Conventions") == 0 )
-		{
-		}
-	      */
-	      else if ( strcmp(attname, "CDI") == 0 )
-		{
-		}
-	      else if ( strcmp(attname, "CDO") == 0 )
-		{
-		}
-              /*
-	      else if ( strcmp(attname, "forecast_reference_time") == 0 )
-		{
-                  memcpy(fcreftime, attstring, attstrlen+1);
-		}
-              */
-	      else if ( strcmp(attname, "grid_file_uri") == 0 )
-		{
-                  memcpy(gridfile, attstring, attstrlen+1);
-		}
-	      else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 )
-		{
-                  attstring[36] = 0;
-                  cdiStr2UUID(attstring, uuidOfHGrid);
-                  //   printf("uuid: %d %s\n", attlen, attstring);
-		}
-	      else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
-		{
-                  attstring[36] = 0;
-                  cdiStr2UUID(attstring, uuidOfVGrid);
-		}
-	      else
-		{
-                  if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
-                    {
-                      memcpy(gridfile, attstring, attstrlen+1);
-                    }
-
-		  vlistDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring);
-		}
-	    }
-	}
-      else if ( xtype == NC_SHORT || xtype == NC_INT )
-	{
-	  if ( strcmp(attname, "number_of_grid_used") == 0 )
-	    {
-	      (*number_of_grid_used) = UNDEFID;
-	      cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used);
-	    }
- 	  else
-            {
-              int attint[attlen];
-              cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
-              if ( xtype == NC_SHORT )
-                vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint);
-              else
-                vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT32, (int)attlen, attint);
-            }
-        }
-      else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE )
-	{
-	  double attflt[attlen];
-	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
-	  if ( xtype == NC_FLOAT )
-	    vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt);
-	  else
-	    vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT64, (int)attlen, attflt);
-	}
-    }
-}
-
-static
-int find_leadtime(int nvars, ncvar_t *ncvars)
-{
-  int leadtime_id = UNDEFID;
-
-  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].stdname[0] )
-        {
-          if ( strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 )
-            {
-              leadtime_id = ncvarid;
-              break;
-            }
-        }
-    }
-
-  return (leadtime_id);
-}
-
-static
-void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr,
-                    int *time_has_units, int *time_has_bounds, int *time_climatology)
-{
-  int ncvarid;
-
-  if ( timedimid == UNDEFID )
-    {
-      char timeunits[CDI_MAX_NAME];
-
-      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-        {
-          if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 )
-            {
-              if ( ncvars[ncvarid].units[0] )
-                {
-                  strcpy(timeunits, ncvars[ncvarid].units);
-                  strtolower(timeunits);
-
-                  if ( isTimeUnits(timeunits) )
-                    {
-                      streamptr->basetime.ncvarid = ncvarid;
-                      break;
-                    }
-                }
-            }
-        }
-    }
-  else
-    {
-      int ltimevar = FALSE;
-
-      if ( ncdims[timedimid].ncvarid != UNDEFID )
-        {
-          streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid;
-          ltimevar = TRUE;
-        }
-
-      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-        if ( ncvarid != streamptr->basetime.ncvarid &&
-             ncvars[ncvarid].ndims == 1 &&
-             timedimid == ncvars[ncvarid].dimids[0] &&
-             !xtypeIsText(ncvars[ncvarid].xtype) &&
-             isTimeAxisUnits(ncvars[ncvarid].units) )
-          {
-            ncvars[ncvarid].isvar = FALSE;
-
-            if ( !ltimevar )
-              {
-                streamptr->basetime.ncvarid = ncvarid;
-                ltimevar = TRUE;
-                if ( CDI_Debug )
-                  fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name);
-              }
-            else
-              {
-                Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name);
-              }
-          }
-
-      if ( ltimevar == FALSE ) /* search for WRF time description */
-        {
-          for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-            if ( ncvarid != streamptr->basetime.ncvarid &&
-                 ncvars[ncvarid].ndims == 2 &&
-                 timedimid == ncvars[ncvarid].dimids[0] &&
-                 xtypeIsText(ncvars[ncvarid].xtype) &&
-                 ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
-              {
-                streamptr->basetime.ncvarid = ncvarid;
-                streamptr->basetime.lwrf    = TRUE;
-                break;
-              }
-        }
-
-      /* time varID */
-      ncvarid = streamptr->basetime.ncvarid;
-
-      if ( ncvarid == UNDEFID )
-        {
-          Warning("Time variable >%s< not found!", ncdims[timedimid].name);
-        }
-    }
-
-  /* time varID */
-  ncvarid = streamptr->basetime.ncvarid;
-
-  if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == FALSE )
-    {
-      if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = TRUE;
-
-      if ( ncvars[ncvarid].bounds != UNDEFID )
-        {
-          int nbdims = ncvars[ncvars[ncvarid].bounds].ndims;
-          if ( nbdims == 2 )
-            {
-              int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len;
-              if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] )
-                {
-                  *time_has_bounds = TRUE;
-                  streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds;
-                  if ( ncvars[ncvarid].climatology ) *time_climatology = TRUE;
-                }
-            }
-        }
-    }
-}
-
-static
-void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize)
-{
-  /* find ECHAM VCT */
-  int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID;
-
-  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].ndims == 1 )
-        {
-          size_t len = strlen(ncvars[ncvarid].name);
-          if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' )
-            {
-              if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai
-                {
-                  vcta_id = ncvarid;
-                  nvcth_id = ncvars[ncvarid].dimids[0];
-                  ncvars[ncvarid].isvar = FALSE;
-                }
-              else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi
-                {
-                  vctb_id = ncvarid;
-                  nvcth_id = ncvars[ncvarid].dimids[0];
-                  ncvars[ncvarid].isvar = FALSE;
-                }
-              else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' )
-                {
-                  ncvars[ncvarid].isvar = FALSE; // hyam or hybm
-                }
-            }
-	}
-    }
-
-  /* read VCT */
-  if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID )
-    {
-      size_t vctsize = ncdims[nvcth_id].len;
-      vctsize *= 2;
-      *vct = (double *) Malloc(vctsize*sizeof(double));
-      cdf_get_var_double(fileID, vcta_id, *vct);
-      cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2);
-      *pvctsize = vctsize;
-    }
-}
-
-
-int cdfInqContents(stream_t *streamptr)
-{
-  int ndims, nvars, ngatts, unlimdimid;
-  int ncvarid;
-  int ncdimid;
-  size_t ntsteps;
-  int timedimid = -1;
-  int *varids;
-  int nvarids;
-  int time_has_units = FALSE;
-  int time_has_bounds = FALSE;
-  int time_climatology = FALSE;
-  int leadtime_id = UNDEFID;
-  int nvars_data;
-  int instID  = UNDEFID;
-  int modelID = UNDEFID;
-  int taxisID;
-  int i;
-  int calendar = UNDEFID;
-  ncdim_t *ncdims;
-  ncvar_t *ncvars = NULL;
-  int format = 0;
-  int ucla_les = FALSE;
-  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
-  unsigned char uuidOfVGrid[CDI_UUID_SIZE];
-  char gridfile[8912];
-  char fcreftime[CDI_MAX_NAME];
-  int number_of_grid_used = UNDEFID;
-
-  memset(uuidOfHGrid, 0, CDI_UUID_SIZE);
-  memset(uuidOfVGrid, 0, CDI_UUID_SIZE);
-  gridfile[0] = 0;
-  fcreftime[0] = 0;
-
-  int vlistID = streamptr->vlistID;
-  int fileID  = streamptr->fileID;
-
-  if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID);
-
-#if  defined  (HAVE_NETCDF4)
-  nc_inq_format(fileID, &format);
-#endif
-
-  cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid);
-
-  if ( CDI_Debug )
-    Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts);
-
-  if ( ndims == 0 )
-    {
-      Warning("ndims = %d", ndims);
-      return (CDI_EUFSTRUCT);
-    }
-
-  /* alloc ncdims */
-  ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t));
-  init_ncdims(ndims, ncdims);
-
-  if ( nvars > 0 )
-    {
-      /* alloc ncvars */
-      ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t));
-      init_ncvars(nvars, ncvars);
-
-      for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
-        ncvars[ncvarid].ncid = fileID;
-    }
-
-#if  defined  (TEST_GROUPS)
-#if  defined  (HAVE_NETCDF4)
-  if ( format == NC_FORMAT_NETCDF4 )
-    {
-      int ncid;
-      int numgrps;
-      int ncids[NC_MAX_VARS];
-      char name1[CDI_MAX_NAME];
-      int gndims, gnvars, gngatts, gunlimdimid;
-      nc_inq_grps(fileID, &numgrps, ncids);
-      for ( int i = 0; i < numgrps; ++i )
-        {
-          ncid = ncids[i];
-          nc_inq_grpname (ncid, name1);
-          cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid);
-
-          if ( CDI_Debug )
-            Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts);
-
-          if ( gndims == 0 )
-            {
-            }
-        }
-    }
-#endif
-#endif
-
-  if ( nvars == 0 )
-    {
-      Warning("nvars = %d", nvars);
-      return (CDI_EUFSTRUCT);
-    }
-
-  /* scan global attributes */
-  scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les,
-                         uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used);
-
-  /* find time dim */
-  if ( unlimdimid >= 0 )
-    timedimid = unlimdimid;
-  else
-    timedimid = cdfTimeDimID(fileID, ndims, nvars);
-
-  streamptr->basetime.ncdimid = timedimid;
-
-  if ( timedimid != UNDEFID )
-    cdf_inq_dimlen(fileID, timedimid, &ntsteps);
-  else
-    ntsteps = 0;
-
-  if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps);
-  if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid);
-
-  /* read ncdims */
-  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
-    {
-      cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len);
-      cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name);
-      if ( timedimid == ncdimid )
-	ncdims[ncdimid].dimtype = T_AXIS;
-    }
-
-  if ( CDI_Debug ) printNCvars(ncvars, nvars, "cdfScanVarAttributes");
-
-  /* scan attributes of all variables */
-  cdfScanVarAttributes(nvars, ncvars, ncdims, timedimid, modelID, format);
-
-
-  if ( CDI_Debug ) printNCvars(ncvars, nvars, "find coordinate vars");
-
-  /* find coordinate vars */
-  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
-    {
-      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-	{
-	  if ( ncvars[ncvarid].ndims == 1 )
-	    {
-	      if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] )
-		{
-		  if ( ncvars[ncvarid].isvar != FALSE ) cdfSetVar(ncvars, ncvarid, TRUE);
-		}
-	      else
-		{
-                  //  if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
-		}
-	      // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
-
-	      if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID )
-		if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 )
-		  {
-		    ncdims[ncdimid].ncvarid = ncvarid;
-		    ncvars[ncvarid].isvar = FALSE;
-		  }
-	    }
-	}
-    }
-
-  /* find time vars */
-  find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology);
-
-  leadtime_id = find_leadtime(nvars, ncvars);
-  if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE;
-
-  /* check ncvars */
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( timedimid != UNDEFID )
-	if ( ncvars[ncvarid].isvar == -1 &&
-	     ncvars[ncvarid].ndims > 1   &&
-	     timedimid == ncvars[ncvarid].dimids[0] )
-	  cdfSetVar(ncvars, ncvarid, TRUE);
-
-      if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 )
-	cdfSetVar(ncvars, ncvarid, FALSE);
-
-      //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 )
-      if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 )
-	cdfSetVar(ncvars, ncvarid, TRUE);
-
-      if ( ncvars[ncvarid].isvar == -1 )
-	{
-	  ncvars[ncvarid].isvar = 0;
-	  Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name);
-	  continue;
-	}
-
-      if ( ncvars[ncvarid].ndims > 4 )
-	{
-	  ncvars[ncvarid].isvar = 0;
-	  Warning("%d dimensional variables are not supported, skipped variable %s!",
-		ncvars[ncvarid].ndims, ncvars[ncvarid].name);
-	  continue;
-	}
-
-      if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID )
-	{
-	  ncvars[ncvarid].isvar = 0;
-	  Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!",
-		ncvars[ncvarid].ndims, ncvars[ncvarid].name);
-	  continue;
-	}
-
-      if ( xtypeIsText(ncvars[ncvarid].xtype) )
-	{
-	  ncvars[ncvarid].isvar = 0;
-	  continue;
-	}
-
-      if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 )
-	{
-	  ncvars[ncvarid].isvar = 0;
-	  Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name);
-	  continue;
-	}
-
-      if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 )
-	{
-	  if ( timedimid == ncvars[ncvarid].dimids[0] )
-	    {
-	      ncvars[ncvarid].isvar = 0;
-	      Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name);
-	      continue;
-	    }
-	}
-    }
-
-  /* verify coordinate vars - first scan (dimname == varname) */
-  verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid);
-
-  /* verify coordinate vars - second scan (all other variables) */
-  verify_coordinate_vars_2(nvars, ncvars);
-
-  if ( CDI_Debug ) printNCvars(ncvars, nvars, "verify_coordinate_vars");
-
-  if ( ucla_les == TRUE )
-    {
-      for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
-	{
-	  ncvarid = ncdims[ncdimid].ncvarid;
-	  if ( ncvarid != -1 )
-	    {
-	      if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' )
-		{
-		  if      ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS;
-		  else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS;
-		  else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS;
-		}
-	    }
-	}
-    }
-  /*
-  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
-    {
-      ncvarid = ncdims[ncdimid].ncvarid;
-      if ( ncvarid != -1 )
-	{
-	  printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units);
-	  if ( ncdims[ncdimid].dimtype == X_AXIS )
-	    printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name);
-	  if ( ncdims[ncdimid].dimtype == Y_AXIS )
-	    printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name);
-	  if ( ncdims[ncdimid].dimtype == Z_AXIS )
-	    printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name);
-	  if ( ncdims[ncdimid].dimtype == T_AXIS )
-	    printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name);
-
-	  if ( ncvars[ncvarid].islon )
-	    printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name);
-	  if ( ncvars[ncvarid].islat )
-	    printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name);
-	  if ( ncvars[ncvarid].islev )
-	    printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name);
-	}
-    }
-  */
-
-  /* Set coordinate varids (att: associate)  */
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    {
-      if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].ncoordvars )
-	{
-	  /* ndims = ncvars[ncvarid].ndims; */
-	  ndims = ncvars[ncvarid].ncoordvars;
-	  for ( i = 0; i < ndims; i++ )
-	    {
-	      if ( ncvars[ncvars[ncvarid].coordvarids[i]].islon )
-		ncvars[ncvarid].xvarid = ncvars[ncvarid].coordvarids[i];
-	      else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islat )
-		ncvars[ncvarid].yvarid = ncvars[ncvarid].coordvarids[i];
-	      else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islev )
-		ncvars[ncvarid].zvarid = ncvars[ncvarid].coordvarids[i];
-	    }
-	}
-    }
-
-  /* set dim type */
-  setDimType(nvars, ncvars, ncdims);
-
-  /* read ECHAM VCT if present */
-  size_t vctsize = 0;
-  double *vct = NULL;
-  read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize);
-
-
-  if ( CDI_Debug ) printNCvars(ncvars, nvars, "define_all_grids");
-
-  /* define all grids */
-  define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used);
-
-
-  /* define all zaxes */
-  define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
-  if ( vct ) Free(vct);
-
-
-  /* select vars */
-  varids = (int *) Malloc((size_t)nvars * sizeof (int));
-  nvarids = 0;
-  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
-    if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
-
-  nvars_data = nvarids;
-
-  if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid);
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
-  if ( CDI_Debug ) Message("nvars_data = %d", nvars_data);
-
-
-  if ( nvars_data == 0 )
-    {
-      streamptr->ntsteps = 0;
-      return (CDI_EUFSTRUCT);
-    }
-
-  if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
-    ntsteps = 1;
-
-  streamptr->ntsteps = (long)ntsteps;
-
-  /* define all data variables */
-  define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
-
-
-  cdiCreateTimesteps(streamptr);
-
-  /* time varID */
-  int nctimevarid = streamptr->basetime.ncvarid;
-
-  if ( time_has_units )
-    {
-      taxis_t *taxis = &streamptr->tsteps[0].taxis;
-
-      if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 )
-        {
-          nctimevarid = UNDEFID;
-          streamptr->basetime.ncvarid = UNDEFID;
-        }
-
-      if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE )
-        {
-          streamptr->basetime.leadtimeid = leadtime_id;
-          taxis->type = TAXIS_FORECAST;
-
-          int timeunit = -1;
-          if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units);
-          if ( timeunit == -1 ) timeunit = taxis->unit;
-          taxis->fc_unit = timeunit;
-
-          setForecastTime(fcreftime, taxis);
-        }
-    }
-
-  if ( time_has_bounds )
-    {
-      streamptr->tsteps[0].taxis.has_bounds = TRUE;
-      if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = TRUE;
-    }
-
-  if ( nctimevarid != UNDEFID )
-    {
-      taxis_t *taxis = &streamptr->tsteps[0].taxis;
-      ptaxisDefName(taxis, ncvars[nctimevarid].name);
-      if ( ncvars[nctimevarid].longname[0] )
-        ptaxisDefLongname(taxis, ncvars[nctimevarid].longname);
-    }
-
-  if ( nctimevarid != UNDEFID )
-    if ( ncvars[nctimevarid].calendar == TRUE )
-      {
-        enum {attstringlen = 8192};
-        char attstring[attstringlen];
-
-	cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring);
-	strtolower(attstring);
-
-	if ( memcmp(attstring, "standard", 8)  == 0 ||
-	     memcmp(attstring, "gregorian", 9) == 0 )
-	  calendar = CALENDAR_STANDARD;
-	else if ( memcmp(attstring, "none", 4) == 0 )
-	  calendar = CALENDAR_NONE;
-	else if ( memcmp(attstring, "proleptic", 9) == 0 )
-	  calendar = CALENDAR_PROLEPTIC;
-	else if ( memcmp(attstring, "360", 3) == 0 )
-	  calendar = CALENDAR_360DAYS;
-	else if ( memcmp(attstring, "365", 3) == 0 ||
-		  memcmp(attstring, "noleap", 6)  == 0 )
-	  calendar = CALENDAR_365DAYS;
-	else if ( memcmp(attstring, "366", 3)  == 0 ||
-		  memcmp(attstring, "all_leap", 8) == 0 )
-	  calendar = CALENDAR_366DAYS;
-	else
-	  Warning("calendar >%s< unsupported!", attstring);
-      }
-
-  if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST )
-    {
-      taxisID = taxisCreate(TAXIS_FORECAST);
-    }
-  else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE )
-    {
-      taxisID = taxisCreate(TAXIS_RELATIVE);
-    }
-  else
-    {
-      taxisID = taxisCreate(TAXIS_ABSOLUTE);
-      if ( !time_has_units )
-	{
-	  taxisDefTunit(taxisID, TUNIT_DAY);
-	  streamptr->tsteps[0].taxis.unit = TUNIT_DAY;
-	}
-    }
-
-
-  if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE )
-    {
-      calendar = CALENDAR_STANDARD;
-    }
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow"
-#endif
-  if ( calendar != UNDEFID )
-    {
-      taxis_t *taxis = &streamptr->tsteps[0].taxis;
-      taxis->calendar = calendar;
-      taxisDefCalendar(taxisID, calendar);
-    }
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
-#pragma GCC diagnostic pop
-#endif
-
-  vlistDefTaxis(vlistID, taxisID);
-
-  streamptr->curTsID = 0;
-  streamptr->rtsteps = 1;
-
-  (void) cdfInqTimestep(streamptr, 0);
-
-  cdfCreateRecords(streamptr, 0);
-
-  /* free ncdims */
-  Free(ncdims);
-
-  /* free ncvars */
-  Free(ncvars);
-
-  return (0);
-}
-
-static
-void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis)
-{
-  size_t start[2], count[2];
-  char stvalue[32];
-  start[0] = (size_t) tsID; start[1] = 0;
-  count[0] = 1; count[1] = 19;
-  stvalue[0] = 0;
-  cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
-  stvalue[19] = 0;
-  {
-    int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0;
-    if ( strlen(stvalue) == 19 )
-      sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
-    taxis->vdate = cdiEncodeDate(year, month, day);
-    taxis->vtime = cdiEncodeTime(hour, minute, second);
-    taxis->type = TAXIS_ABSOLUTE;
-  }
-}
-
-static
-double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache)
-{
-  double timevalue = 0;
-  size_t index = (size_t) tsID;
-
-  if ( tcache )
-    {
-      if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) )
-        {
-          int maxvals = MAX_TIMECACHE_SIZE;
-          tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE;
-          if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE;
-          tcache->size = maxvals;
-          index = (size_t) tcache->startid;
-          // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals);
-          for ( int ival = 0; ival < maxvals; ++ival )
-            {
-              cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
-              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-              tcache->cache[ival] = timevalue;
-              index++;
-            }
-        }
-
-      timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE];
-    }
-  else
-    {
-      cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
-      if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-    }
-
-  return timevalue;
-}
-
-
-int cdfInqTimestep(stream_t * streamptr, int tsID)
-{
-  long nrecs = 0;
-  double timevalue;
-  int fileID;
-  taxis_t *taxis;
-
-  if ( CDI_Debug ) Message("streamID = %d  tsID = %d", streamptr->self, tsID);
-
-  if ( tsID < 0 ) Error("unexpected tsID = %d", tsID);
-
-  if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 )
-    {
-      cdfCreateRecords(streamptr, tsID);
-
-      taxis = &streamptr->tsteps[tsID].taxis;
-      if ( tsID > 0 )
-	ptaxisCopy(taxis, &streamptr->tsteps[0].taxis);
-
-      timevalue = tsID;
-
-      int nctimevarid = streamptr->basetime.ncvarid;
-      if ( nctimevarid != UNDEFID )
-	{
-	  fileID = streamptr->fileID;
-	  size_t index  = (size_t)tsID;
-
-	  if ( streamptr->basetime.lwrf )
-	    {
-              wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
-	    }
-	  else
-	    {
-#if defined (USE_TIMECACHE)
-              if ( streamptr->basetime.timevar_cache == NULL )
-                {
-                  streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t));
-                  streamptr->basetime.timevar_cache->size = 0;
-                  streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps;
-                }
-#endif
-              timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache);
-	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime);
-	    }
-
-	  int nctimeboundsid = streamptr->basetime.ncvarboundsid;
-	  if ( nctimeboundsid != UNDEFID )
-	    {
-	      size_t start[2], count[2];
-              start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
-	      cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
-              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-
-	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb);
-
-              start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1;
-	      cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
-              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-
-	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub);
-	    }
-
-          int leadtimeid = streamptr->basetime.leadtimeid;
-          if ( leadtimeid != UNDEFID )
-            {
-              timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
-              cdiSetForecastPeriod(timevalue, taxis);
-            }
-	}
-    }
-
-  streamptr->curTsID = tsID;
-  nrecs = streamptr->tsteps[tsID].nrecs;
-
-  return ((int) nrecs);
-}
-
-
-void cdfDefHistory(stream_t *streamptr, int size, const char *history)
-{
-  int ncid = streamptr->fileID;
-  cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history);
-}
-
-
-int cdfInqHistorySize(stream_t *streamptr)
-{
-  size_t size = 0;
-  int ncid = streamptr->fileID;
-  if ( streamptr->historyID != UNDEFID )
-    cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size);
-
-  return ((int) size);
-}
-
-
-void cdfInqHistoryString(stream_t *streamptr, char *history)
-{
-  int ncid = streamptr->fileID;
-  if ( streamptr->historyID != UNDEFID )
-    {
-      nc_type atttype;
-      cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype);
-
-      if ( atttype == NC_CHAR )
-        {
-          cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
-        }
-#if  defined  (HAVE_NETCDF4)
-      else if ( atttype == NC_STRING )
-        {
-          // ToDo
-          Warning("History attribute with type NC_STRING unsupported!");
-        }
-#endif
-    }
-}
-
-
-void cdfDefVars(stream_t *streamptr)
-{
-  int vlistID = streamptr->vlistID;
-  if ( vlistID == UNDEFID )
-    Error("Internal problem! vlist undefined for streamptr %p", streamptr);
-
-  int ngrids = vlistNgrids(vlistID);
-  int nzaxis = vlistNzaxis(vlistID);
-  /*
-  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-  */
-  if ( ngrids > 0 )
-    for ( int index = 0; index < ngrids; index++ )
-      {
-        int gridID = vlistGrid(vlistID, index);
-        cdfDefGrid(streamptr, gridID);
-      }
-
-  if ( nzaxis > 0 )
-    for ( int index = 0; index < nzaxis; index++ )
-      {
-        int zaxisID = vlistZaxis(vlistID, index);
-        if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID);
-      }
-
-  /* define time first!!!
-    int nvars  = vlistNvars(vlistID);
-  for ( int varID = 0; varID < nvars; varID++ )
-    {
-      int ncvarid = cdfDefVar(streamptr, varID);
-    }
-  */
-}
-#endif
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/src/stream_cdf.h b/src/stream_cdf.h
index c0228b853a09ccde16bb4a7cb821f671131f11d1..ad61c1ed6e06c0f7f8e5fed32f810771099bdd57 100644
--- a/src/stream_cdf.h
+++ b/src/stream_cdf.h
@@ -1,6 +1,8 @@
 #ifndef _STREAM_CDF_H
 #define _STREAM_CDF_H
 
+#include "cdi_int.h"
+
 void   cdfDefVars(stream_t *streamptr);
 void   cdfDefTimestep(stream_t *streamptr, int tsID);
 int    cdfInqTimestep(stream_t *streamptr, int tsID);
@@ -14,6 +16,8 @@ void   cdfDefRecord(stream_t * streamptr);
 
 void   cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
 
+void   cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID);
+
 void   cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss);
 void   cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
 
@@ -29,6 +33,8 @@ void   cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level);
 void cdfDefTime(stream_t* streamptr);
 
+void cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor);
+
 #endif
 /*
  * Local Variables:
diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd561e9e7d1501e6b5e491b1fc083670678ad481
--- /dev/null
+++ b/src/stream_cdf_i.c
@@ -0,0 +1,4170 @@
+#if defined (HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBNETCDF
+
+//#define TEST_GROUPS 1
+
+#include <ctype.h>
+
+#include "dmemory.h"
+#include "gaussgrid.h"
+#include "cdi_int.h"
+#include "cdi_uuid.h"
+#include "stream_cdf.h"
+#include "cdf_int.h"
+#include "varscan.h"
+#include "vlist.h"
+#include "cdf_util.h"
+#include "cdf_lazy_grid.h"
+
+#undef  UNDEFID
+#define UNDEFID  CDI_UNDEFID
+
+#define  X_AXIS  1
+#define  Y_AXIS  2
+#define  Z_AXIS  3
+#define  T_AXIS  4
+
+#define  POSITIVE_UP    1
+#define  POSITIVE_DOWN  2
+
+typedef struct {
+  int     ncvarid;
+  int     dimtype;
+  size_t  len;
+  char    name[CDI_MAX_NAME];
+}
+ncdim_t;
+#define  MAX_COORDVARS  4
+#define  MAX_AUXVARS    4
+
+typedef struct {
+  int      ncid;
+  int      isvar;
+  bool     ignore;
+  bool     isx;
+  bool     isy;
+  bool     islon;
+  bool     islat;
+  bool     islev;
+  bool     istime;
+  bool     warn;
+  bool     climatology;
+  bool     lformula;
+  bool     lformulaterms;
+  int      tsteptype;
+  int      param;
+  int      code;
+  int      tabnum;
+  int      bounds;
+  int      gridID;
+  int      zaxisID;
+  int      gridtype;
+  int      zaxistype;
+  int      xdim;
+  int      ydim;
+  int      zdim;
+  int      xvarid;
+  int      yvarid;
+  int      zvarid;
+  int      tvarid;
+  int      psvarid;
+  int      p0varid;
+  int      ncoordvars;
+  int      coordvarids[MAX_COORDVARS];
+  int      nauxvars;
+  int      auxvarids[MAX_AUXVARS];
+  int      cellarea;
+  int      calendar;
+  int      tableID;
+  int      truncation;
+  int      position;
+  bool     defmissval;
+  bool     deffillval;
+  int      xtype;
+  int      ndims;
+  int      gmapid;
+  int      positive;
+  int      dimids[8];
+  int      dimtype[8];
+  int      chunks[8];
+  int      chunked;
+  int      chunktype;
+  int      natts;
+  int      deflate;
+  bool     lunsigned;
+  bool     lvalidrange;
+  int     *atts;
+  size_t   vctsize;
+  double  *vct;
+  double   missval;
+  double   fillval;
+  double   addoffset;
+  double   scalefactor;
+  double   validrange[2];
+  char     name[CDI_MAX_NAME];
+  char     longname[CDI_MAX_NAME];
+  char     stdname[CDI_MAX_NAME];
+  char     units[CDI_MAX_NAME];
+  char     extra[CDI_MAX_NAME];
+  ensinfo_t   *ensdata;    /* Ensemble information */
+}
+ncvar_t;
+
+
+static
+void scanTimeString(const char *ptu, int *rdate, int *rtime)
+{
+  int year = 1, month = 1, day = 1;
+  int hour = 0, minute = 0, second = 0;
+  int v1 = 1, v2 = 1, v3 = 1;
+
+  *rdate = 0;
+  *rtime = 0;
+
+  if ( *ptu )
+    {
+      v1 = atoi(ptu);
+      if ( v1 < 0 ) ptu++;
+      while ( isdigit((int) *ptu) ) ptu++;
+      if ( *ptu )
+        {
+          v2 = atoi(++ptu);
+          while ( isdigit((int) *ptu) ) ptu++;
+          if ( *ptu )
+            {
+              v3 = atoi(++ptu);
+              while ( isdigit((int) *ptu) ) ptu++;
+            }
+        }
+    }
+
+  if ( v3 > 999 && v1 < 32 )
+    { year = v3; month = v2; day = v1; }
+  else
+    { year = v1; month = v2; day = v3; }
+
+  while ( isspace((int) *ptu) ) ptu++;
+
+  if ( *ptu )
+    {
+      while ( ! isdigit((int) *ptu) ) ptu++;
+
+      hour = atoi(ptu);
+      while ( isdigit((int) *ptu) ) ptu++;
+      if ( *ptu == ':' )
+        {
+          ptu++;
+          minute = atoi(ptu);
+          while ( isdigit((int) *ptu) ) ptu++;
+          if ( *ptu == ':' )
+            {
+              ptu++;
+              second = atoi(ptu);
+            }
+        }
+    }
+
+  *rdate = cdiEncodeDate(year, month, day);
+  *rtime = cdiEncodeTime(hour, minute, second);
+}
+
+static
+int scanTimeUnit(const char *unitstr)
+{
+  size_t len = strlen(unitstr);
+  int timeunit = get_timeunit(len, unitstr);
+  if ( timeunit == -1 )
+    Message("Unsupported TIMEUNIT: %s!", unitstr);
+
+  return timeunit;
+}
+
+static
+void setForecastTime(const char *timestr, taxis_t *taxis)
+{
+  (*taxis).fdate = 0;
+  (*taxis).ftime = 0;
+
+  int len = (int) strlen(timestr);
+  if ( len == 0 ) return;
+
+  int fdate = 0, ftime = 0;
+  scanTimeString(timestr, &fdate, &ftime);
+
+  (*taxis).fdate = fdate;
+  (*taxis).ftime = ftime;
+}
+
+static
+int setBaseTime(const char *timeunits, taxis_t *taxis)
+{
+  int timetype = TAXIS_ABSOLUTE;
+  int rdate = -1, rtime = -1;
+
+  size_t len = strlen(timeunits);
+  char *tu = (char *) Malloc((len+1) * sizeof (char));
+  memcpy(tu, timeunits, (len+1) * sizeof (char));
+  char *ptu = tu;
+
+  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
+
+  int timeunit = get_timeunit(len, ptu);
+  if ( timeunit == -1 )
+    {
+      Message("Unsupported TIMEUNIT: %s!", timeunits);
+      return 1;
+    }
+
+  while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+  if ( *ptu )
+    {
+      while ( isspace(*ptu) ) ptu++;
+
+      if ( memcmp(ptu, "as", 2) == 0 )
+        timetype = TAXIS_ABSOLUTE;
+      else if ( memcmp(ptu, "since", 5) == 0 )
+        timetype = TAXIS_RELATIVE;
+
+      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+      if ( *ptu )
+        {
+          while ( isspace(*ptu) ) ptu++;
+
+          if ( timetype == TAXIS_ABSOLUTE )
+            {
+              if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
+                {
+                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
+                  timeunit = -1;
+                }
+              else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
+                {
+                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
+                  timeunit = -1;
+                }
+            }
+          else if ( timetype == TAXIS_RELATIVE )
+            {
+              scanTimeString(ptu, &rdate, &rtime);
+
+              (*taxis).rdate = rdate;
+              (*taxis).rtime = rtime;
+
+              if ( CDI_Debug )
+                Message("rdate = %d  rtime = %d", rdate, rtime);
+            }
+        }
+    }
+
+  (*taxis).type = timetype;
+  (*taxis).unit = timeunit;
+
+  Free(tu);
+
+  if ( CDI_Debug )
+    Message("timetype = %d  unit = %d", timetype, timeunit);
+
+  return 0;
+}
+
+static
+void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint)
+{
+  nc_type atttype;
+  size_t nc_attlen;
+
+  *attint = 0;
+
+  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+  if ( atttype != NC_CHAR )
+    {
+      int *pintatt = (int)nc_attlen > attlen
+        ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint;
+
+      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
+
+      if ( (int)nc_attlen > attlen )
+        {
+          memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
+          Free(pintatt);
+        }
+    }
+}
+
+static
+void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
+{
+  nc_type atttype;
+  size_t nc_attlen;
+
+  *attdouble = 0;
+
+  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+  if ( atttype != NC_CHAR )
+    {
+      double *pdoubleatt = NULL;
+
+      if ( (int)nc_attlen > attlen )
+        pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
+      else
+        pdoubleatt = attdouble;
+
+      cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);
+
+      if ( (int)nc_attlen > attlen )
+        {
+          memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
+          Free(pdoubleatt);
+        }
+    }
+}
+
+static
+bool cdfCheckAttText(int fileID, int ncvarid, const char *attname)
+{
+  bool status = false;
+  nc_type atttype;
+
+  int status_nc = nc_inq_atttype(fileID, ncvarid, attname, &atttype);
+
+  if ( status_nc == NC_NOERR
+       && (atttype == NC_CHAR
+#if  defined  (HAVE_NETCDF4)
+           || atttype == NC_STRING
+#endif
+           ) )
+    {
+      status = true;
+    }
+
+  return status;
+}
+
+static
+void cdfGetAttText(int fileID, int ncvarid, const char *attname, int attlen, char *atttext)
+{
+  nc_type atttype;
+  size_t nc_attlen;
+
+  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+  if ( atttype == NC_CHAR )
+    {
+      char attbuf[65636];
+      if ( nc_attlen < sizeof(attbuf) )
+        {
+          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
+
+          if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
+
+          attbuf[nc_attlen++] = 0;
+          memcpy(atttext, attbuf, nc_attlen);
+        }
+      else
+        {
+          atttext[0] = 0;
+        }
+    }
+#if  defined  (HAVE_NETCDF4)
+  else if ( atttype == NC_STRING )
+    {
+      if ( nc_attlen == 1 )
+        {
+          char *attbuf = NULL;
+          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
+
+          size_t ssize = strlen(attbuf) + 1;
+
+          if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
+          memcpy(atttext, attbuf, ssize);
+          atttext[ssize - 1] = 0;
+          Free(attbuf);
+        }
+      else
+        {
+          atttext[0] = 0;
+        }
+    }
+#endif
+}
+
+static
+bool xtypeIsText(nc_type xtype)
+{
+  bool isText = false;
+
+  if      ( xtype == NC_CHAR ) isText = true;
+#if  defined  (HAVE_NETCDF4)
+  else if ( xtype == NC_STRING ) isText = true;
+#endif
+
+  return isText;
+}
+
+static
+bool xtypeIsFloat(nc_type xtype)
+{
+  bool isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE;
+
+  return isFloat;
+}
+
+static
+bool xtypeIsInt(nc_type xtype)
+{
+  bool isInt = xtype == NC_SHORT || xtype == NC_INT
+            || xtype == NC_BYTE
+#if  defined  (HAVE_NETCDF4)
+            || xtype == NC_USHORT || xtype == NC_UINT
+            || xtype == NC_UBYTE
+#endif
+             ;
+
+  return isInt;
+}
+
+static
+int cdfInqDatatype(int xtype, bool lunsigned)
+{
+  int datatype = -1;
+
+#if  defined  (HAVE_NETCDF4)
+  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
+#endif
+
+  if      ( xtype == NC_BYTE   )  datatype = DATATYPE_INT8;
+  /* else if ( xtype == NC_CHAR   )  datatype = DATATYPE_UINT8; */
+  else if ( xtype == NC_SHORT  )  datatype = DATATYPE_INT16;
+  else if ( xtype == NC_INT    )  datatype = DATATYPE_INT32;
+  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
+  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
+#if  defined  (HAVE_NETCDF4)
+  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
+  else if ( xtype == NC_LONG   )  datatype = DATATYPE_INT32;
+  else if ( xtype == NC_USHORT )  datatype = DATATYPE_UINT16;
+  else if ( xtype == NC_UINT   )  datatype = DATATYPE_UINT32;
+  else if ( xtype == NC_INT64  )  datatype = DATATYPE_FLT64;
+  else if ( xtype == NC_UINT64 )  datatype = DATATYPE_FLT64;
+#endif
+
+  return datatype;
+}
+
+
+/* not used
+int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
+{
+  int tsID, recID;
+
+  recID = streamptr->tsteps[0].curRecID++;
+  printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
+  printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
+
+  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
+    {
+      streamptr->tsteps[0].curRecID = 0;
+    }
+
+  *varID   = streamptr->tsteps[0].records[recID].varID;
+  *levelID = streamptr->tsteps[0].records[recID].levelID;
+
+  streamptr->record->varID   = *varID;
+  streamptr->record->levelID = *levelID;
+
+  if ( CDI_Debug )
+    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
+
+  return (recID+1);
+}
+*/
+
+void cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor)
+{
+  int laddoffset   = IS_NOT_EQUAL(addoffset, 0);
+  int lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+  if ( laddoffset || lscalefactor )
+    {
+      for ( size_t i = 0; i < size; ++i )
+        {
+          if ( lscalefactor ) data[i] *= scalefactor;
+          if ( laddoffset )   data[i] += addoffset;
+        }
+    }
+}
+
+static
+void cdfCreateRecords(stream_t *streamptr, int tsID)
+{
+  if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return;
+
+  if ( streamptr->tsteps[tsID].nallrecs > 0 ) return;
+
+  int vlistID  = streamptr->vlistID;
+
+  tsteps_t* sourceTstep = streamptr->tsteps;
+  tsteps_t* destTstep = sourceTstep + tsID;
+
+  int nvars = vlistNvars(vlistID);
+  int nrecs = vlistNrecs(vlistID);
+
+  if ( nrecs <= 0 ) return;
+
+  if ( tsID == 0 )
+    {
+      int nvrecs = nrecs; /* use all records at first timestep */
+
+      streamptr->nrecs += nrecs;
+
+      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+      destTstep->nrecs      = nrecs;
+      destTstep->nallrecs   = nrecs;
+      destTstep->recordSize = nrecs;
+      destTstep->curRecID   = UNDEFID;
+      destTstep->recIDs     = (int *) Malloc((size_t)nvrecs*sizeof (int));;
+      for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
+
+      record_t *records = destTstep->records;
+
+      for ( int varID = 0, recID = 0; varID < nvars; varID++ )
+        {
+          int zaxisID = vlistInqVarZaxis(vlistID, varID);
+          int nlev    = zaxisInqSize(zaxisID);
+          for ( int levelID = 0; levelID < nlev; levelID++ )
+            {
+              recordInitEntry(&records[recID]);
+              records[recID].varID   = (short)varID;
+              records[recID].levelID = (short)levelID;
+              recID++;
+            }
+        }
+    }
+  else if ( tsID == 1 )
+    {
+      int nvrecs = 0;
+      for ( int varID = 0; varID < nvars; varID++ )
+        {
+          if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+            {
+              int zaxisID = vlistInqVarZaxis(vlistID, varID);
+              nvrecs += zaxisInqSize(zaxisID);
+            }
+        }
+
+      streamptr->nrecs += nvrecs;
+
+      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+      destTstep->nrecs      = nvrecs;
+      destTstep->nallrecs   = nrecs;
+      destTstep->recordSize = nrecs;
+      destTstep->curRecID   = UNDEFID;
+
+      memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
+
+      if ( nvrecs )
+        {
+          destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int));
+          for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ )
+            {
+              int varID = destTstep->records[recID].varID;
+              if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+                {
+                  destTstep->recIDs[vrecID++] = recID;
+                }
+            }
+        }
+    }
+  else
+    {
+      if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1);
+
+      int nvrecs = streamptr->tsteps[1].nrecs;
+
+      streamptr->nrecs += nvrecs;
+
+      destTstep->records    = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+      destTstep->nrecs      = nvrecs;
+      destTstep->nallrecs   = nrecs;
+      destTstep->recordSize = nrecs;
+      destTstep->curRecID   = UNDEFID;
+
+      memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
+
+      destTstep->recIDs     = (int *) Malloc((size_t)nvrecs * sizeof(int));
+
+      memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int));
+    }
+}
+
+static
+int cdf_time_dimid(int fileID, int ndims, int nvars)
+{
+  char dimname[80];
+  for ( int dimid = 0; dimid < ndims; ++dimid )
+    {
+      dimname[0] = 0;
+      cdf_inq_dimname(fileID, dimid, dimname);
+      size_t len = strlen(dimname);
+      if ( len >= 4 && memcmp(dimname, "time", 4) == 0 ) return dimid;
+      if ( len >= 4 && memcmp(dimname, "Time", 4) == 0 ) return dimid;
+    }
+
+  for ( int varid = 0; varid < nvars; ++varid )
+    {
+      nc_type xtype;
+      int nvdims, nvatts, dimids[9];
+      cdf_inq_var(fileID, varid, NULL, &xtype, &nvdims, dimids, &nvatts);
+      if ( nvdims == 1 )
+        {
+          char sbuf[CDI_MAX_NAME];
+          for ( int iatt = 0; iatt < nvatts; ++iatt )
+            {
+              sbuf[0] = 0;
+              cdf_inq_attname(fileID, varid, iatt, sbuf);
+              if ( strncmp(sbuf, "units", 5) == 0 )
+                {
+                  cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
+                  str_tolower(sbuf);
+
+                  if ( is_time_units(sbuf) ) return dimids[0];
+                }
+            }
+        }
+    }
+
+  return UNDEFID;
+}
+
+static
+void init_ncdims(long ndims, ncdim_t *ncdims)
+{
+  for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      ncdims[ncdimid].ncvarid      = UNDEFID;
+      ncdims[ncdimid].dimtype      = UNDEFID;
+      ncdims[ncdimid].len          = 0;
+      ncdims[ncdimid].name[0]      = 0;
+    }
+}
+
+static
+void init_ncvars(long nvars, ncvar_t *ncvars)
+{
+  for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid )
+    {
+      ncvars[ncvarid].ncid            = UNDEFID;
+      ncvars[ncvarid].isvar           = UNDEFID;
+      ncvars[ncvarid].ignore          = false;
+      ncvars[ncvarid].isx             = false;
+      ncvars[ncvarid].isy             = false;
+      ncvars[ncvarid].islon           = false;
+      ncvars[ncvarid].islat           = false;
+      ncvars[ncvarid].islev           = false;
+      ncvars[ncvarid].istime          = false;
+      ncvars[ncvarid].warn            = false;
+      ncvars[ncvarid].climatology     = false;
+      ncvars[ncvarid].lformula        = false;
+      ncvars[ncvarid].lformulaterms   = false;
+      ncvars[ncvarid].tsteptype       = TSTEP_CONSTANT;
+      ncvars[ncvarid].param           = UNDEFID;
+      ncvars[ncvarid].code            = UNDEFID;
+      ncvars[ncvarid].tabnum          = 0;
+      ncvars[ncvarid].calendar        = FALSE;
+      ncvars[ncvarid].bounds          = UNDEFID;
+      ncvars[ncvarid].gridID          = UNDEFID;
+      ncvars[ncvarid].zaxisID         = UNDEFID;
+      ncvars[ncvarid].gridtype        = UNDEFID;
+      ncvars[ncvarid].zaxistype       = UNDEFID;
+      ncvars[ncvarid].xdim            = UNDEFID;
+      ncvars[ncvarid].ydim            = UNDEFID;
+      ncvars[ncvarid].zdim            = UNDEFID;
+      ncvars[ncvarid].xvarid          = UNDEFID;
+      ncvars[ncvarid].yvarid          = UNDEFID;
+      ncvars[ncvarid].zvarid          = UNDEFID;
+      ncvars[ncvarid].tvarid          = UNDEFID;
+      ncvars[ncvarid].psvarid         = UNDEFID;
+      ncvars[ncvarid].p0varid         = UNDEFID;
+      ncvars[ncvarid].ncoordvars      = 0;
+      for ( int i = 0; i < MAX_COORDVARS; ++i )
+        ncvars[ncvarid].coordvarids[i]  = UNDEFID;
+      ncvars[ncvarid].nauxvars      = 0;
+      for ( int i = 0; i < MAX_AUXVARS; ++i )
+        ncvars[ncvarid].auxvarids[i]  = UNDEFID;
+      ncvars[ncvarid].cellarea        = UNDEFID;
+      ncvars[ncvarid].tableID         = UNDEFID;
+      ncvars[ncvarid].xtype           = 0;
+      ncvars[ncvarid].ndims           = 0;
+      ncvars[ncvarid].gmapid          = UNDEFID;
+      ncvars[ncvarid].vctsize         = 0;
+      ncvars[ncvarid].vct             = NULL;
+      ncvars[ncvarid].truncation      = 0;
+      ncvars[ncvarid].position        = 0;
+      ncvars[ncvarid].positive        = 0;
+      ncvars[ncvarid].chunked         = 0;
+      ncvars[ncvarid].chunktype       = UNDEFID;
+      ncvars[ncvarid].defmissval      = false;
+      ncvars[ncvarid].deffillval      = false;
+      ncvars[ncvarid].missval         = 0;
+      ncvars[ncvarid].fillval         = 0;
+      ncvars[ncvarid].addoffset       = 0;
+      ncvars[ncvarid].scalefactor     = 1;
+      ncvars[ncvarid].name[0]         = 0;
+      ncvars[ncvarid].longname[0]     = 0;
+      ncvars[ncvarid].stdname[0]      = 0;
+      ncvars[ncvarid].units[0]        = 0;
+      ncvars[ncvarid].extra[0]        = 0;
+      ncvars[ncvarid].natts           = 0;
+      ncvars[ncvarid].atts            = NULL;
+      ncvars[ncvarid].deflate         = 0;
+      ncvars[ncvarid].lunsigned       = false;
+      ncvars[ncvarid].lvalidrange     = false;
+      ncvars[ncvarid].validrange[0]   = VALIDMISS;
+      ncvars[ncvarid].validrange[1]   = VALIDMISS;
+      ncvars[ncvarid].ensdata         = NULL;
+    }
+}
+
+static
+void cdf_set_var(ncvar_t *ncvars, int ncvarid, short isvar)
+{
+  if ( ncvars[ncvarid].isvar != UNDEFID &&
+       ncvars[ncvarid].isvar != isvar   &&
+       ncvars[ncvarid].warn  == false )
+    {
+      if ( ! ncvars[ncvarid].ignore )
+        Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name);
+
+      ncvars[ncvarid].warn = true;
+      isvar = FALSE;
+    }
+
+  ncvars[ncvarid].isvar = isvar;
+}
+
+static
+void cdf_set_dim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype)
+{
+  if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID &&
+       ncvars[ncvarid].dimtype[dimid] != dimtype )
+    {
+      Warning("Inconsistent dimension definition for %s! dimid = %d;  type = %d;  newtype = %d",
+              ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype);
+    }
+
+  ncvars[ncvarid].dimtype[dimid] = dimtype;
+}
+
+static
+int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid)
+{
+  int status = 0;
+  *apvarid = -1;
+  *bvarid  = -1;
+  *psvarid = -1;
+  *avarid  = -1;
+  *p0varid = -1;
+  enum { attstringlen = 8192 }; char attstring[attstringlen];
+  cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
+  if ( strcmp(attstring, "p = ap + b*ps") == 0 )
+    {
+      status = 1;
+      bool lstop = false;
+      int dimvarid;
+      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
+      char *pstring = attstring;
+
+      for ( int i = 0; i < 3; i++ )
+        {
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *tagname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = true;
+          *pstring++ = 0;
+
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *varname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = true;
+          *pstring++ = 0;
+
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
+            {
+              if      ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
+              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
+              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
+            }
+          else if ( strcmp(tagname, "ps:") != 0 )
+            {
+              Warning("%s - %s", nc_strerror(status_nc), varname);
+            }
+
+          if ( lstop ) break;
+        }
+    }
+  else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 )
+    {
+      status = 2;
+      bool lstop = false;
+      int dimvarid;
+      cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
+      char *pstring = attstring;
+
+      for ( int i = 0; i < 4; i++ )
+        {
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *tagname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = true;
+          *pstring++ = 0;
+
+          while ( isspace((int) *pstring) ) pstring++;
+          if ( *pstring == 0 ) break;
+          char *varname = pstring;
+          while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+          if ( *pstring == 0 ) lstop = true;
+          *pstring++ = 0;
+
+          int status_nc = nc_inq_varid(ncid, varname, &dimvarid);
+          if ( status_nc == NC_NOERR )
+            {
+              if      ( strcmp(tagname, "a:")  == 0 ) *avarid  = dimvarid;
+              else if ( strcmp(tagname, "b:")  == 0 ) *bvarid  = dimvarid;
+              else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
+              else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid;
+            }
+          else if ( strcmp(tagname, "ps:") != 0 )
+            {
+              Warning("%s - %s", nc_strerror(status_nc), varname);
+            }
+
+          if ( lstop ) break;
+        }
+    }
+
+  return status;
+}
+
+static
+bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
+{
+  bool status = false;
+  int ncfvarid = ncvarid;
+  ncvar_t *ncvar = &ncvars[ncvarid];
+
+  if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 )
+    {
+      cdiConvention = CDI_CONVENTION_CF;
+
+      status = true;
+      ncvar->zaxistype = ZAXIS_HYBRID;
+      int dimid = ncvar->dimids[0];
+      size_t dimlen = ncdims[dimid].len;
+
+      int ret;
+      int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1;
+      if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
+        ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1);
+      if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
+      if ( bvarid1  != -1 ) ncvars[bvarid1].isvar  = FALSE;
+      if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
+      if ( avarid1  != -1 ) ncvars[avarid1].isvar = FALSE;
+      if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1;
+
+      if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
+        {
+          ncfvarid = ncvar->bounds;
+          int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1;
+          ret = 0;
+          if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
+            ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2);
+          if ( ret == 1 ) avarid2 = apvarid2;
+          if ( avarid2 != -1 && bvarid2 != -1 )
+            {
+              ncvars[avarid2].isvar = FALSE;
+              ncvars[bvarid2].isvar = FALSE;
+
+              if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 )
+                {
+                  double px = 1;
+                  if ( ret == 2 && p0varid1 == p0varid2 )
+                    cdf_get_var_double(ncid, p0varid2, &px);
+
+                  double abuf[dimlen*2], bbuf[dimlen*2];
+                  cdf_get_var_double(ncid, avarid2, abuf);
+                  cdf_get_var_double(ncid, bvarid2, bbuf);
+                  /*
+                  for ( int i = 0; i < dimlen; ++i )
+                    printf("%d  %g %g    %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]);
+                  */
+                  size_t vctsize = (dimlen+1)*2;
+                  double *vct = (double *) Malloc(vctsize * sizeof(double));
+                  for ( size_t i = 0; i < dimlen; ++i )
+                    {
+                      vct[i] = abuf[i*2];
+                      vct[i+dimlen+1] = bbuf[i*2];
+                    }
+                  vct[dimlen]     = abuf[dimlen*2-1];
+                  vct[dimlen*2+1] = bbuf[dimlen*2-1];
+
+                  if ( ret == 2 && IS_NOT_EQUAL(px, 1) )
+                    for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px;
+
+                  ncvar->vct = vct;
+                  ncvar->vctsize = vctsize;
+                }
+            }
+        }
+    }
+
+  return status;
+}
+
+static
+void cdf_set_cdi_attr(int ncid, int ncvarid, int attnum, int cdiID, int varID)
+{
+  nc_type atttype;
+  size_t attlen;
+  char attname[CDI_MAX_NAME];
+
+  cdf_inq_attname(ncid, ncvarid, attnum, attname);
+  cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+  cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
+
+  if ( xtypeIsInt(atttype) )
+    {
+      int attint[attlen];
+      cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
+      int datatype = (atttype == NC_SHORT)  ? DATATYPE_INT16 :
+                     (atttype == NC_BYTE)   ? DATATYPE_INT8 :
+#if  defined  (HAVE_NETCDF4)
+                     (atttype == NC_UBYTE)  ? DATATYPE_UINT8 :
+                     (atttype == NC_USHORT) ? DATATYPE_UINT16 :
+                     (atttype == NC_UINT)   ? DATATYPE_UINT32 :
+#endif
+                     DATATYPE_INT32;
+      cdiDefAttInt(cdiID, varID, attname, datatype, (int)attlen, attint);
+    }
+  else if ( xtypeIsFloat(atttype) )
+    {
+      double attflt[attlen];
+      cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
+      int datatype = (atttype == NC_FLOAT) ? DATATYPE_FLT32 : DATATYPE_FLT64;
+      cdiDefAttFlt(cdiID, varID, attname, datatype, (int)attlen, attflt);
+    }
+  else if ( xtypeIsText(atttype) )
+    {
+      enum {attstringlen = 8192}; char attstring[attstringlen];
+      cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+      cdiDefAttTxt(cdiID, varID, attname, (int)attlen, attstring);
+    }
+}
+
+static
+void cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname)
+{
+  char axis[7];
+  static const char iaxis[] = {'t', 'z', 'y', 'x'};
+
+  fprintf(stderr, "%s:\n", oname);
+
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      int ndim = 0;
+      if ( ncvars[ncvarid].isvar )
+        {
+          axis[ndim++] = 'v';
+          axis[ndim++] = ':';
+          for ( int i = 0; i < ncvars[ncvarid].ndims; i++ )
+            {/*
+              if      ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0];
+              else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1];
+              else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2];
+              else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3];
+              else
+             */
+              if      ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0];
+              else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1];
+              else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2];
+              else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3];
+              else                                             axis[ndim++] = '?';
+            }
+        }
+      else
+        {
+          axis[ndim++] = 'c';
+          axis[ndim++] = ':';
+          if      ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0];
+          else if ( ncvars[ncvarid].islev  ) axis[ndim++] = iaxis[1];
+          else if ( ncvars[ncvarid].islat  ) axis[ndim++] = iaxis[2];
+          else if ( ncvars[ncvarid].isy    ) axis[ndim++] = iaxis[2];
+          else if ( ncvars[ncvarid].islon  ) axis[ndim++] = iaxis[3];
+          else if ( ncvars[ncvarid].isx    ) axis[ndim++] = iaxis[3];
+          else                               axis[ndim++] = '?';
+        }
+
+      axis[ndim++] = 0;
+
+      fprintf(stderr, "%3d %3d  %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name);
+    }
+}
+
+static
+void cdf_scan_attr_axis(ncvar_t *ncvars, ncdim_t *ncdims, int ncvarid, const char *attstring, size_t attlen,
+                        int nvdims, int *dimidsp, const char *name)
+{
+  int i;
+  for ( i = 0; i < (int)attlen; ++i )
+    {
+      if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' &&
+           attstring[i] != 'y' && attstring[i] != 'x' )
+        {
+          Warning("Unexpected character in axis attribute for %s, ignored!", name);
+          break;
+        }
+    }
+
+  if ( i == (int) attlen && (int) attlen == nvdims )
+    {
+      while ( attlen-- )
+        {
+          if ( (int) attstring[attlen] == 't' )
+            {
+              if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
+              cdf_set_dim(ncvars, ncvarid, (int)attlen, T_AXIS);
+            }
+          else if ( (int) attstring[attlen] == 'z' )
+            {
+              ncvars[ncvarid].zdim = dimidsp[attlen];
+              cdf_set_dim(ncvars, ncvarid, (int)attlen, Z_AXIS);
+
+              if ( ncvars[ncvarid].ndims == 1 )
+                {
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
+                }
+            }
+          else if ( (int) attstring[attlen] == 'y' )
+            {
+              ncvars[ncvarid].ydim = dimidsp[attlen];
+              cdf_set_dim(ncvars, ncvarid, (int)attlen, Y_AXIS);
+
+              if ( ncvars[ncvarid].ndims == 1 )
+                {
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS;
+                }
+            }
+          else if ( (int) attstring[attlen] == 'x' )
+            {
+              ncvars[ncvarid].xdim = dimidsp[attlen];
+              cdf_set_dim(ncvars, ncvarid, (int)attlen, X_AXIS);
+
+              if ( ncvars[ncvarid].ndims == 1 )
+                {
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS;
+                }
+            }
+        }
+    }
+}
+
+static
+void cdf_scan_var_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, int modelID, int format)
+{
+  int ncdimid;
+  int nvdims, nvatts;
+  int iatt;
+  nc_type xtype, atttype;
+  size_t attlen;
+  char name[CDI_MAX_NAME];
+  char attname[CDI_MAX_NAME];
+  const int attstringlen = 8192; char attstring[8192];
+
+  int nchecked_vars = 0;
+  enum { max_check_vars = 9 };
+  char *checked_vars[max_check_vars];
+  for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL;
+
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      int ncid    = ncvars[ncvarid].ncid;
+      int *dimidsp = ncvars[ncvarid].dimids;
+
+      cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
+      strcpy(ncvars[ncvarid].name, name);
+
+      for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ )
+        ncvars[ncvarid].dimtype[ncdimid] = -1;
+
+      ncvars[ncvarid].xtype = xtype;
+      ncvars[ncvarid].ndims = nvdims;
+
+#if  defined  (HAVE_NETCDF4)
+      if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
+        {
+          int shuffle, deflate, deflate_level;
+          size_t chunks[nvdims];
+          int storage_in;
+          nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level);
+          if ( deflate > 0 ) ncvars[ncvarid].deflate = 1;
+
+          if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR )
+            {
+              if ( storage_in == NC_CHUNKED )
+                {
+                  ncvars[ncvarid].chunked = 1;
+                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
+                  if ( CDI_Debug )
+                    {
+                      fprintf(stderr, "%s: chunking %d %d %d  chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED);
+                      for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
+                      fprintf(stderr, "\n");
+                    }
+                  {
+                    char *buf = ncvars[ncvarid].extra;
+                    size_t pos = strlen(buf);
+                    static const char prefix[] = "chunks=";
+                    memcpy(buf + pos, prefix, sizeof (prefix));
+                    pos += sizeof (prefix) - 1;
+                    for ( int i = nvdims-1; i >= 0; --i )
+                      {
+                        pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i],
+                                                i > 0 ? "x" : ""));
+                      }
+                    buf[pos] = ' '; buf[pos + 1] = 0;
+                  }
+                }
+            }
+        }
+#endif
+
+      if ( nvdims > 0 )
+        {
+          if ( timedimid == dimidsp[0] )
+            {
+              ncvars[ncvarid].tsteptype = TSTEP_INSTANT;
+              cdf_set_dim(ncvars, ncvarid, 0, T_AXIS);
+            }
+          else
+            {
+              for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ )
+                {
+                  if ( timedimid == dimidsp[ncdimid] )
+                    {
+                      Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
+                      ncvars[ncvarid].isvar = FALSE;
+                    }
+                }
+            }
+        }
+
+      for ( iatt = 0; iatt < nvatts; iatt++ )
+        {
+          cdf_inq_attname(ncid, ncvarid, iatt, attname);
+          cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
+          cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+
+          if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname);
+            }
+          else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname);
+            }
+          else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
+            }
+          else if ( strcmp(attname, "calendar") == 0 )
+            {
+              ncvars[ncvarid].calendar = TRUE;
+            }
+          else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
+            {
+	      char paramstr[32];
+	      int pnum = 0, pcat = 255, pdis = 255;
+              cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr);
+	      sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis);
+	      ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) )
+            {
+              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code);
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
+            {
+              int tablenum;
+              cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
+              if ( tablenum > 0 )
+                {
+                  ncvars[ncvarid].tabnum = tablenum;
+                  ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL);
+                  if ( ncvars[ncvarid].tableID == CDI_UNDEFID )
+                    ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL);
+                }
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              if ( memcmp(attstring, "Triangular", attlen) == 0 )
+                ncvars[ncvarid].gridtype = GRID_SPECTRAL;
+            }
+          else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              str_tolower(attstring);
+
+              set_gridtype(attstring, &ncvars[ncvarid].gridtype);
+
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              str_tolower(attstring);
+
+              set_zaxistype(attstring, &ncvars[ncvarid].zaxistype);
+
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
+            {
+              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+            }
+          else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) )
+            {
+              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+            }
+          else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) )
+            {
+              cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position);
+            }
+          else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
+            {
+	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
+	      /*
+		if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
+		if ( ncvars[ncvarid].addoffset != 0 )
+		Warning("attribute add_offset not supported for atttype %d", atttype);
+	      */
+	      /* (also used for lon/lat) cdf_set_var(ncvars, ncvarid, TRUE); */
+            }
+          else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
+            {
+	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
+	      /*
+		if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
+		if ( ncvars[ncvarid].scalefactor != 1 )
+		Warning("attribute scale_factor not supported for atttype %d", atttype);
+	      */
+	      /* (also used for lon/lat) cdf_set_var(ncvars, ncvarid, TRUE); */
+            }
+          else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              int ncboundsid;
+              int status = nc_inq_varid(ncid, attstring, &ncboundsid);
+              if ( status == NC_NOERR )
+                {
+                  ncvars[ncvarid].climatology = true;
+                  ncvars[ncvarid].bounds = ncboundsid;
+                  cdf_set_var(ncvars, ncvars[ncvarid].bounds, FALSE);
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                }
+              else
+                Warning("%s - %s", nc_strerror(status), attstring);
+            }
+          else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              int ncboundsid;
+              int status = nc_inq_varid(ncid, attstring, &ncboundsid);
+              if ( status == NC_NOERR )
+                {
+                  ncvars[ncvarid].bounds = ncboundsid;
+                  cdf_set_var(ncvars, ncvars[ncvarid].bounds, FALSE);
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                }
+              else
+                Warning("%s - %s", nc_strerror(status), attstring);
+            }
+          else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 )
+            {
+              ncvars[ncvarid].lformulaterms = true;
+            }
+          else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 )
+            {
+              ncvars[ncvarid].lformula = true;
+            }
+          else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              char *pstring = attstring;
+
+              while ( isspace((int) *pstring) ) pstring++;
+              char *cell_measures = pstring;
+              while ( isalnum((int) *pstring) ) pstring++;
+              *pstring++ = 0;
+              while ( isspace((int) *pstring) ) pstring++;
+              char *cell_var = pstring;
+              while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
+              *pstring++ = 0;
+              /*
+              printf("cell_measures >%s<\n", cell_measures);
+              printf("cell_var >%s<\n", cell_var);
+              */
+              if ( memcmp(cell_measures, "area", 4) == 0 )
+                {
+                  int nc_cell_id;
+                  int status = nc_inq_varid(ncid, cell_var, &nc_cell_id);
+                  if ( status == NC_NOERR )
+                    {
+                      ncvars[ncvarid].cellarea = nc_cell_id;
+                      /* ncvars[nc_cell_id].isvar = UNDEFID; */
+                      cdf_set_var(ncvars, nc_cell_id, FALSE);
+                    }
+                  else
+                    Warning("%s - %s", nc_strerror(status), cell_var);
+                }
+              else
+                {
+                  Warning("%s has an unexpected contents: %s", attname, cell_measures);
+                }
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          /*
+          else if ( strcmp(attname, "coordinates") == 0 )
+            {
+              char *pstring, *xvarname = NULL, *yvarname = NULL;
+
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              pstring = attstring;
+
+              while ( isspace((int) *pstring) ) pstring++;
+              xvarname = pstring;
+              while ( isgraph((int) *pstring) ) pstring++;
+              *pstring++ = 0;
+              while ( isspace((int) *pstring) ) pstring++;
+              yvarname = pstring;
+              while ( isgraph((int) *pstring) ) pstring++;
+              *pstring++ = 0;
+
+              cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid);
+              cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid);
+
+              cdf_set_var(ncvars, ncvars[ncvarid].xvarid, FALSE);
+              cdf_set_var(ncvars, ncvars[ncvarid].yvarid, FALSE);
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          */
+          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
+            {
+              bool lstop = false;
+
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              char *pstring = attstring;
+
+              for ( int i = 0; i < MAX_COORDVARS; i++ )
+                {
+                  while ( isspace((int) *pstring) ) pstring++;
+                  if ( *pstring == 0 ) break;
+                  char *varname = pstring;
+                  while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+                  if ( *pstring == 0 ) lstop = true;
+                  *pstring++ = 0;
+
+                  int dimvarid;
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
+                  if ( status == NC_NOERR )
+                    {
+                      cdf_set_var(ncvars, dimvarid, FALSE);
+                      if ( cdiIgnoreAttCoordinates == false )
+                        {
+                          ncvars[ncvarid].coordvarids[i] = dimvarid;
+                          ncvars[ncvarid].ncoordvars++;
+                        }
+                    }
+                  else
+                    {
+                      int k;
+                      for ( k = 0; k < nchecked_vars; ++k )
+                        if ( strcmp(checked_vars[k], varname) == 0 ) break;
+
+                      if ( k == nchecked_vars )
+                        {
+                          if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname);
+                          Warning("%s - %s", nc_strerror(status), varname);
+                        }
+                    }
+
+                  if ( lstop ) break;
+                }
+
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
+            {
+              bool lstop = false;
+
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              char *pstring = attstring;
+
+              for ( int i = 0; i < MAX_AUXVARS; i++ )
+                {
+                  while ( isspace((int) *pstring) ) pstring++;
+                  if ( *pstring == 0 ) break;
+                  char *varname = pstring;
+                  while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+                  if ( *pstring == 0 ) lstop = true;
+                  *pstring++ = 0;
+
+                  int dimvarid;
+                  int status = nc_inq_varid(ncid, varname, &dimvarid);
+                  if ( status == NC_NOERR )
+                    {
+                      cdf_set_var(ncvars, dimvarid, FALSE);
+                      //  if ( cdiIgnoreAttCoordinates == FALSE )
+                        {
+                          ncvars[ncvarid].auxvarids[i] = dimvarid;
+                          ncvars[ncvarid].nauxvars++;
+                        }
+                    }
+                  else
+                    Warning("%s - %s", nc_strerror(status), varname);
+
+                  if ( lstop ) break;
+                }
+
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              int nc_gmap_id;
+              int status = nc_inq_varid(ncid, attstring, &nc_gmap_id);
+              if ( status == NC_NOERR )
+                {
+                  ncvars[ncvarid].gmapid = nc_gmap_id;
+                  cdf_set_var(ncvars, ncvars[ncvarid].gmapid, FALSE);
+                }
+              else
+                Warning("%s - %s", nc_strerror(status), attstring);
+
+              cdf_set_var(ncvars, ncvarid, TRUE);
+            }
+          else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              str_tolower(attstring);
+
+              if    ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN;
+              else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP;
+
+              if ( ncvars[ncvarid].ndims == 1 )
+                {
+                  cdf_set_var(ncvars, ncvarid, FALSE);
+                  cdf_set_dim(ncvars, ncvarid, 0, Z_AXIS);
+                  ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
+                }
+            }
+          else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) )
+            {
+	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval);
+	      ncvars[ncvarid].deffillval = true;
+	      /* cdf_set_var(ncvars, ncvarid, TRUE); */
+            }
+          else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
+            {
+	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
+	      ncvars[ncvarid].defmissval = true;
+	      /* cdf_set_var(ncvars, ncvarid, TRUE); */
+            }
+          else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 )
+            {
+              if ( ncvars[ncvarid].lvalidrange == false )
+                {
+                  extern int cdiIgnoreValidRange;
+                  bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
+                  if ( cdiIgnoreValidRange == FALSE && lignore == false )
+                    {
+                      cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
+                      ncvars[ncvarid].lvalidrange = true;
+                      if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 )
+                        ncvars[ncvarid].lunsigned = true;
+                      /* cdf_set_var(ncvars, ncvarid, TRUE); */
+                    }
+                  else if ( lignore )
+                    {
+                      Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name);
+                    }
+                }
+            }
+          else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 )
+            {
+              if ( ncvars[ncvarid].lvalidrange == false )
+                {
+                  extern int cdiIgnoreValidRange;
+                  bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
+                  if ( cdiIgnoreValidRange == FALSE && lignore == false )
+                    {
+                      cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
+                      ncvars[ncvarid].lvalidrange = true;
+                    }
+                  else if ( lignore )
+                    {
+                      Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name);
+                    }
+                }
+            }
+          else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 )
+            {
+              if ( ncvars[ncvarid].lvalidrange == false )
+                {
+                  extern int cdiIgnoreValidRange;
+                  bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype);
+                  if ( cdiIgnoreValidRange == FALSE && lignore == false )
+                    {
+                      cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
+                      ncvars[ncvarid].lvalidrange = true;
+                    }
+                  else if ( lignore )
+                    {
+                      Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name);
+                    }
+                }
+            }
+          else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+              str_tolower(attstring);
+
+              if ( memcmp(attstring, "true", 4) == 0 )
+                {
+                  ncvars[ncvarid].lunsigned = true;
+                  /*
+                  ncvars[ncvarid].lvalidrange = true;
+                  ncvars[ncvarid].validrange[0] = 0;
+                  ncvars[ncvarid].validrange[1] = 255;
+                  */
+                }
+	      /* cdf_set_var(ncvars, ncvarid, TRUE); */
+            }
+          else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
+            {
+	      cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+	      str_tolower(attstring);
+
+	      if ( memcmp(attstring, "ignore", 6) == 0 )
+		{
+		  ncvars[ncvarid].ignore = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		}
+            }
+          else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
+            {
+              cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+	      attlen = strlen(attstring);
+
+	      if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 )
+		{
+		    Warning("Unexpected axis attribute length for %s, ignored!", name);
+		}
+              else if ( nvdims == 0 && attlen == 1 )
+                {
+                  if ( attstring[0] == 'z' || attstring[0] == 'Z' )
+                    {
+                      cdf_set_var(ncvars, ncvarid, FALSE);
+                      ncvars[ncvarid].islev = true;
+                    }
+                }
+	      else
+		{
+		  str_tolower(attstring);
+                  cdf_scan_attr_axis(ncvars, ncdims, ncvarid, attstring, attlen, nvdims, dimidsp, name);
+		}
+	    }
+	  else if ( ( strcmp(attname, "realization") == 0 )         ||
+	            ( strcmp(attname, "ensemble_members") == 0 )    ||
+	            ( strcmp(attname, "forecast_init_type") == 0 )    )
+	    {
+	      int temp;
+
+	      if( ncvars[ncvarid].ensdata == NULL )
+		ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) );
+
+	      cdfGetAttInt(ncid, ncvarid, attname, 1, &temp);
+
+	      if( strcmp(attname, "realization") == 0 )
+		ncvars[ncvarid].ensdata->ens_index = temp;
+	      else if( strcmp(attname, "ensemble_members") == 0 )
+		ncvars[ncvarid].ensdata->ens_count = temp;
+	      else if( strcmp(attname, "forecast_init_type") == 0 )
+		ncvars[ncvarid].ensdata->forecast_init_type = temp;
+
+	      cdf_set_var(ncvars, ncvarid, TRUE);
+	    }
+	  else
+	    {
+	      if ( ncvars[ncvarid].natts == 0 )
+		ncvars[ncvarid].atts
+                  = (int *) Malloc((size_t)nvatts * sizeof (int));
+
+	      ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
+	      /*
+	      int attrint;
+	      double attrflt;
+	      nc_type atttype;
+	      cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+	      cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
+	      if ( attlen == 1 && (atttype == NC_INT || atttype == NC_SHORT) )
+		{
+		  cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint);
+		  printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint);
+		}
+	      else if ( attlen == 1 && (atttype == NC_FLOAT || atttype == NC_DOUBLE) )
+		{
+		  cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt);
+		  printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt);
+		}
+	      else if ( atttype == NC_CHAR )
+		{
+		  cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+		  attstring[attlen] = 0;
+		  printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring);
+		}
+	      else
+		printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
+	      */
+	    }
+	}
+    }
+
+  for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]);
+}
+
+static
+void cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
+{
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      if ( ncvars[ncvarid].isvar == TRUE )
+	{
+	  bool lxdim = false, lydim = false, lzdim = false/* , ltdim = false */;
+	  int ndims = ncvars[ncvarid].ndims;
+	  for ( int i = 0; i < ndims; i++ )
+	    {
+	      int ncdimid = ncvars[ncvarid].dimids[i];
+	      if      ( ncdims[ncdimid].dimtype == X_AXIS ) cdf_set_dim(ncvars, ncvarid, i, X_AXIS);
+	      else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Y_AXIS);
+	      else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Z_AXIS);
+	      else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdf_set_dim(ncvars, ncvarid, i, T_AXIS);
+	    }
+
+	  if ( CDI_Debug )
+	    {
+	      Message("var %d %s", ncvarid, ncvars[ncvarid].name);
+	      for ( int i = 0; i < ndims; i++ )
+		printf("  dim%d type=%d  ", i, ncvars[ncvarid].dimtype[i]);
+	      printf("\n");
+	    }
+
+	  for ( int i = 0; i < ndims; i++ )
+	    {
+	      if      ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = true;
+	      else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = true;
+	      else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = true;
+	      /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = true; */
+	    }
+
+          if ( !lxdim && ncvars[ncvarid].xvarid != UNDEFID )
+            {
+              if (  ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = true;
+            }
+
+          if ( !lydim && ncvars[ncvarid].yvarid != UNDEFID )
+            {
+              if (  ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = true;
+            }
+
+          //   if ( ndims > 1 )
+            for ( int i = ndims-1; i >= 0; i-- )
+              {
+                if ( ncvars[ncvarid].dimtype[i] == -1 )
+                  {
+                    if ( !lxdim )
+                      {
+                        cdf_set_dim(ncvars, ncvarid, i, X_AXIS);
+                        lxdim = true;
+                      }
+                    else if ( !lydim && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED )
+                      {
+                        cdf_set_dim(ncvars, ncvarid, i, Y_AXIS);
+                        lydim = true;
+                      }
+                    else if ( !lzdim )
+                      {
+                        cdf_set_dim(ncvars, ncvarid, i, Z_AXIS);
+                        lzdim = true;
+                      }
+                  }
+              }
+	}
+    }
+}
+
+/* verify coordinate vars - first scan (dimname == varname) */
+static
+void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid)
+{
+  for ( int ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      int ncvarid = ncdims[ncdimid].ncvarid;
+      if ( ncvarid != -1 )
+	{
+	  if ( ncvars[ncvarid].dimids[0] == timedimid )
+	    {
+              ncvars[ncvarid].istime = true;
+	      ncdims[ncdimid].dimtype = T_AXIS;
+	      continue;
+	    }
+
+          if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue;
+
+	  if ( ncvars[ncvarid].units[0] != 0 )
+	    {
+	      if ( is_lon_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].islon = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, X_AXIS);
+		  ncdims[ncdimid].dimtype = X_AXIS;
+		}
+	      else if ( is_lat_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].islat = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS);
+		  ncdims[ncdimid].dimtype = Y_AXIS;
+		}
+	      else if ( is_x_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].isx = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, X_AXIS);
+		  ncdims[ncdimid].dimtype = X_AXIS;
+		}
+	      else if ( is_y_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].isy = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS);
+		  ncdims[ncdimid].dimtype = Y_AXIS;
+		}
+	      else if ( is_pressure_units(ncvars[ncvarid].units) )
+		{
+		  ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
+		}
+	      else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
+		{
+		  if      ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+		  else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+		  else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
+		}
+	      else if ( is_DBL_axis(ncvars[ncvarid].longname) )
+                {
+                  ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
+		}
+	      else if ( is_height_units(ncvars[ncvarid].units) )
+		{
+		  if ( is_depth_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+		    ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
+		  else if ( is_height_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
+		}
+	    }
+          else
+            {
+              if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 ||
+                    strcmp(ncvars[ncvarid].longname, "generalized height") == 0) &&
+                   strcmp(ncvars[ncvarid].stdname, "height") == 0 )
+                  ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE;
+            }
+
+	  if ( !ncvars[ncvarid].islon && ncvars[ncvarid].longname[0] != 0 &&
+               !ncvars[ncvarid].islat && ncvars[ncvarid].longname[1] != 0 )
+	    {
+	      if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
+		{
+		  ncvars[ncvarid].islon = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, X_AXIS);
+		  ncdims[ncdimid].dimtype = X_AXIS;
+		  continue;
+		}
+	      else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
+		{
+		  ncvars[ncvarid].islat = true;
+		  cdf_set_var(ncvars, ncvarid, FALSE);
+		  cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS);
+		  ncdims[ncdimid].dimtype = Y_AXIS;
+		  continue;
+		}
+	    }
+
+	  if ( ncvars[ncvarid].zaxistype != UNDEFID )
+	    {
+              ncvars[ncvarid].islev = true;
+	      cdf_set_var(ncvars, ncvarid, FALSE);
+	      cdf_set_dim(ncvars, ncvarid, 0, Z_AXIS);
+	      ncdims[ncdimid].dimtype = Z_AXIS;
+	    }
+	}
+    }
+}
+
+/* verify coordinate vars - second scan (all other variables) */
+static
+void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
+{
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      if ( ncvars[ncvarid].isvar == 0 )
+	{
+	  if ( ncvars[ncvarid].units[0] != 0 )
+	    {
+	      if ( is_lon_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].islon = true;
+		  continue;
+		}
+	      else if ( is_lat_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].islat = true;
+		  continue;
+		}
+	      else if ( is_x_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].isx = true;
+		  continue;
+		}
+	      else if ( is_y_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+		{
+		  ncvars[ncvarid].isy = true;
+		  continue;
+		}
+	      else if ( is_pressure_units(ncvars[ncvarid].units) )
+		{
+		  ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
+		  continue;
+		}
+	      else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
+		{
+		  if      ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+		  else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+		  else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+		  else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
+		    ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
+		  continue;
+		}
+	      else if ( is_DBL_axis(ncvars[ncvarid].longname) )
+		{
+                  ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
+		  continue;
+		}
+	      else if ( is_height_units(ncvars[ncvarid].units) )
+		{
+		  if ( is_depth_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+		    ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
+		  else if ( is_height_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+		    ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
+		  continue;
+		}
+            }
+
+	  /* not needed anymore for rotated grids */
+	  if ( !ncvars[ncvarid].islon && ncvars[ncvarid].longname[0] != 0 &&
+               !ncvars[ncvarid].islat && ncvars[ncvarid].longname[1] != 0 )
+	    {
+	      if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
+		{
+		  ncvars[ncvarid].islon = true;
+		  continue;
+		}
+	      else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
+		{
+		  ncvars[ncvarid].islat = true;
+		  continue;
+		}
+	    }
+	}
+    }
+}
+
+static
+void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
+{
+  if ( ncvar->chunked )
+    {
+      int ndims = ncvar->ndims;
+
+      if ( grid->type == GRID_UNSTRUCTURED )
+        {
+          if ( ncvar->chunks[ndims-1] == grid->size )
+            ncvar->chunktype = CDI_CHUNK_GRID;
+          else
+            ncvar->chunktype = CDI_CHUNK_AUTO;
+        }
+      else
+        {
+          if ( grid->x.size > 1 && grid->y.size > 1 && ndims > 1 &&
+               grid->x.size == ncvar->chunks[ndims-1] &&
+               grid->y.size == ncvar->chunks[ndims-2] )
+            ncvar->chunktype = CDI_CHUNK_GRID;
+          else if ( grid->x.size > 1 && grid->x.size == ncvar->chunks[ndims-1] )
+            ncvar->chunktype = CDI_CHUNK_LINES;
+          else
+            ncvar->chunktype = CDI_CHUNK_AUTO;
+        }
+    }
+}
+
+/* define all input grids */
+static
+void cdf_load_vals(size_t size, int ndims, int varid, ncvar_t *ncvar, double **gridvals, struct xyValGet *valsGet,
+                   int ntdims, size_t *start, size_t *count)
+{
+  if ( CDI_netcdf_lazy_grid_load )
+    {
+      *valsGet = (struct xyValGet){
+        .scalefactor = ncvar->scalefactor,
+        .addoffset = ncvar->addoffset,
+        .start = { start[0], start[1], start[2] },
+        .count = { count[0], count[1], count[2] },
+        .size = size,
+        .datasetNCId = ncvar->ncid,
+        .varNCId = varid,
+        .ndims = (short)ndims,
+      };
+      *gridvals = cdfPendingLoad;
+    }
+  else
+    {
+      *gridvals = (double*) Malloc(size*sizeof(double));
+      if ( ntdims == 1 )
+        cdf_get_vara_double(ncvar->ncid, varid, start, count, *gridvals);
+      else
+        cdf_get_var_double(ncvar->ncid, varid, *gridvals);
+      cdf_scale_add(size, *gridvals, ncvar->addoffset, ncvar->scalefactor);
+    }
+}
+
+static
+void cdf_load_bounds(size_t size, ncvar_t *ncvar, double **gridbounds, struct cdfLazyGridIds *cellBoundsGet)
+{
+  if ( CDI_netcdf_lazy_grid_load )
+    {
+      cellBoundsGet->datasetNCId = ncvar->ncid;
+      cellBoundsGet->varNCId  = ncvar->bounds;
+      *gridbounds = cdfPendingLoad;
+    }
+  else
+    {
+      *gridbounds = (double*) Malloc(size*sizeof(double));
+      cdf_get_var_double(ncvar->ncid, ncvar->bounds, *gridbounds);
+    }
+}
+
+static
+void cdf_load_cellarea(size_t size, ncvar_t *ncvar, double **gridarea, struct cdfLazyGridIds *cellAreaGet)
+{
+  if ( CDI_netcdf_lazy_grid_load )
+    {
+      cellAreaGet->datasetNCId = ncvar->ncid;
+      cellAreaGet->varNCId = ncvar->cellarea;
+      *gridarea = cdfPendingLoad;
+    }
+  else
+    {
+      *gridarea = (double*) Malloc(size*sizeof(double));
+      cdf_get_var_double(ncvar->ncid, ncvar->cellarea, *gridarea);
+    }
+}
+
+static
+void cdf_copy_axis_attr(ncvar_t *ncvar, struct gridaxis_t *gridaxis)
+{
+  strcpy(gridaxis->name, ncvar->name);
+  strcpy(gridaxis->longname, ncvar->longname);
+  strcpy(gridaxis->units, ncvar->units);
+}
+
+static
+int cdf_get_xydimid(int ndims, int *dimids, int *dimtype, int *xdimid, int *ydimid)
+{
+  int nxdims = 0, nydims = 0;
+  int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
+
+  for ( int i = 0; i < ndims; i++ )
+    {
+      if ( dimtype[i] == X_AXIS && nxdims < 2 )
+        {
+          xdimids[nxdims] = dimids[i];
+          nxdims++;
+        }
+      else if ( dimtype[i] == Y_AXIS && nydims < 2 )
+        {
+          ydimids[nydims] = dimids[i];
+          nydims++;
+        }
+    }
+
+  if ( nxdims == 2 )
+    {
+      *xdimid = xdimids[1];
+      *ydimid = xdimids[0];
+    }
+  else if ( nydims == 2 )
+    {
+      *xdimid = ydimids[1];
+      *ydimid = ydimids[0];
+    }
+  else
+    {
+      *xdimid = xdimids[0];
+      *ydimid = ydimids[0];
+    }
+
+  return nydims;
+}
+
+static
+void cdf_check_gridtype(int *gridtype, bool islon, bool islat, size_t xsize, size_t ysize, grid_t *grid)
+{
+  if ( islat && (islon || xsize == 0) )
+    {
+      double yinc = 0;
+      if ( islon && (int) ysize > 1 )
+        {
+          yinc = fabs(grid->y.vals[0] - grid->y.vals[1]);
+          for ( size_t i = 2; i < ysize; i++ )
+            if ( (fabs(grid->y.vals[i-1] - grid->y.vals[i]) - yinc) > (yinc/1000) )
+              {
+                yinc = 0;
+                break;
+              }
+        }
+      if ( ysize < 10000 && isGaussGrid(ysize, yinc, grid->y.vals) )
+        {
+          *gridtype = GRID_GAUSSIAN;
+          grid->np = (int)(ysize/2);
+        }
+      else
+        *gridtype = GRID_LONLAT;
+    }
+  else if ( islon && !islat && ysize == 0 )
+    {
+      *gridtype = GRID_LONLAT;
+    }
+  else
+    *gridtype = GRID_GENERIC;
+}
+
+static
+bool cdf_read_xcoord(struct cdfLazyGrid *restrict lazyGrid, ncdim_t *ncdims, ncvar_t *ncvar, int xvarid, ncvar_t *axisvar,
+                     size_t *xsize, size_t ysize, int ntdims, size_t *start, size_t *count, bool *islon)
+{
+  grid_t *grid = &lazyGrid->base;
+  bool skipvar = true;
+  *islon = axisvar->islon;
+  int ndims = axisvar->ndims;
+  size_t size = 0;
+  if ( (ndims - ntdims) == 2 )
+    {
+      ncvar->gridtype = GRID_CURVILINEAR;
+      size = (*xsize)*ysize;
+      /* Check size of 2 dimensional coordinate variables */
+      int dimid = axisvar->dimids[ndims-2];
+      size_t dimsize1 = ncdims[dimid].len;
+      dimid = axisvar->dimids[ndims-1];
+      size_t dimsize2 = ncdims[dimid].len;
+      skipvar = dimsize1*dimsize2 != size;
+    }
+  else if ( (ndims - ntdims) == 1 )
+    {
+      size = *xsize;
+      /* Check size of 1 dimensional coordinate variables */
+      int dimid = axisvar->dimids[ndims-1];
+      size_t dimsize = ncdims[dimid].len;
+      skipvar = dimsize != size;
+    }
+  else if ( ndims == 0 && *xsize == 0 )
+    {
+      size = *xsize = 1;
+      skipvar = false;
+    }
+
+  if ( skipvar )
+    {
+      Warning("Unsupported array structure, skipped variable %s!", ncvar->name);
+      ncvar->isvar = -1;
+      return true;
+    }
+
+  if ( axisvar->xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+
+  cdf_load_vals(size, ndims, xvarid, axisvar, &grid->x.vals, &lazyGrid->xValsGet, ntdims, start, count);
+
+  cdf_copy_axis_attr(axisvar, &grid->x);
+
+  return false;
+}
+
+static
+bool cdf_read_ycoord(struct cdfLazyGrid *restrict lazyGrid, ncdim_t *ncdims, ncvar_t *ncvar, int yvarid, ncvar_t *axisvar,
+                     size_t xsize, size_t *ysize, int ntdims, size_t *start, size_t *count, bool *islat)
+{
+  grid_t *grid = &lazyGrid->base;
+  bool skipvar = true;
+  *islat = axisvar->islat;
+  int ndims = axisvar->ndims;
+  size_t size = 0;
+  if ( (ndims - ntdims) == 2 )
+    {
+      ncvar->gridtype = GRID_CURVILINEAR;
+      size = xsize*(*ysize);
+      /* Check size of 2 dimensional coordinate variables */
+      int dimid = axisvar->dimids[ndims-2];
+      size_t dimsize1 = ncdims[dimid].len;
+      dimid = axisvar->dimids[ndims-1];
+      size_t dimsize2 = ncdims[dimid].len;
+      skipvar = dimsize1*dimsize2 != size;
+    }
+  else if ( (ndims - ntdims) == 1 )
+    {
+      if ( (int) *ysize == 0 ) size = xsize;
+      else                    size = *ysize;
+
+      int dimid = axisvar->dimids[ndims-1];
+      size_t dimsize = ncdims[dimid].len;
+      skipvar = dimsize != size;
+    }
+  else if ( ndims == 0 && *ysize == 0 )
+    {
+      size = *ysize = 1;
+      skipvar = false;
+    }
+
+  if ( skipvar )
+    {
+      Warning("Unsupported array structure, skipped variable %s!", ncvar->name);
+      ncvar->isvar = -1;
+      return true;
+    }
+
+  if ( axisvar->xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+
+  cdf_load_vals(size, ndims, yvarid, axisvar, &grid->y.vals, &lazyGrid->yValsGet,
+                ntdims, start, count);
+
+  cdf_copy_axis_attr(axisvar, &grid->y);
+
+  return false;
+}
+
+static
+bool cdf_read_coordinates(struct cdfLazyGrid *restrict lazyGrid, ncvar_t *ncvar, ncvar_t *ncvars, ncdim_t *ncdims,
+                          int timedimid, int xvarid, int yvarid, size_t xsize, size_t ysize, int *vdimid)
+{
+  grid_t *grid = &lazyGrid->base;
+  size_t size = 0;
+
+  grid->prec = DATATYPE_FLT64;
+
+  if ( ncvar->gridtype == GRID_TRAJECTORY )
+    {
+      if ( ncvar->xvarid == UNDEFID ) Error("Longitude coordinate undefined for %s!", ncvar->name);
+      if ( ncvar->yvarid == UNDEFID ) Error("Latitude coordinate undefined for %s!", ncvar->name);
+    }
+  else
+    {
+      static bool ltwarn = true;
+      size_t start[3], count[3];
+      int ntdims = 0;
+
+      if ( xvarid != UNDEFID && yvarid != UNDEFID )
+        {
+          int ndims = ncvars[xvarid].ndims;
+          if ( ndims != ncvars[yvarid].ndims )
+            {
+              Warning("Inconsistent grid structure for variable %s!", ncvar->name);
+              ncvar->xvarid = xvarid = UNDEFID;
+              ncvar->yvarid = yvarid = UNDEFID;
+            }
+          if ( ndims > 1 )
+            {
+              if ( ndims <= 3 )
+                {
+                  if ( ncvars[xvarid].dimids[0] == timedimid && ncvars[yvarid].dimids[0] == timedimid )
+                    {
+                      size_t ntsteps = 0;
+                      cdf_inq_dimlen(ncvar->ncid, timedimid, &ntsteps);
+                      if ( ltwarn && ntsteps > 1 ) Warning("Time varying grids unsupported, using grid at time step 1!");
+                      ltwarn = false;
+                      ntdims = 1;
+                      start[0] = start[1] = start[2] = 0;
+                      count[0] = 1; count[1] = ysize; count[ndims-1] = xsize;
+                    }
+                }
+              else
+                {
+                  Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvar->name);
+                  ncvar->xvarid = xvarid = UNDEFID;
+                  ncvar->yvarid = yvarid = UNDEFID;
+                }
+            }
+        }
+
+      if ( xvarid != UNDEFID )
+        {
+          if ( (ncvars[xvarid].ndims - ntdims) > 2 )
+            {
+              Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims);
+              //ncvar->xvarid = UNDEFID;
+              xvarid = UNDEFID;
+            }
+        }
+
+      if ( yvarid != UNDEFID )
+        {
+          if ( (ncvars[yvarid].ndims - ntdims) > 2 )
+            {
+              Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims);
+              //ncvar->yvarid = UNDEFID;
+              yvarid = UNDEFID;
+            }
+        }
+
+      bool islon = false, islat = false;
+
+      if ( xvarid != UNDEFID )
+        if ( cdf_read_xcoord(lazyGrid, ncdims, ncvar, xvarid, &ncvars[xvarid],
+                             &xsize, ysize, ntdims, start, count, &islon) )
+          return true;
+
+      if ( yvarid != UNDEFID )
+        if ( cdf_read_ycoord(lazyGrid, ncdims, ncvar, yvarid, &ncvars[yvarid],
+                             xsize, &ysize, ntdims, start, count, &islat) )
+          return true;
+
+      if      ( (int) ysize == 0 ) size = xsize;
+      else if ( (int) xsize == 0 ) size = ysize;
+      else if ( ncvar->gridtype == GRID_UNSTRUCTURED ) size = xsize;
+      else                         size = xsize*ysize;
+
+      if ( ncvar->gridtype == UNDEFID || ncvar->gridtype == GRID_GENERIC )
+        cdf_check_gridtype(&ncvar->gridtype, islon, islat, xsize, ysize, grid);
+    }
+
+  int gridtype = grid->type;
+  if ( gridtype != GRID_PROJECTION ) gridtype = ncvar->gridtype;
+  else if ( gridtype == GRID_PROJECTION && ncvar->gridtype == GRID_LONLAT )
+    {
+      int gmapvarid = ncvar->gmapid;
+      if ( gmapvarid != UNDEFID && cdfCheckAttText(ncvar->ncid, gmapvarid, "grid_mapping_name") )
+        {
+          char attstring[CDI_MAX_NAME];
+          cdfGetAttText(ncvar->ncid, gmapvarid, "grid_mapping_name", CDI_MAX_NAME, attstring);
+          if ( strcmp(attstring, "latitude_longitude") == 0 ) gridtype = ncvar->gridtype;
+        }
+    }
+
+  switch (gridtype)
+    {
+    case GRID_GENERIC:
+    case GRID_LONLAT:
+    case GRID_GAUSSIAN:
+    case GRID_UNSTRUCTURED:
+    case GRID_CURVILINEAR:
+    case GRID_PROJECTION:
+      {
+        grid->size  = (int)size;
+        grid->x.size = (int)xsize;
+        grid->y.size = (int)ysize;
+        if ( xvarid != UNDEFID )
+          {
+            grid->x.flag = 1;
+            int bvarid = ncvars[xvarid].bounds;
+            if ( bvarid != UNDEFID )
+              {
+                int nbdims = ncvars[bvarid].ndims;
+                if ( nbdims == 2 || nbdims == 3 )
+                  {
+                    *vdimid = ncvars[bvarid].dimids[nbdims-1];
+                    grid->nvertex = (int)ncdims[*vdimid].len;
+                    cdf_load_bounds(grid->size*grid->nvertex, &ncvars[xvarid], &grid->x.bounds, &lazyGrid->xBoundsGet);
+                  }
+              }
+          }
+        if ( yvarid != UNDEFID )
+          {
+            grid->y.flag = 1;
+            int bvarid = ncvars[yvarid].bounds;
+            if ( bvarid != UNDEFID )
+              {
+                int nbdims = ncvars[bvarid].ndims;
+                if ( nbdims == 2 || nbdims == 3 )
+                  {
+                    if ( *vdimid == UNDEFID )
+                      {
+                        *vdimid = ncvars[bvarid].dimids[nbdims-1];
+                        grid->nvertex = (int)ncdims[*vdimid].len;
+                      }
+                    cdf_load_bounds(grid->size*grid->nvertex, &ncvars[yvarid], &grid->y.bounds, &lazyGrid->yBoundsGet);
+                  }
+              }
+          }
+
+        if ( ncvar->cellarea != UNDEFID )
+          cdf_load_cellarea(size, ncvar, &grid->area, &lazyGrid->cellAreaGet);
+
+        break;
+      }
+    case GRID_SPECTRAL:
+      {
+        grid->size = (int)size;
+        grid->lcomplex = 1;
+        grid->trunc = ncvar->truncation;
+        break;
+      }
+    case GRID_FOURIER:
+      {
+        grid->size = (int)size;
+        grid->trunc = ncvar->truncation;
+        break;
+      }
+    case GRID_TRAJECTORY:
+      {
+        grid->size = 1;
+        break;
+      }
+    }
+
+  // if ( grid->type != GRID_PROJECTION && grid->type != ncvar->gridtype )
+  if ( grid->type != gridtype )
+    {
+      // int gridtype = ncvar->gridtype;
+      grid->type = gridtype;
+      cdiGridTypeInit(grid, gridtype, grid->size);
+    }
+
+  if ( grid->size == 0 )
+    {
+      int ndims = ncvar->ndims;
+      int *dimtype = ncvar->dimtype;
+      if ( (ndims == 1 && dimtype[0] == T_AXIS) ||
+           (ndims == 1 && dimtype[0] == Z_AXIS) ||
+           (ndims == 2 && dimtype[0] == T_AXIS && dimtype[1] == Z_AXIS) )
+        {
+          grid->type  = GRID_GENERIC;
+          grid->size  = 1;
+          grid->x.size = 0;
+          grid->y.size = 0;
+        }
+      else
+        {
+          Warning("Variable %s has an unsupported grid, skipped!", ncvar->name);
+          ncvar->isvar = -1;
+          return true;
+        }
+    }
+
+  return false;
+}
+
+static
+bool cdf_set_unstructured_par(ncvar_t *ncvar, grid_t *grid, int xdimid, int ydimid, int number_of_grid_used, unsigned char *uuidOfHGrid)
+{
+  int ndims = ncvar->ndims;
+  int *dimtype = ncvar->dimtype;
+
+  int zdimid = UNDEFID;
+  int xdimidx = UNDEFID, ydimidx = UNDEFID;
+
+  for ( int i = 0; i < ndims; i++ )
+    {
+      if      ( dimtype[i] == X_AXIS ) xdimidx = i;
+      else if ( dimtype[i] == Y_AXIS ) ydimidx = i;
+      else if ( dimtype[i] == Z_AXIS ) zdimid = ncvar->dimids[i];
+    }
+
+  if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID )
+    {
+      if ( grid->x.size > grid->y.size && grid->y.size < 1000 )
+        {
+          dimtype[ydimidx] = Z_AXIS;
+          ydimid = UNDEFID;
+          grid->size  = grid->x.size;
+          grid->y.size = 0;
+        }
+      else if ( grid->y.size > grid->x.size && grid->x.size < 1000 )
+        {
+          dimtype[xdimidx] = Z_AXIS;
+          xdimid = ydimid;
+          ydimid = UNDEFID;
+          grid->size  = grid->y.size;
+          grid->x.size = grid->y.size;
+          grid->y.size = 0;
+        }
+    }
+
+  if ( grid->size != grid->x.size )
+    {
+      Warning("Unsupported array structure, skipped variable %s!", ncvar->name);
+      ncvar->isvar = -1;
+      return true;
+    }
+
+  if ( number_of_grid_used != UNDEFID ) grid->number = number_of_grid_used;
+  if ( ncvar->position > 0 ) grid->position = ncvar->position;
+  if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16);
+
+  return false;
+}
+
+static
+void cdf_read_mapping_atts(int ncid, int gmapvarid, int projID, const char *varname)
+{
+  if ( cdfCheckAttText(ncid, gmapvarid, "grid_mapping_name") )
+    {
+      char attstring[CDI_MAX_NAME];
+      cdfGetAttText(ncid, gmapvarid, "grid_mapping_name", CDI_MAX_NAME, attstring);
+      cdiGridDefKeyStr(projID, CDI_KEY_MAPPING, (int)(strlen(attstring)+1), attstring);
+    }
+  else
+    {
+      Warning("Text attribute %s:grid_mapping_name missing!", varname);
+    }
+
+  int nvatts;
+  cdf_inq_varnatts(ncid, gmapvarid, &nvatts);
+  for ( int attnum = 0; attnum < nvatts; ++attnum )
+    cdf_set_cdi_attr(ncid, gmapvarid, attnum, projID, CDI_GLOBAL);
+}
+
+static
+void cdf_set_proj_atts(int ncid, int gmapvarid, grid_t *grid)
+{
+  int nvatts;
+  cdf_inq_varnatts(ncid, gmapvarid, &nvatts);
+
+  for ( int iatt = 0; iatt < nvatts; iatt++ )
+    {
+      nc_type atttype;
+      size_t attlen;
+      char attname[CDI_MAX_NAME];
+      cdf_inq_attname(ncid, gmapvarid, iatt, attname);
+      cdf_inq_attlen(ncid, gmapvarid, attname, &attlen);
+      cdf_inq_atttype(ncid, gmapvarid, attname, &atttype);
+
+      if ( strcmp(attname, "grid_mapping_name") == 0 )
+        {
+          enum {attstringlen = 8192};
+          char attstring[attstringlen];
+          cdfGetAttText(ncid, gmapvarid, attname, attstringlen, attstring);
+          str_tolower(attstring);
+
+          if ( strcmp(attstring, "rotated_latitude_longitude") == 0 )
+            grid->isRotated = TRUE;
+          else if ( strcmp(attstring, "sinusoidal") == 0 )
+            grid->type = GRID_SINUSOIDAL;
+          else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 )
+            grid->type = GRID_LAEA;
+          else if ( strcmp(attstring, "lambert_conformal_conic") == 0 )
+            grid->type = GRID_LCC2;
+        }
+      else if ( strcmp(attname, "earth_radius") == 0 )
+        {
+          double datt;
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt);
+          grid->laea.a = datt;
+          grid->lcc2.a = datt;
+        }
+      else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )
+        {
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->laea.lon_0);
+        }
+      else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )
+        {
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->lcc2.lon_0);
+        }
+      else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )
+        {
+          double datt;
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt);
+          grid->laea.lat_0 = datt;
+          grid->lcc2.lat_0 = datt;
+        }
+      else if ( strcmp(attname, "standard_parallel") == 0 )
+        {
+          if ( attlen == 1 )
+            {
+              double datt;
+              cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt);
+              grid->lcc2.lat_1 = datt;
+              grid->lcc2.lat_2 = datt;
+            }
+          else
+            {
+              double datt2[2];
+              cdfGetAttDouble(ncid, gmapvarid, attname, 2, datt2);
+              grid->lcc2.lat_1 = datt2[0];
+              grid->lcc2.lat_2 = datt2[1];
+            }
+        }
+      else if ( strcmp(attname, "grid_north_pole_latitude") == 0 )
+        {
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.ypole);
+        }
+      else if ( strcmp(attname, "grid_north_pole_longitude") == 0 )
+        {
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.xpole);
+        }
+      else if ( strcmp(attname, "north_pole_grid_longitude") == 0 )
+        {
+          cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.angle);
+        }
+    }
+}
+
+static
+void cdf_set_grid_to_similar_vars(ncvar_t *ncvar1, ncvar_t *ncvar2, int gridtype, int xdimid, int ydimid)
+{
+  if ( ncvar2->isvar == TRUE && ncvar2->gridID == UNDEFID )
+    {
+      int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID;
+      int xdimidx = UNDEFID, ydimidx = UNDEFID;
+      int ndims2 = ncvar2->ndims;
+
+      for ( int i = 0; i < ndims2; i++ )
+        {
+          int *dimtype2 = ncvar2->dimtype;
+          int *dimids2 = ncvar2->dimids;
+          if      ( dimtype2[i] == X_AXIS ) { xdimid2 = dimids2[i]; xdimidx = i; }
+          else if ( dimtype2[i] == Y_AXIS ) { ydimid2 = dimids2[i]; ydimidx = i; }
+          else if ( dimtype2[i] == Z_AXIS ) { zdimid2 = dimids2[i]; }
+        }
+
+      if ( ncvar2->gridtype == UNDEFID && gridtype == GRID_UNSTRUCTURED )
+        {
+          if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID )
+            {
+              ncvar2->dimtype[ydimidx] = Z_AXIS;
+              ydimid2 = UNDEFID;
+            }
+
+          if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID )
+            {
+              ncvar2->dimtype[xdimidx] = Z_AXIS;
+              xdimid2 = ydimid2;
+              ydimid2 = UNDEFID;
+            }
+        }
+
+      if ( xdimid == xdimid2 &&
+           (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) )
+        {
+          bool same_grid = ncvar1->xvarid == ncvar2->xvarid
+            && ncvar1->yvarid == ncvar2->yvarid
+            && ncvar1->position == ncvar2->position;
+          /*
+            if ( xvarid != -1 && ncvar2->xvarid != UNDEFID &&
+            xvarid != ncvar2->xvarid ) same_grid = false;
+
+            if ( yvarid != -1 && ncvar2->yvarid != UNDEFID &&
+            yvarid != ncvar2->yvarid ) same_grid = false;
+          */
+
+          if ( same_grid )
+            {
+              if ( CDI_Debug ) Message("Same gridID %d %s", ncvar1->gridID, ncvar2->name);
+              ncvar2->gridID = ncvar1->gridID;
+              ncvar2->chunktype = ncvar1->chunktype;
+            }
+        }
+    }
+}
+
+static
+void cdf_define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars,
+                          int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used)
+{
+#ifdef TEST_PROJECTION
+  bool testproj = true;
+#else
+  bool testproj = false;
+#endif
+
+  for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid )
+    {
+      ncvar_t *ncvar = &ncvars[ncvarid];
+      if ( ncvar->isvar && ncvar->gridID == UNDEFID )
+	{
+          int gmapvarid = ncvar->gmapid;
+          bool lproj = gmapvarid != UNDEFID;
+          bool lgrid = !(lproj && ncvar->xvarid == UNDEFID);
+          int ndims = ncvar->ndims;
+          int *dimtype = ncvar->dimtype;
+          int vdimid = UNDEFID;
+          struct addIfNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 },
+                             gridAdded = { .Id = CDI_UNDEFID, .isNew = 0 };
+
+	  int xdimid = UNDEFID, ydimid = UNDEFID;
+          int nydims = cdf_get_xydimid(ndims, ncvar->dimids, dimtype, &xdimid, &ydimid);
+
+          int xaxisid = (xdimid != UNDEFID) ? ncdims[xdimid].ncvarid : UNDEFID;
+          int yaxisid = (ydimid != UNDEFID) ? ncdims[ydimid].ncvarid : UNDEFID;
+          int xvarid = (ncvar->xvarid != UNDEFID) ? ncvar->xvarid : xaxisid;
+          int yvarid = (ncvar->yvarid != UNDEFID) ? ncvar->yvarid : yaxisid;
+
+	  size_t xsize = (xdimid != UNDEFID) ? ncdims[xdimid].len : 0;
+	  size_t ysize = (ydimid != UNDEFID) ? ncdims[ydimid].len : 0;
+
+	  if ( ydimid == UNDEFID && yvarid != UNDEFID )
+	    {
+	      if ( ncvars[yvarid].ndims == 1 )
+		{
+		  ydimid = ncvars[yvarid].dimids[0];
+		  ysize  = ncdims[ydimid].len;
+		}
+	    }
+
+          bool lunstructured = xdimid != UNDEFID && xdimid == ydimid && nydims == 0;
+	  if ( (ncvar->gridtype == UNDEFID || ncvar->gridtype == GRID_GENERIC) && lunstructured )
+            ncvar->gridtype = GRID_UNSTRUCTURED;
+
+          struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL;
+
+          {
+#ifdef TEST_PROJECTION
+            int gridtype = !lgrid ? GRID_PROJECTION : ncvar->gridtype;
+#else
+            int gridtype = ncvar->gridtype;
+#endif
+            if ( CDI_netcdf_lazy_grid_load )
+              {
+                cdfLazyGridRenew(&lazyGrid, gridtype);
+                if ( lgrid && lproj ) cdfLazyGridRenew(&lazyProj, GRID_PROJECTION);
+              }
+            else
+              {
+                cdfBaseGridRenew(&lazyGrid, gridtype);
+                if ( lgrid && lproj ) cdfBaseGridRenew(&lazyProj, GRID_PROJECTION);
+              }
+          }
+          grid_t *grid = &lazyGrid->base;
+          grid_t *proj = ( lgrid && lproj ) ? &lazyProj->base : NULL;
+
+          xaxisid = (xdimid != UNDEFID) ? ncdims[xdimid].ncvarid : UNDEFID;
+          yaxisid = (ydimid != UNDEFID) ? ncdims[ydimid].ncvarid : UNDEFID;
+
+
+          if ( cdf_read_coordinates(lazyGrid, ncvar, ncvars, ncdims,
+                                    timedimid, xvarid, yvarid, xsize, ysize, &vdimid) )
+            continue;
+
+	  if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) )
+            grid->type = GRID_UNSTRUCTURED;
+
+          if ( grid->type == GRID_UNSTRUCTURED )
+            if ( cdf_set_unstructured_par(ncvar, grid, xdimid, ydimid, number_of_grid_used, uuidOfHGrid) )
+              continue;
+
+          if ( lproj )
+            {
+              int ncid = ncvars[gmapvarid].ncid;
+              if ( !testproj && ncvar->gridtype != GRID_CURVILINEAR )
+                {
+                  cdf_set_proj_atts(ncid, gmapvarid, grid);
+                }
+              else if ( testproj )
+                {
+                  if ( lgrid )
+                    {
+                      int dumid;
+                      cdf_read_coordinates(lazyProj, ncvar, ncvars, ncdims, timedimid,
+                                           xaxisid, yaxisid, xsize, ysize, &dumid);
+                    }
+                }
+	    }
+
+	  if ( CDI_Debug )
+	    {
+	      Message("grid: type = %d, size = %d, nx = %d, ny %d",
+		      grid->type, grid->size, grid->x.size, grid->y.size);
+              if ( proj )
+                Message("proj: type = %d, size = %d, nx = %d, ny %d",
+                        proj->type, proj->size, proj->x.size, proj->y.size);
+	    }
+
+
+          if ( lgrid && lproj && testproj )
+            {
+              projAdded = cdiVlistAddGridIfNew(vlistID, proj, 2);
+              grid->proj = projAdded.Id;
+            }
+
+          gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1);
+          ncvar->gridID = gridAdded.Id;
+
+          int gridID = ncvar->gridID;
+
+          if ( lproj && testproj )
+            {
+              int projID = lgrid ? grid->proj : gridID;
+              int ncid = ncvars[gmapvarid].ncid;
+              const char *gmapname = ncvars[gmapvarid].name;
+              cdf_read_mapping_atts(ncid, gmapvarid, projID, gmapname);
+              cdiGridDefKeyStr(projID, CDI_KEY_MAPNAME, (int)(strlen(gmapname)+1), gmapname);
+              gridVerifyProj(projID);
+            }
+
+          if ( grid->type == GRID_UNSTRUCTURED && gridfile[0] != 0 )
+            gridDefReference(gridID, gridfile);
+
+          if ( ncvar->chunked ) grid_set_chunktype(grid, ncvar);
+
+	  int gridindex = vlistGridIndex(vlistID, gridID);
+	  streamptr->xdimID[gridindex] = xdimid;
+	  streamptr->ydimID[gridindex] = ydimid;
+          if ( xdimid == UNDEFID && ydimid == UNDEFID && grid->size == 1 )
+            gridDefHasDims(gridID, FALSE);
+
+          if ( xdimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name);
+          if ( ydimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name);
+          if ( vdimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name);
+
+	  if ( CDI_Debug ) Message("gridID %d %d %s", gridID, ncvarid, ncvar->name);
+
+	  for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
+            cdf_set_grid_to_similar_vars(ncvar, &ncvars[ncvarid2], grid->type, xdimid, ydimid);
+
+          if ( gridAdded.isNew ) lazyGrid = NULL;
+          if ( projAdded.isNew ) lazyProj = NULL;
+
+          if ( lazyGrid )
+            {
+              if ( CDI_netcdf_lazy_grid_load ) cdfLazyGridDestroy(lazyGrid);
+              if ( grid ) { grid_free(grid); Free(grid); }
+            }
+
+          if ( lazyProj )
+            {
+              if ( CDI_netcdf_lazy_grid_load ) cdfLazyGridDestroy(lazyProj);
+              if ( proj ) { grid_free(proj); Free(proj); }
+            }
+	}
+    }
+}
+
+/* define all input zaxes */
+static
+void cdf_define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars,
+                          size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid)
+{
+  int ncvarid2;
+  int i, ilev;
+  int zaxisindex;
+  int nbdims, nvertex, nlevel;
+  int psvarid = -1;
+  char *pname, *plongname, *punits;
+  size_t vctsize = vctsize_echam;
+  double *vct = vct_echam;
+
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      ncvar_t *ncvar = &ncvars[ncvarid];
+      if ( ncvar->isvar == TRUE && ncvar->zaxisID == UNDEFID )
+	{
+          bool is_scalar = false;
+	  bool with_bounds = false;
+	  int zdimid = UNDEFID;
+	  int zvarid = UNDEFID;
+	  int zsize = 1;
+	  double *lbounds = NULL;
+	  double *ubounds = NULL;
+
+          int positive = 0;
+	  int ndims = ncvar->ndims;
+
+          if ( ncvar->zvarid != -1 && ncvars[ncvar->zvarid].ndims == 0 )
+            {
+              zvarid = ncvar->zvarid;
+              is_scalar = true;
+            }
+          else
+            {
+              for ( i = 0; i < ndims; i++ )
+                {
+                  if ( ncvar->dimtype[i] == Z_AXIS )
+                    zdimid = ncvar->dimids[i];
+                }
+
+              if ( zdimid != UNDEFID )
+                {
+                  zvarid = ncdims[zdimid].ncvarid;
+                  zsize  = (int)ncdims[zdimid].len;
+                }
+            }
+
+	  if ( CDI_Debug ) Message("nlevs = %d", zsize);
+
+	  double *zvar = (double *) Malloc((size_t)zsize * sizeof (double));
+
+	  int zaxisType = UNDEFID;
+	  if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype;
+	  if ( zaxisType == UNDEFID )  zaxisType = ZAXIS_GENERIC;
+
+	  int zprec = DATATYPE_FLT64;
+
+	  if ( zvarid != UNDEFID )
+	    {
+	      positive  = ncvars[zvarid].positive;
+	      pname     = ncvars[zvarid].name;
+	      plongname = ncvars[zvarid].longname;
+	      punits    = ncvars[zvarid].units;
+	      if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32;
+	      /* don't change the name !!! */
+	      /*
+	      if ( (len = strlen(pname)) > 2 )
+		if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) )
+		  pname[len-2] = 0;
+	      */
+              psvarid = -1;
+              if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct )
+                {
+                  vct = ncvars[zvarid].vct;
+                  vctsize = ncvars[zvarid].vctsize;
+
+                  if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid;
+                }
+
+	      cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar);
+
+	      if ( ncvars[zvarid].bounds != UNDEFID )
+		{
+		  nbdims = ncvars[ncvars[zvarid].bounds].ndims;
+		  if ( nbdims == 2 )
+		    {
+		      nlevel  = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
+		      nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
+		      if ( nlevel == zsize && nvertex == 2 )
+			{
+			  with_bounds = true;
+			  lbounds = (double *) Malloc((size_t)nlevel*sizeof(double));
+			  ubounds = (double *) Malloc((size_t)nlevel*sizeof(double));
+			  double zbounds[2*nlevel];
+			  cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
+			  for ( i = 0; i < nlevel; ++i )
+			    {
+			      lbounds[i] = zbounds[i*2];
+			      ubounds[i] = zbounds[i*2+1];
+			    }
+			}
+		    }
+		}
+	    }
+	  else
+	    {
+	      pname     = NULL;
+	      plongname = NULL;
+	      punits    = NULL;
+
+	      if ( zsize == 1 )
+		{
+                  if ( ncvar->zaxistype != UNDEFID )
+                    zaxisType = ncvar->zaxistype;
+                  else
+                    zaxisType = ZAXIS_SURFACE;
+
+		  zvar[0] = 0;
+		  /*
+		  if ( zdimid == UNDEFID )
+		    zvar[0] = 9999;
+		  else
+		    zvar[0] = 0;
+		  */
+		}
+	      else
+		{
+		  for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
+		}
+	    }
+
+      	  ncvar->zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, (int)with_bounds, lbounds, ubounds,
+                                       (int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+
+	  if ( uuidOfVGrid[0] != 0 )
+            {
+              // printf("uuidOfVGrid: defined\n");
+              zaxisDefUUID(ncvar->zaxisID, uuidOfVGrid);
+            }
+
+          if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvar->zaxisID, ncvars[psvarid].name);
+
+          if ( positive > 0 ) zaxisDefPositive(ncvar->zaxisID, positive);
+          if ( is_scalar ) zaxisDefScalar(ncvar->zaxisID);
+
+          if ( zdimid != -1 )
+            cdiZaxisDefString(ncvar->zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name);
+          /*
+          if ( vdimid != -1 )
+            cdiZaxisDefString(ncvar->zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name);
+          */
+	  Free(zvar);
+	  Free(lbounds);
+	  Free(ubounds);
+
+	  zaxisindex = vlistZaxisIndex(vlistID, ncvar->zaxisID);
+	  streamptr->zaxisID[zaxisindex]  = zdimid;
+
+	  if ( CDI_Debug )
+	    Message("zaxisID %d %d %s", ncvar->zaxisID, ncvarid, ncvar->name);
+
+	  for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
+	    if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ )
+	      {
+                int zvarid2 = UNDEFID;
+                if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 )
+                  zvarid2 = ncvars[ncvarid2].zvarid;
+
+		int zdimid2 = UNDEFID;
+		ndims = ncvars[ncvarid2].ndims;
+		for ( i = 0; i < ndims; i++ )
+		  {
+		    if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
+		      zdimid2 = ncvars[ncvarid2].dimids[i];
+		  }
+
+		if ( zdimid == zdimid2 /* && zvarid == zvarid2 */)
+		  {
+                    if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ||
+                         (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) ||
+                         (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) ||
+                         (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) )
+                      {
+                        if ( CDI_Debug )
+                          Message("zaxisID %d %d %s", ncvar->zaxisID, ncvarid2, ncvars[ncvarid2].name);
+                        ncvars[ncvarid2].zaxisID = ncvar->zaxisID;
+                      }
+                  }
+	      }
+	}
+    }
+}
+
+struct varinfo
+{
+  int      ncvarid;
+  const char *name;
+};
+
+static
+int cmpvarname(const void *s1, const void *s2)
+{
+  const struct varinfo *x = (const struct varinfo *)s1,
+                       *y = (const struct varinfo *)s2;
+  return strcmp(x->name, y->name);
+}
+
+/* define all input data variables */
+static
+void cdf_define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars)
+{
+  if ( CDI_Debug )
+    for ( int i = 0; i < nvars; i++ ) Message("varids[%d] = %d", i, varids[i]);
+
+  if ( streamptr->sortname )
+    {
+      struct varinfo *varInfo
+        = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo));
+
+      for ( int varID = 0; varID < nvars; varID++ )
+	{
+	  int ncvarid = varids[varID];
+	  varInfo[varID].ncvarid = ncvarid;
+	  varInfo[varID].name = ncvars[ncvarid].name;
+	}
+      qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname);
+      for ( int varID = 0; varID < nvars; varID++ )
+	{
+	  varids[varID] = varInfo[varID].ncvarid;
+	}
+      Free(varInfo);
+      if ( CDI_Debug )
+        for ( int i = 0; i < nvars; i++ ) Message("sorted varids[%d] = %d", i, varids[i]);
+    }
+
+  for ( int varID1 = 0; varID1 < nvars; varID1++ )
+    {
+      int ncvarid = varids[varID1];
+      int gridID  = ncvars[ncvarid].gridID;
+      int zaxisID = ncvars[ncvarid].zaxisID;
+
+      stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID);
+      int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype);
+
+#if  defined  (HAVE_NETCDF4)
+      if ( ncvars[ncvarid].deflate )
+	vlistDefVarCompType(vlistID, varID, CDI_COMPRESS_ZIP);
+
+      if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID )
+        vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype);
+#endif
+
+      streamptr->vars[varID1].defmiss = 0;
+      streamptr->vars[varID1].ncvarid = ncvarid;
+
+      vlistDefVarName(vlistID, varID, ncvars[ncvarid].name);
+      if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param);
+      if ( ncvars[ncvarid].code != UNDEFID )  vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code);
+      if ( ncvars[ncvarid].code != UNDEFID )
+	{
+	  int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255);
+	  vlistDefVarParam(vlistID, varID, param);
+	}
+      if ( ncvars[ncvarid].longname[0] )  vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname);
+      if ( ncvars[ncvarid].stdname[0] )   vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname);
+      if ( ncvars[ncvarid].units[0] )     vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units);
+
+      if ( ncvars[ncvarid].lvalidrange )
+        vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange);
+
+      if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) )
+	vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset);
+      if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) )
+	vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor);
+
+      vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned));
+
+      vlistDefVarInstitut(vlistID, varID, instID);
+      vlistDefVarModel(vlistID, varID, modelID);
+      if ( ncvars[ncvarid].tableID != UNDEFID )
+	vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID);
+
+      if ( ncvars[ncvarid].deffillval == false && ncvars[ncvarid].defmissval )
+        {
+          ncvars[ncvarid].deffillval = true;
+          ncvars[ncvarid].fillval    = ncvars[ncvarid].missval;
+        }
+
+      if ( ncvars[ncvarid].deffillval )
+        vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval);
+
+      if ( CDI_Debug )
+	Message("varID = %d  gridID = %d  zaxisID = %d", varID,
+		vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID));
+
+      int gridindex = vlistGridIndex(vlistID, gridID);
+      int xdimid = streamptr->xdimID[gridindex];
+      int ydimid = streamptr->ydimID[gridindex];
+
+      int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+      int zdimid = streamptr->zaxisID[zaxisindex];
+
+      int ndims = ncvars[ncvarid].ndims;
+      int iodim = 0;
+      int ixyz = 0;
+      int ipow10[4] = {1, 10, 100, 1000};
+
+      if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++;
+
+      int *dimids = ncvars[ncvarid].dimids;
+
+      if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid )
+        {
+          ixyz = (xdimid == dimids[ndims-1]) ? 321 : 213;
+        }
+      else
+        {
+          for ( int idim = iodim; idim < ndims; idim++ )
+            {
+              if      ( xdimid == dimids[idim] ) ixyz += 1*ipow10[ndims-idim-1];
+              else if ( ydimid == dimids[idim] ) ixyz += 2*ipow10[ndims-idim-1];
+              else if ( zdimid == dimids[idim] ) ixyz += 3*ipow10[ndims-idim-1];
+            }
+        }
+
+      vlistDefVarXYZ(vlistID, varID, ixyz);
+      /*
+      printf("ixyz %d\n", ixyz);
+      printf("ndims %d\n", ncvars[ncvarid].ndims);
+      for ( int i = 0; i < ncvars[ncvarid].ndims; ++i )
+        printf("dimids: %d %d\n", i, dimids[i]);
+      printf("xdimid, ydimid %d %d\n", xdimid, ydimid);
+      */
+      if ( ncvars[ncvarid].ensdata != NULL )
+        {
+          vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index,
+                               ncvars[ncvarid].ensdata->ens_count,
+                               ncvars[ncvarid].ensdata->forecast_init_type );
+          Free(ncvars[ncvarid].ensdata);
+          ncvars[ncvarid].ensdata = NULL;
+        }
+
+      if ( ncvars[ncvarid].extra[0] != 0 )
+        {
+          vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
+        }
+    }
+
+  for ( int varID = 0; varID < nvars; varID++ )
+    {
+      int ncvarid = varids[varID];
+      int ncid = ncvars[ncvarid].ncid;
+
+      int nvatts = ncvars[ncvarid].natts;
+      for ( int iatt = 0; iatt < nvatts; ++iatt )
+        {
+          int attnum = ncvars[ncvarid].atts[iatt];
+          cdf_set_cdi_attr(ncid, ncvarid, attnum, vlistID, varID);
+        }
+
+      if ( ncvars[ncvarid].atts )
+        {
+          Free(ncvars[ncvarid].atts);
+          ncvars[ncvarid].atts = NULL;
+        }
+
+      if ( ncvars[ncvarid].vct )
+        {
+          Free(ncvars[ncvarid].vct);
+          ncvars[ncvarid].vct = NULL;
+        }
+    }
+
+  /* release mem of not freed attributes */
+  for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ )
+    if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts);
+
+  if ( varids ) Free(varids);
+
+  for ( int varID = 0; varID < nvars; varID++ )
+    {
+      if ( vlistInqVarCode(vlistID, varID) == -varID-1 )
+	{
+	  const char *pname = vlistInqVarNamePtr(vlistID, varID);
+	  size_t len = strlen(pname);
+	  if ( len > 3 && isdigit((int) pname[3]) )
+	    {
+	      if ( memcmp("var", pname, 3) == 0 )
+		{
+		  vlistDefVarCode(vlistID, varID, atoi(pname+3));
+                  // vlistDestroyVarName(vlistID, varID);
+		}
+	    }
+	  else if ( len > 4 && isdigit((int) pname[4]) )
+	    {
+	      if ( memcmp("code", pname, 4) == 0 )
+		{
+		  vlistDefVarCode(vlistID, varID, atoi(pname+4));
+		  // vlistDestroyVarName(vlistID, varID);
+		}
+	    }
+	  else if ( len > 5 && isdigit((int) pname[5]) )
+	    {
+	      if ( memcmp("param", pname, 5) == 0 )
+		{
+		  int pnum = -1, pcat = 255, pdis = 255;
+		  sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis);
+		  vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis));
+                  // vlistDestroyVarName(vlistID, varID);
+		}
+	    }
+	}
+    }
+
+  for ( int varID = 0; varID < nvars; varID++ )
+    {
+      int varInstID  = vlistInqVarInstitut(vlistID, varID);
+      int varModelID = vlistInqVarModel(vlistID, varID);
+      int varTableID = vlistInqVarTable(vlistID, varID);
+      int code = vlistInqVarCode(vlistID, varID);
+      if ( cdiDefaultTableID != UNDEFID )
+	{
+	  if ( tableInqParNamePtr(cdiDefaultTableID, code) )
+	    {
+	      vlistDestroyVarName(vlistID, varID);
+	      vlistDestroyVarLongname(vlistID, varID);
+	      vlistDestroyVarUnits(vlistID, varID);
+
+	      if ( varTableID != UNDEFID )
+		{
+		  vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code));
+		  if ( tableInqParLongnamePtr(cdiDefaultTableID, code) )
+		    vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code));
+		  if ( tableInqParUnitsPtr(cdiDefaultTableID, code) )
+		    vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code));
+		}
+	      else
+		{
+		  varTableID = cdiDefaultTableID;
+		}
+	    }
+
+	  if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID;
+	  if ( cdiDefaultInstID  != UNDEFID ) varInstID  = cdiDefaultInstID;
+	}
+      if ( varInstID  != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID);
+      if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID);
+      if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID);
+    }
+}
+
+static
+void cdf_scan_global_attr(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, bool *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used)
+{
+  nc_type xtype;
+  size_t attlen;
+  char attname[CDI_MAX_NAME];
+  enum { attstringlen = 65636 };
+  char attstring[attstringlen];
+
+  for ( int iatt = 0; iatt < ngatts; iatt++ )
+    {
+      cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname);
+      cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
+      cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
+
+      if ( xtypeIsText(xtype) )
+	{
+	  cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring);
+
+          size_t attstrlen = strlen(attstring);
+
+	  if ( attlen > 0 && attstring[0] != 0 )
+	    {
+	      if ( strcmp(attname, "history") == 0 )
+		{
+		  streamptr->historyID = iatt;
+		}
+	      else if ( strcmp(attname, "institution") == 0 )
+		{
+		  *instID = institutInq(0, 0, NULL, attstring);
+		  if ( *instID == UNDEFID )
+		    *instID = institutDef(0, 0, NULL, attstring);
+		}
+	      else if ( strcmp(attname, "source") == 0 )
+		{
+		  *modelID = modelInq(-1, 0, attstring);
+		  if ( *modelID == UNDEFID )
+		    *modelID = modelDef(-1, 0, attstring);
+		}
+	      else if ( strcmp(attname, "Source") == 0 )
+		{
+		  if ( strncmp(attstring, "UCLA-LES", 8) == 0 )
+		    *ucla_les = true;
+		}
+	      /*
+	      else if ( strcmp(attname, "Conventions") == 0 )
+		{
+		}
+	      */
+	      else if ( strcmp(attname, "CDI") == 0 )
+		{
+		}
+	      else if ( strcmp(attname, "CDO") == 0 )
+		{
+		}
+              /*
+	      else if ( strcmp(attname, "forecast_reference_time") == 0 )
+		{
+                  memcpy(fcreftime, attstring, attstrlen+1);
+		}
+              */
+	      else if ( strcmp(attname, "grid_file_uri") == 0 )
+		{
+                  memcpy(gridfile, attstring, attstrlen+1);
+		}
+	      else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 )
+		{
+                  attstring[36] = 0;
+                  cdiStr2UUID(attstring, uuidOfHGrid);
+                  //   printf("uuid: %d %s\n", attlen, attstring);
+		}
+	      else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
+		{
+                  attstring[36] = 0;
+                  cdiStr2UUID(attstring, uuidOfVGrid);
+		}
+	      else
+		{
+                  if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
+                    {
+                      memcpy(gridfile, attstring, attstrlen+1);
+                    }
+
+		  cdiDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring);
+		}
+	    }
+	}
+      else if ( xtype == NC_SHORT || xtype == NC_INT )
+	{
+	  if ( strcmp(attname, "number_of_grid_used") == 0 )
+	    {
+	      (*number_of_grid_used) = UNDEFID;
+	      cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used);
+	    }
+ 	  else
+            {
+              int attint[attlen];
+              cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
+              int datatype = (xtype == NC_SHORT) ? DATATYPE_INT16 : DATATYPE_INT32;
+              cdiDefAttInt(vlistID, CDI_GLOBAL, attname, datatype, (int)attlen, attint);
+            }
+        }
+      else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE )
+	{
+	  double attflt[attlen];
+	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
+          int datatype = (xtype == NC_FLOAT) ? DATATYPE_FLT32 : DATATYPE_FLT64;
+          cdiDefAttFlt(vlistID, CDI_GLOBAL, attname, datatype, (int)attlen, attflt);
+	}
+    }
+}
+
+static
+int find_leadtime(int nvars, ncvar_t *ncvars)
+{
+  int leadtime_id = UNDEFID;
+
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      if ( ncvars[ncvarid].stdname[0] && strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 )
+        {
+          leadtime_id = ncvarid;
+          break;
+        }
+    }
+
+  return leadtime_id;
+}
+
+static
+void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr,
+                    bool *time_has_units, bool *time_has_bounds, bool *time_climatology)
+{
+  int ncvarid;
+
+  if ( timedimid == UNDEFID )
+    {
+      char timeunits[CDI_MAX_NAME];
+
+      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+        {
+          if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 )
+            {
+              if ( ncvars[ncvarid].units[0] )
+                {
+                  strcpy(timeunits, ncvars[ncvarid].units);
+                  str_tolower(timeunits);
+
+                  if ( is_time_units(timeunits) )
+                    {
+                      streamptr->basetime.ncvarid = ncvarid;
+                      break;
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      bool ltimevar = false;
+
+      if ( ncdims[timedimid].ncvarid != UNDEFID )
+        {
+          streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid;
+          ltimevar = true;
+        }
+
+      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+        if ( ncvarid != streamptr->basetime.ncvarid &&
+             ncvars[ncvarid].ndims == 1 &&
+             timedimid == ncvars[ncvarid].dimids[0] &&
+             !xtypeIsText(ncvars[ncvarid].xtype) &&
+             is_timeaxis_units(ncvars[ncvarid].units) )
+          {
+            ncvars[ncvarid].isvar = FALSE;
+
+            if ( !ltimevar )
+              {
+                streamptr->basetime.ncvarid = ncvarid;
+                ltimevar = true;
+                if ( CDI_Debug )
+                  fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name);
+              }
+            else
+              {
+                Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name);
+              }
+          }
+
+      if ( ltimevar == false ) /* search for WRF time description */
+        {
+          for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+            if ( ncvarid != streamptr->basetime.ncvarid &&
+                 ncvars[ncvarid].ndims == 2 &&
+                 timedimid == ncvars[ncvarid].dimids[0] &&
+                 xtypeIsText(ncvars[ncvarid].xtype) &&
+                 ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
+              {
+                streamptr->basetime.ncvarid = ncvarid;
+                streamptr->basetime.lwrf    = true;
+                break;
+              }
+        }
+
+      /* time varID */
+      ncvarid = streamptr->basetime.ncvarid;
+
+      if ( ncvarid == UNDEFID )
+        {
+          Warning("Time variable >%s< not found!", ncdims[timedimid].name);
+        }
+    }
+
+  /* time varID */
+  ncvarid = streamptr->basetime.ncvarid;
+
+  if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == false )
+    {
+      if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = true;
+
+      if ( ncvars[ncvarid].bounds != UNDEFID )
+        {
+          int nbdims = ncvars[ncvars[ncvarid].bounds].ndims;
+          if ( nbdims == 2 )
+            {
+              int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len;
+              if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] )
+                {
+                  *time_has_bounds = true;
+                  streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds;
+                  if ( ncvars[ncvarid].climatology ) *time_climatology = true;
+                }
+            }
+        }
+    }
+}
+
+static
+void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize)
+{
+  /* find ECHAM VCT */
+  int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID;
+
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      if ( ncvars[ncvarid].ndims == 1 )
+        {
+          size_t len = strlen(ncvars[ncvarid].name);
+          if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' )
+            {
+              if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai
+                {
+                  vcta_id = ncvarid;
+                  nvcth_id = ncvars[ncvarid].dimids[0];
+                  ncvars[ncvarid].isvar = FALSE;
+                }
+              else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi
+                {
+                  vctb_id = ncvarid;
+                  nvcth_id = ncvars[ncvarid].dimids[0];
+                  ncvars[ncvarid].isvar = FALSE;
+                }
+              else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' )
+                {
+                  ncvars[ncvarid].isvar = FALSE; // hyam or hybm
+                }
+            }
+	}
+    }
+
+  /* read VCT */
+  if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID )
+    {
+      size_t vctsize = ncdims[nvcth_id].len;
+      vctsize *= 2;
+      *vct = (double *) Malloc(vctsize*sizeof(double));
+      cdf_get_var_double(fileID, vcta_id, *vct);
+      cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2);
+      *pvctsize = vctsize;
+    }
+}
+
+static
+void cdf_set_ucla_dimtype(int ndims, ncdim_t *ncdims, ncvar_t *ncvars)
+{
+  for ( int ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      int ncvarid = ncdims[ncdimid].ncvarid;
+      if ( ncvarid != -1 )
+        {
+          if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' )
+            {
+              if      ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS;
+              else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS;
+              else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS;
+            }
+        }
+    }
+}
+
+static
+int cdf_check_vars(int nvars, ncvar_t *ncvars, int ntsteps, int timedimid)
+{
+  for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      if ( timedimid != UNDEFID )
+	if ( ncvars[ncvarid].isvar == -1 &&
+	     ncvars[ncvarid].ndims > 1   &&
+	     timedimid == ncvars[ncvarid].dimids[0] )
+	  cdf_set_var(ncvars, ncvarid, TRUE);
+
+      if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 )
+	cdf_set_var(ncvars, ncvarid, FALSE);
+
+      //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 )
+      if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 )
+	cdf_set_var(ncvars, ncvarid, TRUE);
+
+      if ( ncvars[ncvarid].isvar == -1 )
+	{
+	  ncvars[ncvarid].isvar = 0;
+	  Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name);
+	  continue;
+	}
+
+      if ( ncvars[ncvarid].ndims > 4 )
+	{
+	  ncvars[ncvarid].isvar = 0;
+	  Warning("%d dimensional variables are not supported, skipped variable %s!",
+		ncvars[ncvarid].ndims, ncvars[ncvarid].name);
+	  continue;
+	}
+
+      if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID )
+	{
+	  ncvars[ncvarid].isvar = 0;
+	  Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!",
+		ncvars[ncvarid].ndims, ncvars[ncvarid].name);
+	  continue;
+	}
+
+      if ( xtypeIsText(ncvars[ncvarid].xtype) )
+	{
+	  ncvars[ncvarid].isvar = 0;
+	  continue;
+	}
+
+      if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 )
+	{
+	  ncvars[ncvarid].isvar = 0;
+	  Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name);
+	  continue;
+	}
+
+      if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 )
+	{
+	  if ( timedimid == ncvars[ncvarid].dimids[0] )
+	    {
+	      ncvars[ncvarid].isvar = 0;
+	      Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name);
+	      continue;
+	    }
+	}
+    }
+
+  return timedimid;
+}
+
+
+int cdfInqContents(stream_t *streamptr)
+{
+  int ndims, nvars, ngatts, unlimdimid;
+  int ncvarid;
+  int ncdimid;
+  int timedimid = -1;
+  int *varids;
+  int nvarids;
+  bool time_has_units = false;
+  bool time_has_bounds = false;
+  bool time_climatology = false;
+  int leadtime_id = UNDEFID;
+  int nvars_data;
+  int instID  = UNDEFID;
+  int modelID = UNDEFID;
+  int taxisID;
+  int calendar = UNDEFID;
+  int format = 0;
+  bool ucla_les = false;
+  char gridfile[8912];
+  char fcreftime[CDI_MAX_NAME];
+  int number_of_grid_used = UNDEFID;
+
+  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
+  unsigned char uuidOfVGrid[CDI_UUID_SIZE];
+  memset(uuidOfHGrid, 0, CDI_UUID_SIZE);
+  memset(uuidOfVGrid, 0, CDI_UUID_SIZE);
+  gridfile[0] = 0;
+  fcreftime[0] = 0;
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+
+#if  defined  (HAVE_NETCDF4)
+  nc_inq_format(fileID, &format);
+#endif
+
+  cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid);
+
+  if ( CDI_Debug )
+    Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts);
+
+  if ( ndims == 0 )
+    {
+      Warning("No dimensions found!");
+      return CDI_EUFSTRUCT;
+    }
+
+  /* alloc ncdims */
+  ncdim_t *ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t));
+  init_ncdims(ndims, ncdims);
+
+#if  defined  (TEST_GROUPS)
+#if  defined  (HAVE_NETCDF4)
+  if ( format == NC_FORMAT_NETCDF4 )
+    {
+      int ncid;
+      int numgrps;
+      int ncids[NC_MAX_VARS];
+      char name1[CDI_MAX_NAME];
+      int gndims, gnvars, gngatts, gunlimdimid;
+      nc_inq_grps(fileID, &numgrps, ncids);
+      for ( int i = 0; i < numgrps; ++i )
+        {
+          ncid = ncids[i];
+          nc_inq_grpname(ncid, name1);
+          cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid);
+
+          if ( CDI_Debug )
+            Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts);
+
+          if ( gndims == 0 )
+            {
+            }
+        }
+    }
+#endif
+#endif
+
+  if ( nvars == 0 )
+    {
+      Warning("No arrays found!");
+      return CDI_EUFSTRUCT;
+    }
+
+  /* alloc ncvars */
+  ncvar_t *ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t));
+  init_ncvars(nvars, ncvars);
+
+  for ( ncvarid = 0; ncvarid < nvars; ++ncvarid ) ncvars[ncvarid].ncid = fileID;
+
+
+  /* scan global attributes */
+  cdf_scan_global_attr(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les,
+                       uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used);
+
+  /* find time dim */
+  if ( unlimdimid >= 0 )
+    timedimid = unlimdimid;
+  else
+    timedimid = cdf_time_dimid(fileID, ndims, nvars);
+
+  streamptr->basetime.ncdimid = timedimid;
+
+  size_t ntsteps = 0;
+  if ( timedimid != UNDEFID ) cdf_inq_dimlen(fileID, timedimid, &ntsteps);
+
+  if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps);
+  if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid);
+
+  /* read ncdims */
+  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len);
+      cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name);
+      if ( timedimid == ncdimid )
+	ncdims[ncdimid].dimtype = T_AXIS;
+    }
+
+  if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "cdf_scan_var_attr");
+
+  /* scan attributes of all variables */
+  cdf_scan_var_attr(nvars, ncvars, ncdims, timedimid, modelID, format);
+
+
+  if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "find coordinate vars");
+
+  /* find coordinate vars */
+  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+	{
+	  if ( ncvars[ncvarid].ndims == 1 )
+	    {
+	      if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] )
+		{
+		  if ( ncvars[ncvarid].isvar != FALSE ) cdf_set_var(ncvars, ncvarid, TRUE);
+		}
+	      else
+		{
+                  //  if ( ncvars[ncvarid].isvar != TRUE ) cdf_set_var(ncvars, ncvarid, FALSE);
+		}
+	      // if ( ncvars[ncvarid].isvar != TRUE ) cdf_set_var(ncvars, ncvarid, FALSE);
+
+	      if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID )
+		if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 )
+		  {
+		    ncdims[ncdimid].ncvarid = ncvarid;
+		    ncvars[ncvarid].isvar = FALSE;
+		  }
+	    }
+	}
+    }
+
+  /* find time vars */
+  find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology);
+
+  leadtime_id = find_leadtime(nvars, ncvars);
+  if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE;
+
+  /* check ncvars */
+  timedimid = cdf_check_vars(nvars, ncvars, ntsteps, timedimid);
+
+  /* verify coordinate vars - first scan (dimname == varname) */
+  verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid);
+
+  /* verify coordinate vars - second scan (all other variables) */
+  verify_coordinate_vars_2(nvars, ncvars);
+
+  if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "verify_coordinate_vars");
+
+  if ( ucla_les ) cdf_set_ucla_dimtype(ndims, ncdims, ncvars);
+
+  /*
+  for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+    {
+      ncvarid = ncdims[ncdimid].ncvarid;
+      if ( ncvarid != -1 )
+	{
+	  printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units);
+	  if ( ncdims[ncdimid].dimtype == X_AXIS )
+	    printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name);
+	  if ( ncdims[ncdimid].dimtype == Y_AXIS )
+	    printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name);
+	  if ( ncdims[ncdimid].dimtype == Z_AXIS )
+	    printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name);
+	  if ( ncdims[ncdimid].dimtype == T_AXIS )
+	    printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name);
+
+	  if ( ncvars[ncvarid].islon )
+	    printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name);
+	  if ( ncvars[ncvarid].islat )
+	    printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name);
+	  if ( ncvars[ncvarid].islev )
+	    printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name);
+	}
+    }
+  */
+
+  /* Set coordinate varids (att: associate)  */
+  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    {
+      ncvar_t *ncvar = &ncvars[ncvarid];
+      if ( ncvar->isvar == TRUE && ncvar->ncoordvars )
+	{
+	  int ndims = ncvar->ncoordvars;
+	  for ( int i = 0; i < ndims; i++ )
+	    {
+	      if      ( ncvars[ncvar->coordvarids[i]].islon ||
+                        ncvars[ncvar->coordvarids[i]].isx )   ncvar->xvarid = ncvar->coordvarids[i];
+	      else if ( ncvars[ncvar->coordvarids[i]].islat ||
+                        ncvars[ncvar->coordvarids[i]].isy )   ncvar->yvarid = ncvar->coordvarids[i];
+	      else if ( ncvars[ncvar->coordvarids[i]].islev ) ncvar->zvarid = ncvar->coordvarids[i];
+	    }
+	}
+    }
+
+  /* set dim type */
+  cdf_set_dimtype(nvars, ncvars, ncdims);
+
+  /* read ECHAM VCT if present */
+  size_t vctsize = 0;
+  double *vct = NULL;
+  read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize);
+
+
+  if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "cdf_define_all_grids");
+
+  /* define all grids */
+  cdf_define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used);
+
+
+  /* define all zaxes */
+  cdf_define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
+  if ( vct ) Free(vct);
+
+
+  /* select vars */
+  varids = (int *) Malloc((size_t)nvars * sizeof (int));
+  nvarids = 0;
+  for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+    if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
+
+  nvars_data = nvarids;
+
+  if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid);
+  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+  if ( CDI_Debug ) Message("nvars_data = %d", nvars_data);
+
+
+  if ( nvars_data == 0 )
+    {
+      streamptr->ntsteps = 0;
+      return CDI_EUFSTRUCT;
+    }
+
+  if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
+    ntsteps = 1;
+
+  streamptr->ntsteps = (long)ntsteps;
+
+  /* define all data variables */
+  cdf_define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
+
+
+  cdiCreateTimesteps(streamptr);
+
+  /* time varID */
+  int nctimevarid = streamptr->basetime.ncvarid;
+
+  if ( time_has_units )
+    {
+      taxis_t *taxis = &streamptr->tsteps[0].taxis;
+
+      if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 )
+        {
+          nctimevarid = UNDEFID;
+          streamptr->basetime.ncvarid = UNDEFID;
+        }
+
+      if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE )
+        {
+          streamptr->basetime.leadtimeid = leadtime_id;
+          taxis->type = TAXIS_FORECAST;
+
+          int timeunit = -1;
+          if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units);
+          if ( timeunit == -1 ) timeunit = taxis->unit;
+          taxis->fc_unit = timeunit;
+
+          setForecastTime(fcreftime, taxis);
+        }
+    }
+
+  if ( time_has_bounds )
+    {
+      streamptr->tsteps[0].taxis.has_bounds = true;
+      if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = true;
+    }
+
+  if ( nctimevarid != UNDEFID )
+    {
+      taxis_t *taxis = &streamptr->tsteps[0].taxis;
+      ptaxisDefName(taxis, ncvars[nctimevarid].name);
+      if ( ncvars[nctimevarid].longname[0] )
+        ptaxisDefLongname(taxis, ncvars[nctimevarid].longname);
+    }
+
+  if ( nctimevarid != UNDEFID )
+    if ( ncvars[nctimevarid].calendar == TRUE )
+      {
+        enum {attstringlen = 8192};
+        char attstring[attstringlen];
+
+	cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring);
+	str_tolower(attstring);
+        set_calendar(attstring, &calendar);
+      }
+
+  if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST )
+    {
+      taxisID = taxisCreate(TAXIS_FORECAST);
+    }
+  else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE )
+    {
+      taxisID = taxisCreate(TAXIS_RELATIVE);
+    }
+  else
+    {
+      taxisID = taxisCreate(TAXIS_ABSOLUTE);
+      if ( !time_has_units )
+	{
+	  taxisDefTunit(taxisID, TUNIT_DAY);
+	  streamptr->tsteps[0].taxis.unit = TUNIT_DAY;
+	}
+    }
+
+
+  if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE )
+    {
+      calendar = CALENDAR_STANDARD;
+    }
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wstrict-overflow"
+#endif
+  if ( calendar != UNDEFID )
+    {
+      taxis_t *taxis = &streamptr->tsteps[0].taxis;
+      taxis->calendar = calendar;
+      taxisDefCalendar(taxisID, calendar);
+    }
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic pop
+#endif
+
+  vlistDefTaxis(vlistID, taxisID);
+
+  streamptr->curTsID = 0;
+  streamptr->rtsteps = 1;
+
+  (void) cdfInqTimestep(streamptr, 0);
+
+  cdfCreateRecords(streamptr, 0);
+
+  /* free ncdims */
+  Free(ncdims);
+
+  /* free ncvars */
+  Free(ncvars);
+
+  return 0;
+}
+
+static
+void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis)
+{
+  size_t start[2], count[2];
+  char stvalue[32];
+  start[0] = (size_t) tsID; start[1] = 0;
+  count[0] = 1; count[1] = 19;
+  stvalue[0] = 0;
+  cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
+  stvalue[19] = 0;
+  {
+    int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0;
+    if ( strlen(stvalue) == 19 )
+      sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
+    taxis->vdate = cdiEncodeDate(year, month, day);
+    taxis->vtime = cdiEncodeTime(hour, minute, second);
+    taxis->type = TAXIS_ABSOLUTE;
+  }
+}
+
+static
+double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache)
+{
+  double timevalue = 0;
+
+  if ( tcache )
+    {
+      if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) )
+        {
+          int maxvals = MAX_TIMECACHE_SIZE;
+          tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE;
+          if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE;
+          tcache->size = maxvals;
+          size_t index = (size_t) tcache->startid;
+          // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals);
+          for ( int ival = 0; ival < maxvals; ++ival )
+            {
+              cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
+              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+              tcache->cache[ival] = timevalue;
+              index++;
+            }
+        }
+
+      timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE];
+    }
+  else
+    {
+      size_t index = (size_t) tsID;
+      cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
+      if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+    }
+
+  return timevalue;
+}
+
+
+int cdfInqTimestep(stream_t * streamptr, int tsID)
+{
+  if ( CDI_Debug ) Message("streamID = %d  tsID = %d", streamptr->self, tsID);
+
+  if ( tsID < 0 ) Error("unexpected tsID = %d", tsID);
+
+  if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 )
+    {
+      cdfCreateRecords(streamptr, tsID);
+
+      taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+      if ( tsID > 0 )
+	ptaxisCopy(taxis, &streamptr->tsteps[0].taxis);
+
+      double timevalue = tsID;
+
+      int nctimevarid = streamptr->basetime.ncvarid;
+      if ( nctimevarid != UNDEFID )
+	{
+	  int fileID = streamptr->fileID;
+	  size_t index  = (size_t)tsID;
+
+	  if ( streamptr->basetime.lwrf )
+	    {
+              wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
+	    }
+	  else
+	    {
+#if defined (USE_TIMECACHE)
+              if ( streamptr->basetime.timevar_cache == NULL )
+                {
+                  streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t));
+                  streamptr->basetime.timevar_cache->size = 0;
+                  streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps;
+                }
+#endif
+              timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache);
+	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime);
+	    }
+
+	  int nctimeboundsid = streamptr->basetime.ncvarboundsid;
+	  if ( nctimeboundsid != UNDEFID )
+	    {
+	      size_t start[2], count[2];
+              start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
+	      cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
+              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+
+	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb);
+
+              start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1;
+	      cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
+              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+
+	      cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub);
+	    }
+
+          int leadtimeid = streamptr->basetime.leadtimeid;
+          if ( leadtimeid != UNDEFID )
+            {
+              timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
+              cdiSetForecastPeriod(timevalue, taxis);
+            }
+	}
+    }
+
+  streamptr->curTsID = tsID;
+  long nrecs = streamptr->tsteps[tsID].nrecs;
+
+  return (int) nrecs;
+}
+
+
+int cdfInqHistorySize(stream_t *streamptr)
+{
+  size_t size = 0;
+  int ncid = streamptr->fileID;
+  if ( streamptr->historyID != UNDEFID )
+    cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size);
+
+  return (int) size;
+}
+
+
+void cdfInqHistoryString(stream_t *streamptr, char *history)
+{
+  int ncid = streamptr->fileID;
+  if ( streamptr->historyID != UNDEFID )
+    {
+      nc_type atttype;
+      cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype);
+
+      if ( atttype == NC_CHAR )
+        {
+          cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
+        }
+#if  defined  (HAVE_NETCDF4)
+      else if ( atttype == NC_STRING )
+        {
+          // ToDo
+          Warning("History attribute with type NC_STRING unsupported!");
+        }
+#endif
+    }
+}
+
+#endif
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/stream_cdf_o.c b/src/stream_cdf_o.c
new file mode 100644
index 0000000000000000000000000000000000000000..70ba1e1e24e88a3ca69e9c829034d1c940b575fc
--- /dev/null
+++ b/src/stream_cdf_o.c
@@ -0,0 +1,2201 @@
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#ifdef HAVE_LIBNETCDF
+
+#include "dmemory.h"
+#include "cdi_int.h"
+#include "cdi_uuid.h"
+#include "stream_cdf.h"
+#include "cdf_int.h"
+#include "varscan.h"
+#include "vlist.h"
+#include "zaxis.h"
+
+
+#undef  UNDEFID
+#define UNDEFID  CDI_UNDEFID
+
+#define  POSITIVE_UP    1
+#define  POSITIVE_DOWN  2
+
+
+static const char bndsName[] = "bnds";
+
+
+void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+{
+  int vlistID1 = streamptr1->vlistID;
+  int tsID     = streamptr1->curTsID;
+  int vrecID   = streamptr1->tsteps[tsID].curRecID;
+  int recID    = streamptr1->tsteps[tsID].recIDs[vrecID];
+  int ivarID   = streamptr1->tsteps[tsID].records[recID].varID;
+  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
+  int datasize = gridInqSize(gridID);
+  int datatype = vlistInqVarDatatype(vlistID1, ivarID);
+  int memtype  = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT;
+
+  void *data = Malloc((size_t)datasize
+             * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float)));
+
+  int nmiss;
+  cdf_read_record(streamptr1, memtype, data, &nmiss);
+  cdf_write_record(streamptr2, memtype, data, nmiss);
+
+  Free(data);
+}
+
+/* not used
+int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
+{
+  int tsID, recID;
+
+  recID = streamptr->tsteps[0].curRecID++;
+  printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
+  printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
+
+  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
+    {
+      streamptr->tsteps[0].curRecID = 0;
+    }
+
+  *varID   = streamptr->tsteps[0].records[recID].varID;
+  *levelID = streamptr->tsteps[0].records[recID].levelID;
+
+  streamptr->record->varID   = *varID;
+  streamptr->record->levelID = *levelID;
+
+  if ( CDI_Debug )
+    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
+
+  return (recID+1);
+}
+*/
+
+
+void cdfDefRecord(stream_t *streamptr)
+{
+  (void)streamptr;
+}
+
+static
+void cdfDefTimeValue(stream_t *streamptr, int tsID)
+{
+  int fileID = streamptr->fileID;
+
+  if ( CDI_Debug )
+    Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+
+  if ( streamptr->ncmode == 1 )
+    {
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+    }
+
+  size_t index = (size_t)tsID;
+
+  double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
+  if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
+
+  int ncvarid = streamptr->basetime.ncvarid;
+  cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
+
+  if ( taxis->has_bounds )
+    {
+      size_t start[2], count[2];
+
+      ncvarid = streamptr->basetime.ncvarboundsid;
+
+      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
+      start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
+      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+
+      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
+      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
+      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+    }
+
+  ncvarid = streamptr->basetime.leadtimeid;
+  if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
+    {
+      timevalue = taxis->fc_period;
+      cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
+    }
+
+  /*
+printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
+  */
+}
+
+static
+int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis)
+{
+  int time_bndsid = -1;
+  int dims[2];
+
+  dims[0] = nctimedimid;
+
+  /* fprintf(stderr, "time has bounds\n"); */
+
+  if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR )
+    cdf_def_dim(fileID, bndsName, 2, &dims[1]);
+
+  const char *bndsAttName, *bndsAttVal;
+  size_t bndsAttValLen;
+  char tmpstr[CDI_MAX_NAME];
+  if ( taxis->climatology )
+    {
+      static const char climatology_bndsName[] = "climatology_bnds",
+        climatology_bndsAttName[] = "climatology";
+      bndsAttName = climatology_bndsAttName;
+      bndsAttValLen = sizeof (climatology_bndsName) - 1;
+      bndsAttVal = climatology_bndsName;
+    }
+  else
+    {
+      size_t taxisnameLen = strlen(taxis_name);
+      memcpy(tmpstr, taxis_name, taxisnameLen);
+      tmpstr[taxisnameLen] = '_';
+      memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName));
+      size_t tmpstrLen = taxisnameLen + sizeof (bndsName);
+      static const char generic_bndsAttName[] = "bounds";
+      bndsAttName = generic_bndsAttName;
+      bndsAttValLen = tmpstrLen;
+      bndsAttVal = tmpstr;
+    }
+  cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid);
+  cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal);
+
+  return time_bndsid;
+}
+
+static
+void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
+{
+  unitstr[0] = 0;
+
+  if ( taxis0->type == TAXIS_ABSOLUTE )
+    {
+      if ( taxis0->unit == TUNIT_YEAR )
+        sprintf(unitstr, "year as %s", "%Y.%f");
+      else if ( taxis0->unit == TUNIT_MONTH )
+        sprintf(unitstr, "month as %s", "%Y%m.%f");
+      else
+        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
+    }
+  else
+    {
+      int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
+      int rdate    = taxis->rdate;
+      int rtime    = taxis->rtime;
+      if ( rdate == -1 )
+        {
+          rdate  = taxis->vdate;
+          rtime  = taxis->vtime;
+        }
+
+      int year, month, day, hour, minute, second;
+      cdiDecodeDate(rdate, &year, &month, &day);
+      cdiDecodeTime(rtime, &hour, &minute, &second);
+
+      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
+      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
+      if ( timeunit == TUNIT_3HOURS  ||
+	   timeunit == TUNIT_6HOURS  ||
+	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
+
+      sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
+              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
+    }
+}
+
+static
+void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
+{
+  unitstr[0] = 0;
+
+  if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
+
+  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
+  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
+  if ( timeunit == TUNIT_3HOURS  ||
+       timeunit == TUNIT_6HOURS  ||
+       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
+
+  strcpy(unitstr, tunitNamePtr(timeunit));
+}
+
+static
+void cdfDefCalendar(int fileID, int ncvarid, int calendar)
+{
+  static const struct { int calCode; const char *calStr; } calTab[] = {
+    { CALENDAR_STANDARD, "standard" },
+    { CALENDAR_PROLEPTIC, "proleptic_gregorian" },
+    { CALENDAR_NONE, "none" },
+    { CALENDAR_360DAYS, "360_day" },
+    { CALENDAR_365DAYS, "365_day" },
+    { CALENDAR_366DAYS, "366_day" },
+  };
+  enum { calTabSize = sizeof calTab / sizeof calTab[0] };
+
+  for (size_t i = 0; i < calTabSize; ++i)
+    if (calTab[i].calCode == calendar)
+      {
+        const char *calstr = calTab[i].calStr;
+        size_t len = strlen(calstr);
+        cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
+        break;
+      }
+}
+
+
+void cdfDefTime(stream_t* streamptr)
+{
+  int time_varid;
+  int time_dimid;
+  int time_bndsid = -1;
+  static const char default_name[] = "time";
+
+  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
+
+  int fileID = streamptr->fileID;
+
+  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
+  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+  taxis_t *taxis = &streamptr->tsteps[0].taxis;
+
+  const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ;
+
+  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
+  streamptr->basetime.ncdimid = time_dimid;
+
+  cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid);
+
+  streamptr->basetime.ncvarid = time_varid;
+
+  {
+    static const char timeStr[] = "time";
+    cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr);
+  }
+
+  if ( taxis->longname && taxis->longname[0] )
+    cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);
+
+  if ( taxis->has_bounds )
+    {
+      time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
+      streamptr->basetime.ncvarboundsid = time_bndsid;
+    }
+
+  {
+    char unitstr[CDI_MAX_NAME];
+    cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
+    size_t len = strlen(unitstr);
+    if ( len )
+      {
+        cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
+        /*
+          if ( taxis->has_bounds )
+          cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
+        */
+      }
+  }
+
+  if ( taxis->calendar != -1 )
+    {
+      cdfDefCalendar(fileID, time_varid, taxis->calendar);
+      /*
+      if ( taxis->has_bounds )
+        cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
+      */
+    }
+
+  if ( taxis->type == TAXIS_FORECAST )
+    {
+      int leadtimeid;
+
+      cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid);
+
+      streamptr->basetime.leadtimeid = leadtimeid;
+
+      {
+        static const char stdname[] = "forecast_period";
+        cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname);
+      }
+
+      {
+        static const char lname[] = "Time elapsed since the start of the forecast";
+        cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname);
+      }
+
+      {
+          char unitstr[CDI_MAX_NAME];
+          cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);
+          size_t len = strlen(unitstr);
+          if ( len )
+            cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
+      }
+    }
+
+  cdf_put_att_text(fileID, time_varid, "axis", 1, "T");
+
+  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+}
+
+
+void cdfDefTimestep(stream_t *streamptr, int tsID)
+{
+  int vlistID = streamptr->vlistID;
+
+  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+
+  cdfDefTimeValue(streamptr, tsID);
+}
+
+static
+void cdfDefComplex(stream_t *streamptr, int gridID, int gridindex)
+{
+  int dimID = UNDEFID;
+  int fileID  = streamptr->fileID;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  for ( int index = 0; index < gridindex; ++index )
+    {
+      if ( ncgrid[index].xdimID != UNDEFID )
+        {
+          int gridID0 = ncgrid[index].gridID;
+          int gridtype0 = gridInqType(gridID0);
+          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
+            {
+              dimID = ncgrid[index].xdimID;
+              break;
+            }
+        }
+    }
+
+  if ( dimID == UNDEFID )
+    {
+      static const char axisname[] = "nc2";
+      size_t dimlen = 2;
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+      cdf_enddef(fileID);
+
+      streamptr->ncmode = 2;
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].xdimID = dimID;
+}
+
+static void
+cdfDefSPorFC(stream_t *streamptr, int gridID, int gridindex,
+             char *restrict axisname, int gridRefType)
+{
+  int index, iz = 0;
+  int dimID = UNDEFID;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  size_t dimlen = (size_t)gridInqSize(gridID)/2;
+
+  for ( index = 0; index < gridindex; index++ )
+    {
+      if ( ncgrid[index].ydimID != UNDEFID )
+        {
+          int gridID0 = ncgrid[index].gridID;
+          int gridtype0 = gridInqType(gridID0);
+          if ( gridtype0 == gridRefType )
+            {
+              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
+              if ( dimlen == dimlen0 )
+                {
+                  dimID = ncgrid[index].ydimID;
+                  break;
+                }
+              else
+                iz++;
+            }
+        }
+    }
+
+  if ( dimID == UNDEFID )
+    {
+      int fileID  = streamptr->fileID;
+      if ( iz == 0 ) axisname[3] = '\0';
+      else           sprintf(&axisname[3], "%1d", iz+1);
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].ydimID = dimID;
+}
+
+static
+void cdfDefSP(stream_t *streamptr, int gridID, int gridindex)
+{
+  /*
+  char longname[] = "Spherical harmonic coefficient";
+  */
+  char axisname[5] = "nspX";
+  cdfDefSPorFC(streamptr, gridID, gridindex, axisname, GRID_SPECTRAL);
+}
+
+
+static
+void cdfDefFC(stream_t *streamptr, int gridID, int gridindex)
+{
+  char axisname[5] = "nfcX";
+  cdfDefSPorFC(streamptr, gridID, gridindex, axisname, GRID_FOURIER);
+}
+
+static const struct cdfDefGridAxisInqs {
+  int (*axisSize)(int gridID);
+  void (*axisName)(int gridID, char *dimname);
+  void (*axisStdname)(int gridID, char *dimstdname);
+  void (*axisLongname)(int gridID, char *dimlongname);
+  void (*axisUnits)(int gridID, char *dimunits);
+  double (*axisVal)(int gridID, int index);
+  const double *(*axisValsPtr)(int gridID);
+  const double *(*axisBoundsPtr)(int gridID);
+} gridInqsX = {
+  .axisSize = gridInqXsize,
+  .axisName = gridInqXname,
+  .axisStdname = gridInqXstdname,
+  .axisLongname = gridInqXlongname,
+  .axisUnits = gridInqXunits,
+  .axisVal = gridInqXval,
+  .axisValsPtr = gridInqXvalsPtr,
+  .axisBoundsPtr = gridInqXboundsPtr,
+}, gridInqsY = {
+  .axisSize = gridInqYsize,
+  .axisName = gridInqYname,
+  .axisStdname = gridInqYstdname,
+  .axisLongname = gridInqYlongname,
+  .axisUnits = gridInqYunits,
+  .axisVal = gridInqYval,
+  .axisValsPtr = gridInqYvalsPtr,
+  .axisBoundsPtr = gridInqYboundsPtr,
+}, gridInqsZ = {
+  .axisStdname = zaxisInqStdname,
+  .axisLongname = zaxisInqLongname,
+  .axisUnits = zaxisInqUnits,
+};
+
+static void
+cdfPutGridStdAtts(int fileID, int ncvarid,
+                  int gridID, const struct cdfDefGridAxisInqs *inqs)
+{
+  size_t len;
+  {
+    char stdname[CDI_MAX_NAME];
+    inqs->axisStdname(gridID, stdname);
+    if ( (len = strlen(stdname)) )
+      cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
+  }
+  {
+    char longname[CDI_MAX_NAME];
+    inqs->axisLongname(gridID, longname);
+    if ( (len = strlen(longname)) )
+      cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
+  }
+  {
+    char units[CDI_MAX_NAME];
+    inqs->axisUnits(gridID, units);
+    if ( (len = strlen(units)) )
+      cdf_put_att_text(fileID, ncvarid, "units", len, units);
+  }
+}
+
+static void
+cdfDefTrajLatLon(stream_t *streamptr, int gridID, int gridindex,
+                 const struct cdfDefGridAxisInqs *inqs, int dimtype)
+{
+  nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  int dimlen = inqs->axisSize(gridID);
+  if ( dimlen != 1 )
+    Error("%c size isn't 1 for %s grid!", dimtype, gridNamePtr(gridInqType(gridID)));
+
+  int ncvarid = UNDEFID;
+  if ( dimtype == 'X' )
+    ncvarid = ncgrid[gridindex].xdimID;
+  else
+    ncvarid = ncgrid[gridindex].ydimID;
+
+  if ( ncvarid == UNDEFID )
+    {
+      int dimNcID = streamptr->basetime.ncvarid;
+      int fileID  = streamptr->fileID;
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      char axisname[CDI_MAX_NAME];
+      inqs->axisName(gridID, axisname);
+      cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
+      cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs);
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  if ( dimtype == 'X' )
+    ncgrid[gridindex].xdimID = ncvarid; /* var ID for trajectory !!! */
+  else
+    ncgrid[gridindex].ydimID = ncvarid; /* var ID for trajectory !!! */
+}
+
+static
+void cdfDefTrajLon(stream_t *streamptr, int gridID, int gridindex)
+{
+  cdfDefTrajLatLon(streamptr, gridID, gridindex, &gridInqsX, 'X');
+}
+
+
+static
+void cdfDefTrajLat(stream_t *streamptr, int gridID, int gridindex)
+{
+  cdfDefTrajLatLon(streamptr, gridID, gridindex, &gridInqsY, 'Y');
+}
+
+static
+int checkDimName(int fileID, size_t dimlen, char *dimname)
+{
+  /* check whether the dimenion name is already defined with the same length */
+  unsigned iz = 0;
+  int dimid = UNDEFID;
+  char name[CDI_MAX_NAME];
+
+  size_t len = strlen(dimname);
+  memcpy(name, dimname, len + 1);
+
+  do
+    {
+      if ( iz ) sprintf(name + len, "_%u", iz+1);
+
+      int dimid0, status = nc_inq_dimid(fileID, name, &dimid0);
+      if ( status != NC_NOERR )
+        break;
+      size_t dimlen0;
+      cdf_inq_dimlen(fileID, dimid0, &dimlen0);
+      if ( dimlen0 == dimlen )
+        {
+          dimid = dimid0;
+          break;
+        }
+      iz++;
+    }
+  while ( iz <= 99 );
+
+
+  if ( iz ) sprintf(dimname + len, "_%u", iz+1);
+
+  return dimid;
+}
+
+static
+void checkGridName(char *axisname, int fileID)
+{
+  int ncdimid;
+  char axisname2[CDI_MAX_NAME];
+
+  /* check that the name is not already defined */
+  unsigned iz = 0;
+
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
+  do
+    {
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
+
+      int status = nc_inq_varid(fileID, axisname2, &ncdimid);
+      if ( status != NC_NOERR ) break;
+
+      ++iz;
+    }
+  while ( iz <= 99 );
+
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
+}
+
+static
+int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis)
+{
+  char axisname2[CDI_MAX_NAME];
+
+  /* check that the name is not already defined */
+  unsigned iz = 0;
+
+  size_t axisnameLen = strlen(axisname);
+  memcpy(axisname2, axisname, axisnameLen + 1);
+  do
+    {
+      if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1);
+
+      int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid);
+
+      if ( status != NC_NOERR )
+        {
+          if ( iz )
+            {
+              /* check that the name does not exist for other zaxes */
+              for ( int index = 0; index < nzaxis; index++ )
+                {
+                  int zaxisID0 = vlistZaxis(vlistID, index);
+                  if ( zaxisID != zaxisID0 )
+                    {
+                      const char *axisname0 = zaxisInqNamePtr(zaxisID0);
+                      if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix;
+                    }
+                }
+            }
+          break;
+        }
+      nextSuffix:
+      ++iz;
+    }
+  while (iz <= 99);
+
+
+  if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1);
+
+  return (int)iz;
+}
+
+static void
+cdfDefAxisCommon(stream_t *streamptr, int gridID, int gridindex, int ndims,
+                 const struct cdfDefGridAxisInqs *gridAxisInq, int dimKey, char axisLetter,
+                 void (*finishCyclicBounds)(double *pbounds, size_t dimlen, const double *pvals))
+{
+  int dimID = UNDEFID;
+  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
+  int nvdimID = UNDEFID;
+  int fileID  = streamptr->fileID;
+  size_t dimlen = (size_t)gridAxisInq->axisSize(gridID);
+  nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  for ( int index = 0; index < gridindex; ++index )
+    {
+      int gridID0 = ncgrid[index].gridID;
+      assert(gridID0 != UNDEFID);
+      int gridtype0 = gridInqType(gridID0);
+      if ( gridtype0 == GRID_GAUSSIAN    ||
+           gridtype0 == GRID_LONLAT      ||
+           gridtype0 == GRID_PROJECTION  ||
+           gridtype0 == GRID_CURVILINEAR ||
+           gridtype0 == GRID_GENERIC )
+        {
+          size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0);
+          if ( dimlen == dimlen0 )
+            {
+              double (*inqVal)(int gridID, int index) = gridAxisInq->axisVal;
+              if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) &&
+                   IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) )
+                {
+                  if ( dimKey == CDI_KEY_XDIMNAME )
+                    dimID = ncgrid[index].xdimID;
+                  else
+                    dimID = ncgrid[index].ydimID;
+                  break;
+                }
+            }
+        }
+    }
+
+  if ( dimID == UNDEFID )
+    {
+      const double *pvals = gridAxisInq->axisValsPtr(gridID);
+
+      char axisname[CDI_MAX_NAME];
+      gridAxisInq->axisName(gridID, axisname);
+      if ( axisname[0] == 0 ) Error("axis name undefined!");
+      size_t axisnameLen = strlen(axisname);
+
+      /* enough to append _ plus up to 100 decimal and trailing \0 */
+      char extendedAxisname[axisnameLen + 4 + 1];
+      memcpy(extendedAxisname, axisname, axisnameLen + 1);
+      checkGridName(extendedAxisname, fileID);
+      size_t extendedAxisnameLen = axisnameLen + strlen(extendedAxisname + axisnameLen);
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      if ( ndims )
+        {
+          char dimname[CDI_MAX_NAME+3]; dimname[0] = 0;
+
+          if ( pvals == NULL )
+            cdiGridInqKeyStr(gridID, dimKey, CDI_MAX_NAME, dimname);
+
+          if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname);
+          dimID = checkDimName(fileID, dimlen, dimname);
+
+          if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
+        }
+
+      bool gen_bounds = false;
+      bool grid_is_cyclic = gridIsCircular(gridID) > 0;
+      double *pbounds = NULL;
+      if ( pvals )
+        {
+          cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid);
+
+          cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq);
+          {
+            char axisStr[2] = { axisLetter, '\0' };
+            cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr);
+          }
+
+          pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID);
+
+          if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+            {
+              gen_bounds = true;
+              pbounds = (double*) Malloc(2*dimlen*sizeof(double));
+              for ( size_t i = 0; i < dimlen-1; ++i )
+                {
+                  pbounds[i*2+1]   = (pvals[i] + pvals[i+1])/2;
+                  pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+                }
+              finishCyclicBounds(pbounds, dimlen, pvals);
+            }
+          if ( pbounds )
+            {
+              size_t nvertex = 2;
+              if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+                cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
+            }
+          if ( pbounds && nvdimID != UNDEFID )
+            {
+              char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)];
+              memcpy(boundsname, axisname, extendedAxisnameLen);
+              boundsname[extendedAxisnameLen] = '_';
+              memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName);
+              int dimIDs[2] = { dimID, nvdimID };
+              cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid);
+              cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname);
+            }
+        }
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+
+      if ( ncvarid  != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
+      if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
+      if ( gen_bounds ) Free(pbounds);
+
+      if ( ndims == 0 )
+        {
+          if ( dimKey == CDI_KEY_XDIMNAME )
+            ncgrid[gridindex].xvarID = ncvarid;
+          else
+            ncgrid[gridindex].yvarID = ncvarid;
+        }
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  if ( dimKey == CDI_KEY_XDIMNAME )
+    ncgrid[gridindex].xdimID = dimID;
+  else
+    ncgrid[gridindex].ydimID = dimID;
+}
+
+static
+void finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5;
+  pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5;
+}
+
+static
+void cdfDefXaxis(stream_t *streamptr, int gridID, int gridindex, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, gridindex, ndims, &gridInqsX,
+                   CDI_KEY_XDIMNAME, 'X', finishCyclicXBounds);
+}
+
+static
+void finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals)
+{
+  pbounds[0] = copysign(90.0, pvals[0]);
+  pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]);
+}
+
+static
+void cdfDefYaxis(stream_t *streamptr, int gridID, int gridindex, int ndims)
+{
+  cdfDefAxisCommon(streamptr, gridID, gridindex, ndims, &gridInqsY,
+                   CDI_KEY_YDIMNAME, 'Y', finishCyclicYBounds);
+}
+
+static
+void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype)
+{
+#if  defined  (HAVE_NETCDF4)
+  if ( gridsize > 1 && comptype == CDI_COMPRESS_ZIP && (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) )
+    {
+      nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
+      cdfDefVarDeflate(fileID, ncvarid, 1);
+    }
+#endif
+}
+
+static
+void cdfDefCurvilinear(stream_t *streamptr, int gridID, int gridindex)
+{
+  int xdimID = UNDEFID;
+  int ydimID = UNDEFID;
+  int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
+  int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
+  nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  int fileID  = streamptr->fileID;
+
+  size_t dimlen = (size_t)gridInqSize(gridID);
+  size_t xdimlen = (size_t)gridInqXsize(gridID);
+  size_t ydimlen = (size_t)gridInqYsize(gridID);
+
+  for ( int index = 0; index < gridindex; index++ )
+    {
+      if ( ncgrid[index].xdimID != UNDEFID )
+        {
+          int gridID0 = ncgrid[index].gridID;
+          int gridtype0 = gridInqType(gridID0);
+          if ( gridtype0 == GRID_CURVILINEAR )
+            {
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
+              if ( dimlen == dimlen0 )
+                if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+                     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
+                  {
+                    xdimID = ncgrid[index].xdimID;
+                    ydimID = ncgrid[index].ydimID;
+                    ncxvarid = ncgrid[index].xvarID;
+                    ncyvarid = ncgrid[index].yvarID;
+                    break;
+                  }
+            }
+        }
+    }
+
+  if ( xdimID == UNDEFID || ydimID == UNDEFID )
+    {
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqKeyStr(gridID, CDI_KEY_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; }
+        xdimID = checkDimName(fileID, xdimlen, xdimname);
+        if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID);
+      }
+      {
+        char ydimname[CDI_MAX_NAME+3];
+        ydimname[0] = 0;
+        cdiGridInqKeyStr(gridID, CDI_KEY_YDIMNAME, CDI_MAX_NAME, ydimname);
+        if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; }
+        ydimID = checkDimName(fileID, ydimlen, ydimname);
+        if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID);
+      }
+
+      int nvdimID = UNDEFID;
+      int dimIDs[3];
+      if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
+        {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqKeyStr(gridID, CDI_KEY_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4");
+          size_t nvertex = 4;
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
+        }
+
+      dimIDs[0] = ydimID;
+      dimIDs[1] = xdimID;
+      dimIDs[2] = nvdimID;
+
+      if ( gridInqXvalsPtr(gridID) )
+        {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID);
+
+          cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
+          cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
+
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
+
+          /* attribute for Panoply */
+          cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon");
+
+          if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
+            {
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
+              cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
+              cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
+
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
+            }
+        }
+
+      if ( gridInqYvalsPtr(gridID) )
+        {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID);
+
+          cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
+          cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
+
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
+
+          /* attribute for Panoply */
+          cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat");
+
+          if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
+            {
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
+              cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
+              cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
+
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
+            }
+        }
+
+      if ( gridInqAreaPtr(gridID) )
+        {
+          static const char yaxisname_[] = "cell_area";
+          static const char units[] = "m2";
+          static const char longname[] = "area of grid cell";
+          static const char stdname[] = "cell_area";
+
+          cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid);
+
+          cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
+          cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
+          cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units);
+        }
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+
+      if ( ncxvarid  != UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  gridInqXvalsPtr(gridID));
+      if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID));
+      if ( ncyvarid  != UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  gridInqYvalsPtr(gridID));
+      if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID));
+      if ( ncavarid  != UNDEFID ) cdf_put_var_double(fileID, ncavarid,  gridInqAreaPtr(gridID));
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].xdimID = xdimID;
+  ncgrid[gridindex].ydimID = ydimID;
+  ncgrid[gridindex].xvarID = ncxvarid;
+  ncgrid[gridindex].yvarID = ncyvarid;
+  ncgrid[gridindex].avarID = ncavarid;
+}
+
+static
+void cdfDefRgrid(stream_t *streamptr, int gridID, int gridindex)
+{
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+  int dimID = UNDEFID;
+
+  size_t dimlen = (size_t)gridInqSize(gridID);
+
+  int iz = 0;
+  for ( int index = 0; index < gridindex; index++ )
+    {
+      if ( ncgrid[index].xdimID != UNDEFID )
+        {
+          int gridID0 = ncgrid[index].gridID;
+          int gridtype0 = gridInqType(gridID0);
+          if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
+            {
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
+
+              if ( dimlen == dimlen0 )
+                {
+                  dimID = ncgrid[index].xdimID;
+                  break;
+                }
+              iz++;
+            }
+        }
+    }
+
+  if ( dimID == UNDEFID )
+    {
+      int fileID  = streamptr->fileID;
+      static bool lwarn = true;
+      if ( lwarn )
+        {
+          Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
+          Warning("The further processing of the resulting file is unsupported!");
+          lwarn = false;
+        }
+
+      char axisname[7] = "rgridX";
+      if ( iz == 0 ) axisname[5] = '\0';
+      else           sprintf(&axisname[5], "%1d", iz+1);
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      cdf_def_dim(fileID, axisname, dimlen, &dimID);
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].xdimID = dimID;
+}
+
+static
+void cdfDefGdim(stream_t *streamptr, int gridID, int gridindex)
+{
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+  int iz = 0;
+  int dimID = UNDEFID;
+
+  size_t dimlen = (size_t)gridInqSize(gridID);
+
+  if ( gridInqYsize(gridID) == 0 )
+    for ( int index = 0; index < gridindex; index++ )
+      {
+        if ( ncgrid[index].xdimID != UNDEFID )
+          {
+            int gridID0 = ncgrid[index].gridID;
+            int gridtype0 = gridInqType(gridID0);
+            if ( gridtype0 == GRID_GENERIC )
+              {
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
+                if ( dimlen == dimlen0 )
+                  {
+                    dimID = ncgrid[index].xdimID;
+                    break;
+                  }
+                else
+                  iz++;
+              }
+          }
+      }
+
+  if ( gridInqXsize(gridID) == 0 )
+    for ( int index = 0; index < gridindex; index++ )
+      {
+        if ( ncgrid[index].ydimID != UNDEFID )
+          {
+            int gridID0 = ncgrid[index].gridID;
+            int gridtype0 = gridInqType(gridID0);
+            if ( gridtype0 == GRID_GENERIC )
+              {
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
+                if ( dimlen == dimlen0 )
+                  {
+                    dimID = ncgrid[index].ydimID;
+                    break;
+                  }
+                else
+                  iz++;
+              }
+          }
+      }
+
+  if ( dimID == UNDEFID )
+    {
+      int fileID  = streamptr->fileID;
+      char dimname[CDI_MAX_NAME];
+      strcpy(dimname, "gsize");
+
+      dimID = checkDimName(fileID, dimlen, dimname);
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].xdimID = dimID;
+}
+
+static
+void cdfDefGridReference(stream_t *streamptr, int gridID)
+{
+  int fileID  = streamptr->fileID;
+  int number = gridInqNumber(gridID);
+
+  if ( number > 0 )
+    {
+      cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number);
+    }
+
+  const char *gridfile = gridInqReferencePtr(gridID);
+  if ( gridfile && gridfile[0] != 0 )
+    cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile);
+}
+
+static
+void cdfDefGridUUID(stream_t *streamptr, int gridID)
+{
+  unsigned char uuidOfHGrid[CDI_UUID_SIZE];
+
+  gridInqUUID(gridID, uuidOfHGrid);
+  if ( !cdiUUIDIsNull(uuidOfHGrid) )
+    {
+      char uuidOfHGridStr[37];
+      cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
+      if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
+        {
+          int fileID  = streamptr->fileID;
+          //if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+          cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfHGrid", 36, uuidOfHGridStr);
+          //if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+        }
+    }
+}
+
+static
+void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
+{
+  unsigned char uuidOfVGrid[CDI_UUID_SIZE];
+  zaxisInqUUID(zaxisID, uuidOfVGrid);
+
+  if ( uuidOfVGrid[0] != 0 )
+    {
+      char uuidOfVGridStr[37];
+      cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
+      if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
+        {
+          int fileID  = streamptr->fileID;
+          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+          cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfVGrid", 36, uuidOfVGridStr);
+          if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+        }
+    }
+}
+
+static
+void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
+{
+  int dimID = UNDEFID;
+  int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
+  int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
+  int nvdimID = UNDEFID;
+  nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE;
+  ncgrid_t *ncgrid = streamptr->ncgrid;
+
+  int fileID  = streamptr->fileID;
+
+  size_t dimlen = (size_t)gridInqSize(gridID);
+
+  for ( int index = 0; index < gridindex; index++ )
+    {
+      if ( ncgrid[index].xdimID != UNDEFID )
+        {
+          int gridID0 = ncgrid[index].gridID;
+          int gridtype0 = gridInqType(gridID0);
+          if ( gridtype0 == GRID_UNSTRUCTURED )
+            {
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
+              if ( dimlen == dimlen0 )
+		if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) &&
+		     IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) &&
+		     IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
+		  {
+		    dimID = ncgrid[index].xdimID;
+                    ncxvarid = ncgrid[index].xvarID;
+                    ncyvarid = ncgrid[index].yvarID;
+                    ncavarid = ncgrid[index].avarID;
+		    break;
+		  }
+            }
+        }
+    }
+
+  if ( dimID == UNDEFID )
+    {
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+      {
+        char xdimname[CDI_MAX_NAME+3];
+        xdimname[0] = 0;
+        cdiGridInqKeyStr(gridID, CDI_KEY_XDIMNAME, CDI_MAX_NAME, xdimname);
+        if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells");
+        dimID = checkDimName(fileID, dimlen, xdimname);
+        if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID);
+      }
+
+      size_t nvertex = (size_t)gridInqNvertex(gridID);
+      if ( nvertex > 0 )
+        {
+          char vdimname[CDI_MAX_NAME+3];
+          vdimname[0] = 0;
+          cdiGridInqKeyStr(gridID, CDI_KEY_VDIMNAME, CDI_MAX_NAME, vdimname);
+          if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices");
+          nvdimID = checkDimName(fileID, nvertex, vdimname);
+          if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID);
+        }
+
+      cdfDefGridReference(streamptr, gridID);
+
+      cdfDefGridUUID(streamptr, gridID);
+
+      if ( gridInqXvalsPtr(gridID) )
+        {
+          char xaxisname[CDI_MAX_NAME];
+          gridInqXname(gridID, xaxisname);
+          checkGridName(xaxisname, fileID);
+          cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
+          cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
+
+          cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX);
+
+          if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
+            {
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t xaxisnameLen = strlen(xaxisname);
+              xaxisname[xaxisnameLen] = '_';
+              memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName));
+              cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
+              cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
+
+              cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname);
+            }
+        }
+
+      if ( gridInqYvalsPtr(gridID) )
+        {
+          char yaxisname[CDI_MAX_NAME];
+          gridInqYname(gridID, yaxisname);
+          checkGridName(yaxisname, fileID);
+          cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
+          cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
+
+          cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY);
+
+          if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
+            {
+              int dimIDs[2] = { dimID, nvdimID };
+              size_t yaxisnameLen = strlen(yaxisname);
+              yaxisname[yaxisnameLen] = '_';
+              memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName));
+              cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
+              cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
+
+              cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname);
+            }
+        }
+
+      if ( gridInqAreaPtr(gridID) )
+        {
+          static const char yaxisname_[] = "cell_area";
+          static const char units[] = "m2";
+          static const char longname[] = "area of grid cell";
+          static const char stdname[] = "cell_area";
+
+          cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid);
+
+          cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
+          cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
+          cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units);
+        }
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+
+      if ( ncxvarid  != UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  gridInqXvalsPtr(gridID));
+      if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID));
+      if ( ncyvarid  != UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  gridInqYvalsPtr(gridID));
+      if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID));
+      if ( ncavarid  != UNDEFID ) cdf_put_var_double(fileID, ncavarid,  gridInqAreaPtr(gridID));
+    }
+
+  ncgrid[gridindex].gridID = gridID;
+  ncgrid[gridindex].xdimID = dimID;
+  ncgrid[gridindex].xvarID = ncxvarid;
+  ncgrid[gridindex].yvarID = ncyvarid;
+  ncgrid[gridindex].avarID = ncavarid;
+}
+
+struct attTxtTab2
+{
+  const char *attName, *attVal;
+  size_t valLen;
+};
+
+static
+void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
+{
+  int type = zaxisInqType(zaxisID);
+
+  if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
+    {
+      int ilev = zaxisInqVctSize(zaxisID)/2;
+      if ( ilev == 0 ) return;
+
+      int mlev = ilev - 1;
+      size_t start;
+      size_t count = 1;
+      int ncdimid, ncdimid2;
+      int hyaiid, hybiid, hyamid, hybmid;
+      double mval;
+
+      if ( streamptr->vct.ilev > 0 )
+        {
+          if ( streamptr->vct.ilev != ilev )
+            Error("more than one VCT for each file unsupported!");
+          return;
+        }
+
+      int fileID = streamptr->fileID;
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      cdf_def_dim(fileID, "nhym", (size_t)mlev, &ncdimid);
+      cdf_def_dim(fileID, "nhyi", (size_t)ilev, &ncdimid2);
+
+      streamptr->vct.mlev   = mlev;
+      streamptr->vct.ilev   = ilev;
+      streamptr->vct.mlevID = ncdimid;
+      streamptr->vct.ilevID = ncdimid2;
+
+      cdf_def_var(fileID, "hyai", NC_DOUBLE, 1, &ncdimid2, &hyaiid);
+      cdf_def_var(fileID, "hybi", NC_DOUBLE, 1, &ncdimid2, &hybiid);
+      cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid,  &hyamid);
+      cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid,  &hybmid);
+
+      {
+        static const char lname_n[] = "long_name",
+          lname_v_ai[] = "hybrid A coefficient at layer interfaces",
+          units_n[] = "units",
+          units_v_ai[] = "Pa",
+          lname_v_bi[] = "hybrid B coefficient at layer interfaces",
+          units_v_bi[] = "1",
+          lname_v_am[] = "hybrid A coefficient at layer midpoints",
+          units_v_am[] = "Pa",
+          lname_v_bm[] = "hybrid B coefficient at layer midpoints",
+          units_v_bm[] = "1";
+        static const struct attTxtTab2 tab[]
+          = {
+          { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 },
+          { units_n, units_v_ai, sizeof (units_v_ai) - 1 },
+          { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 },
+          { units_n, units_v_bi, sizeof (units_v_bi) - 1 },
+          { lname_n, lname_v_am, sizeof (lname_v_am) - 1 },
+          { units_n, units_v_am, sizeof (units_v_am) - 1 },
+          { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 },
+          { units_n, units_v_bm, sizeof (units_v_bm) - 1 },
+        };
+        enum { tabLen = sizeof (tab) / sizeof (tab[0]) };
+        int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid,
+                            hyamid, hyamid, hybmid, hybmid };
+        for ( size_t i = 0; i < tabLen; ++i )
+          cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal);
+      }
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+
+      const double *vctptr = zaxisInqVctPtr(zaxisID);
+
+      cdf_put_var_double(fileID, hyaiid, vctptr);
+      cdf_put_var_double(fileID, hybiid, vctptr+ilev);
+
+      for ( int i = 0; i < mlev; i++ )
+        {
+          start = (size_t)i;
+          mval = (vctptr[i] + vctptr[i+1]) * 0.5;
+          cdf_put_vara_double(fileID, hyamid, &start, &count, &mval);
+          mval = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5;
+          cdf_put_vara_double(fileID, hybmid, &start, &count, &mval);
+        }
+    }
+}
+
+static
+void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
+{
+  int type = zaxisInqType(zaxisID);
+
+  if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
+    {
+      int ilev = zaxisInqVctSize(zaxisID)/2;
+      if ( ilev == 0 ) return;
+
+      int mlev = ilev - 1;
+      int hyaiid = 0, hybiid = 0, hyamid, hybmid;
+
+      if ( streamptr->vct.ilev > 0 )
+        {
+          if ( streamptr->vct.ilev != ilev )
+            Error("more than one VCT for each file unsupported!");
+          return;
+        }
+
+      int fileID = streamptr->fileID;
+
+      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+      int dimIDs[2];
+      dimIDs[0] = nclevID;
+      dimIDs[1] = ncbndsID;
+
+      streamptr->vct.mlev   = mlev;
+      streamptr->vct.ilev   = ilev;
+      streamptr->vct.mlevID = nclevID;
+      streamptr->vct.ilevID = nclevID;
+
+      cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs,  &hyamid);
+      cdf_def_var(fileID, "b",  NC_DOUBLE, 1, dimIDs,  &hybmid);
+
+      {
+        static const char lname[] = "vertical coordinate formula term: ap(k)";
+        cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "Pa";
+        cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units);
+      }
+      {
+        static const char lname[] = "vertical coordinate formula term: b(k)";
+        cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname);
+      }
+      {
+        static const char units[] = "1";
+        cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units);
+      }
+
+      if ( ncbndsID != -1 )
+        {
+          cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid);
+          cdf_def_var(fileID, "b_bnds",  NC_DOUBLE, 2, dimIDs, &hybiid);
+          {
+            static const char lname[] = "vertical coordinate formula term: ap(k+1/2)";
+            cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "Pa";
+            cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units);
+          }
+          {
+            static const char lname[] = "vertical coordinate formula term: b(k+1/2)";
+            cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units);
+          }
+        }
+
+      cdf_enddef(fileID);
+      streamptr->ncmode = 2;
+
+      const double *vctptr = zaxisInqVctPtr(zaxisID);
+      double tarray[ilev*2];
+
+      if ( ncbndsID != -1 )
+        {
+          for ( int i = 0; i < mlev; ++i )
+            {
+              tarray[2*i  ] = vctptr[i];
+              tarray[2*i+1] = vctptr[i+1];
+            }
+          cdf_put_var_double(fileID, hyaiid, tarray);
+
+          for ( int i = 0; i < mlev; ++i )
+            {
+              tarray[2*i  ] = vctptr[ilev+i];
+              tarray[2*i+1] = vctptr[ilev+i+1];
+            }
+          cdf_put_var_double(fileID, hybiid, tarray);
+        }
+
+      for ( int i = 0; i < mlev; ++i )
+        tarray[i] = (vctptr[i] + vctptr[i+1]) * 0.5;
+      cdf_put_var_double(fileID, hyamid, tarray);
+
+      for ( int i = 0; i < mlev; ++i )
+        tarray[i] = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5;
+      cdf_put_var_double(fileID, hybmid, tarray);
+    }
+}
+
+struct attTxtTab { const char *txt; size_t txtLen; };
+
+static
+void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
+{
+  int fileID  = streamptr->fileID;
+
+  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+  cdf_def_dim(fileID, axisname, dimlen, dimID);
+  cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
+
+  {
+    static const char sname[] = "hybrid_sigma_pressure";
+    cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname);
+  }
+  {
+    static const char *attName[] = {
+      "long_name",
+      "formula",
+      "formula_terms"
+    };
+    enum { nAtt = sizeof (attName) / sizeof (attName[0]) };
+    static const char lname_m[] = "hybrid level at layer midpoints",
+      formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)",
+      fterms_m[] = "ap: hyam b: hybm ps: aps",
+      lname_i[] = "hybrid level at layer interfaces",
+      formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)",
+      fterms_i[] = "ap: hyai b: hybi ps: aps";
+    static const struct attTxtTab tab[2][nAtt] = {
+      {
+        { lname_i, sizeof (lname_i) - 1 },
+        { formula_i, sizeof (formula_i) - 1 },
+        { fterms_i, sizeof (fterms_i) - 1 }
+      },
+      {
+        { lname_m, sizeof (lname_m) - 1 },
+        { formula_m, sizeof (formula_m) - 1 },
+        { fterms_m, sizeof (fterms_m) - 1 }
+      }
+    };
+
+    size_t tabSelect = type == ZAXIS_HYBRID;
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, attName[i],
+                       tab[tabSelect][i].txtLen, tab[tabSelect][i].txt);
+  }
+
+  {
+    static const char units[] = "level";
+    cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units);
+  }
+  {
+    static const char direction[] = "down";
+    cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction);
+  }
+
+  cdf_enddef(fileID);
+  streamptr->ncmode = 2;
+
+  cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID));
+
+  cdf_def_vct_echam(streamptr, zaxisID);
+
+  if ( *dimID == UNDEFID )
+    {
+      if ( type == ZAXIS_HYBRID )
+        streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID;
+      else
+        streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID;
+    }
+}
+
+static
+void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
+{
+  char psname[CDI_MAX_NAME];
+  psname[0] = 0;
+  zaxisInqPsName(zaxisID, psname);
+  if ( psname[0] == 0 ) strcpy(psname, "ps");
+
+  int fileID = streamptr->fileID;
+  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+  strcpy(axisname, "lev");
+
+  cdf_def_dim(fileID, axisname, dimlen, dimID);
+  cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID,  &ncvarid);
+
+  {
+    static const char sname[] = "standard_name",
+      sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+      lname[] = "long_name",
+      lname_v[] = "hybrid sigma pressure coordinate",
+      formula[] = "formula",
+      formula_v[] = "p = ap + b*ps",
+      fterms[] = "formula_terms",
+      fterms_v[] = "ap: ap b: b ps: ",
+      units[] = "units",
+      units_v[] = "1",
+      axis[] = "axis",
+      axis_v[] = "Z",
+      direction[] = "positive",
+      direction_v[] = "down";
+    struct attTxtTab2 tab[] = {
+      { sname, sname_v, sizeof (sname_v) - 1 },
+      { lname, lname_v, sizeof (lname_v) - 1 },
+      { formula, formula_v, sizeof (formula_v) - 1 },
+      { fterms, fterms_v, sizeof (fterms_v) - 1 },
+      { units, units_v, sizeof (units_v) - 1 },
+      { axis, axis_v, sizeof (axis_v) - 1 },
+      { direction, direction_v, sizeof (direction_v) - 1 },
+    };
+    enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+    for (size_t i = 0; i < nAtt; ++i)
+      cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+  }
+
+  int ncbvarid = UNDEFID;
+  int nvdimID = UNDEFID;
+
+  double lbounds[dimlen], ubounds[dimlen], levels[dimlen];
+
+  zaxisInqLevels(zaxisID, levels);
+
+  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+    {
+      zaxisInqLbounds(zaxisID, lbounds);
+      zaxisInqUbounds(zaxisID, ubounds);
+    }
+  else
+    {
+      for ( size_t i = 0; i < dimlen; ++i ) lbounds[i] = levels[i];
+      for ( size_t i = 0; i < dimlen-1; ++i ) ubounds[i] = levels[i+1];
+      ubounds[dimlen-1] = levels[dimlen-1] + 1;
+    }
+
+  //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+    {
+      size_t nvertex = 2;
+      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+        cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
+
+      if ( nvdimID != UNDEFID )
+        {
+          size_t axisnameLen = strlen(axisname);
+          axisname[axisnameLen] = '_';
+          memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+          axisnameLen += sizeof (bndsName);
+          int dimIDs[2] = { *dimID, nvdimID };
+          cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
+          cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname);
+          {
+            static const char sname[] = "standard_name",
+              sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate",
+              formula[] = "formula",
+              formula_v[] = "p = ap + b*ps";
+            struct attTxtTab2 tab[] = {
+              { sname, sname_v, sizeof (sname_v) - 1 },
+              { formula, formula_v, sizeof (formula_v) - 1 },
+            };
+            enum { nAtt = sizeof (tab) / sizeof (tab[0]) };
+            for (size_t i = 0; i < nAtt; ++i)
+              cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal);
+          }
+          {
+            char txt[CDI_MAX_NAME];
+            size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname));
+            cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt);
+          }
+          {
+            static const char units[] = "1";
+            cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units);
+          }
+        }
+    }
+
+  cdf_enddef(fileID);
+  streamptr->ncmode = 2;
+
+  cdf_put_var_double(fileID, ncvarid, levels);
+
+  if ( ncbvarid != UNDEFID )
+    {
+      double zbounds[2*dimlen];
+      for ( size_t i = 0; i < dimlen; ++i )
+        {
+          zbounds[2*i  ] = lbounds[i];
+          zbounds[2*i+1] = ubounds[i];
+        }
+      cdf_put_var_double(fileID, ncbvarid, zbounds);
+    }
+
+  cdf_def_vct_cf(streamptr, zaxisID, *dimID, nvdimID);
+
+  if ( *dimID == UNDEFID )
+    {
+      if ( type == ZAXIS_HYBRID )
+        streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID;
+      else
+        streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID;
+    }
+}
+
+static
+void cdf_def_zaxis_hybrid(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname)
+{
+  if ( (!CDI_cmor_mode && cdiConvention == CDI_CONVENTION_ECHAM) || type == ZAXIS_HYBRID_HALF )
+    cdf_def_zaxis_hybrid_echam(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname);
+  else
+    cdf_def_zaxis_hybrid_cf(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname);
+}
+
+static
+void cdfDefZaxis(stream_t *streamptr, int zaxisID)
+{
+  /*  char zaxisname0[CDI_MAX_NAME]; */
+  char axisname[CDI_MAX_NAME];
+  int dimID = UNDEFID;
+  int dimIDs[2];
+  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
+  int nvdimID = UNDEFID;
+  int xtype = NC_DOUBLE;
+
+  if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+
+  int nzaxis = vlistNzaxis(vlistID);
+
+  size_t dimlen = (size_t)zaxisInqSize(zaxisID);
+  int type   = zaxisInqType(zaxisID);
+
+  int is_scalar = FALSE;
+  if ( dimlen == 1 )
+    {
+      is_scalar = zaxisInqScalar(zaxisID);
+      if ( !is_scalar && CDI_cmor_mode )
+        {
+          is_scalar = TRUE;
+          zaxisDefScalar(zaxisID);
+        }
+    }
+
+  int ndims = 1;
+  if ( is_scalar ) ndims = 0;
+
+  if ( dimlen == 1 )
+    switch (type)
+      {
+      case ZAXIS_SURFACE:
+      case ZAXIS_CLOUD_BASE:
+      case ZAXIS_CLOUD_TOP:
+      case ZAXIS_ISOTHERM_ZERO:
+      case ZAXIS_TOA:
+      case ZAXIS_SEA_BOTTOM:
+      case ZAXIS_ATMOSPHERE:
+      case ZAXIS_MEANSEA:
+      case ZAXIS_LAKE_BOTTOM:
+      case ZAXIS_SEDIMENT_BOTTOM:
+      case ZAXIS_SEDIMENT_BOTTOM_TA:
+      case ZAXIS_SEDIMENT_BOTTOM_TW:
+      case ZAXIS_MIX_LAYER:
+        return;
+      }
+
+  zaxisInqName(zaxisID, axisname);
+
+  if ( dimID == UNDEFID )
+    {
+      checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis);
+
+      char dimname[CDI_MAX_NAME+3];
+      dimname[0] = 0;
+      //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname);
+      if ( dimname[0] == 0 ) strcpy(dimname, axisname);
+
+      if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID);
+
+      if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
+        {
+          cdf_def_zaxis_hybrid(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, &dimID, axisname);
+        }
+      else
+        {
+          dimID = checkDimName(fileID, dimlen, dimname);
+
+          if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+          if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID);
+
+          cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
+
+          cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ);
+
+          {
+            int positive = zaxisInqPositive(zaxisID);
+            static const char positive_up[] = "up",
+              positive_down[] = "down";
+            static const struct attTxtTab tab[2] = {
+              { positive_up, sizeof (positive_up) - 1 },
+              { positive_down, sizeof (positive_down) - 1 },
+            };
+            if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN )
+              {
+                size_t select = positive == POSITIVE_DOWN;
+                cdf_put_att_text(fileID, ncvarid, "positive",
+                                 tab[select].txtLen, tab[select].txt);
+              }
+          }
+          cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z");
+
+	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+            {
+              size_t nvertex = 2;
+	      if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR )
+		cdf_def_dim(fileID, bndsName, nvertex, &nvdimID);
+
+	      if ( nvdimID != UNDEFID )
+		{
+                  size_t axisnameLen = strlen(axisname);
+                  axisname[axisnameLen] = '_';
+                  memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName));
+		  dimIDs[0] = dimID;
+		  dimIDs[ndims] = nvdimID;
+		  cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid);
+		  cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
+		}
+	    }
+
+          cdf_enddef(fileID);
+          streamptr->ncmode = 2;
+
+          cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID));
+
+          if ( ncbvarid != UNDEFID )
+	    {
+              double lbounds[dimlen], ubounds[dimlen], zbounds[2*dimlen];
+	      zaxisInqLbounds(zaxisID, lbounds);
+	      zaxisInqUbounds(zaxisID, ubounds);
+	      for ( size_t i = 0; i < dimlen; ++i )
+		{
+		  zbounds[2*i  ] = lbounds[i];
+		  zbounds[2*i+1] = ubounds[i];
+		}
+
+	      cdf_put_var_double(fileID, ncbvarid, zbounds);
+	    }
+
+          if ( ndims == 0 ) streamptr->nczvarID[zaxisindex] = ncvarid;
+        }
+    }
+
+  if ( dimID != UNDEFID )
+    streamptr->zaxisID[zaxisindex] = dimID;
+}
+
+static
+void cdfDefPole(stream_t *streamptr, int gridID)
+{
+  int ncvarid = UNDEFID;
+  static const char varname[] = "rotated_pole";
+  static const char mapname[] = "rotated_latitude_longitude";
+
+  int fileID  = streamptr->fileID;
+
+  double ypole = gridInqYpole(gridID);
+  double xpole = gridInqXpole(gridID);
+  double angle = gridInqAngle(gridID);
+
+  cdf_redef(fileID);
+
+  int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
+  if ( ncerrcode == NC_NOERR )
+    {
+      cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname);
+      cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
+      cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
+      if ( IS_NOT_EQUAL(angle, 0) )
+        cdf_put_att_double(fileID, ncvarid, "north_pole_grid_longitude", NC_DOUBLE, 1, &angle);
+    }
+
+  cdf_enddef(fileID);
+}
+
+static
+void cdf_def_mapping(stream_t *streamptr, int gridID)
+{
+  char mapping[CDI_MAX_NAME]; mapping[0] = 0;
+  cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
+  if ( mapping[0] )
+    {
+      char gmapvarname[CDI_MAX_NAME]; gmapvarname[0] = 0;
+      cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, gmapvarname);
+
+      int fileID = streamptr->fileID;
+      cdf_redef(fileID);
+
+      int ncvarid;
+      int ncerrcode = nc_def_var(fileID, gmapvarname, (nc_type) NC_INT, 0, NULL, &ncvarid);
+      if ( ncerrcode == NC_NOERR )
+        cdfDefineAttributes(gridID, CDI_GLOBAL, fileID, ncvarid);
+
+      cdf_enddef(fileID);
+
+      if ( ncerrcode == NC_NOERR )
+        {
+          int dummy = 1;
+          cdf_put_var_int(fileID, ncvarid, &dummy);
+        }
+    }
+}
+
+static
+void cdfDefMapping(stream_t *streamptr, int gridID)
+{
+  int ncvarid = UNDEFID;
+  int fileID  = streamptr->fileID;
+
+  if ( gridInqType(gridID) == GRID_SINUSOIDAL )
+    {
+      static const char varname[] = "Sinusoidal";
+      static const char mapname[] = "sinusoidal";
+
+      cdf_redef(fileID);
+
+      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
+      if ( ncerrcode == NC_NOERR )
+        {
+          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
+          /*
+          cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole);
+          cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole);
+          */
+        }
+
+      cdf_enddef(fileID);
+    }
+  else if ( gridInqType(gridID) == GRID_LAEA )
+    {
+      static const char varname[] = "Lambert_AEA";
+      static const char mapname[] = "lambert_azimuthal_equal_area";
+
+      cdf_redef(fileID);
+
+      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
+      if ( ncerrcode == NC_NOERR )
+        {
+          double a, lon_0, lat_0;
+
+          gridInqLaea(gridID, &a, &lon_0, &lat_0);
+
+          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
+          cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &a);
+          cdf_put_att_double(fileID, ncvarid, "longitude_of_projection_origin", NC_DOUBLE, 1, &lon_0);
+          cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0);
+        }
+
+      cdf_enddef(fileID);
+    }
+  else if ( gridInqType(gridID) == GRID_LCC2 )
+    {
+      static const char varname[] = "Lambert_CC";
+      static const char mapname[] = "lambert_conformal_conic";
+
+      cdf_redef(fileID);
+
+      int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid);
+      if ( ncerrcode == NC_NOERR )
+        {
+          double radius, lon_0, lat_0, lat_1, lat_2;
+
+          gridInqLcc2(gridID, &radius, &lon_0, &lat_0, &lat_1, &lat_2);
+
+          cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname);
+          if ( radius > 0 )
+            cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &radius);
+          cdf_put_att_double(fileID, ncvarid, "longitude_of_central_meridian", NC_DOUBLE, 1, &lon_0);
+          cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0);
+          if ( IS_EQUAL(lat_1, lat_2) )
+            cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 1, &lat_1);
+          else
+            {
+              double lat_1_2[2];
+              lat_1_2[0] = lat_1;
+              lat_1_2[1] = lat_2;
+              cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 2, lat_1_2);
+            }
+        }
+
+      cdf_enddef(fileID);
+    }
+}
+
+static
+void cdfDefGrid(stream_t *streamptr, int gridID, int gridindex)
+{
+  if ( streamptr->ncgrid[gridindex].xdimID != UNDEFID ) return;
+
+  int gridtype = gridInqType(gridID);
+  int size     = gridInqSize(gridID);
+
+  if ( CDI_Debug )
+    Message("gridtype = %d  size = %d", gridtype, size);
+
+  if ( gridtype == GRID_GAUSSIAN    ||
+       gridtype == GRID_LONLAT      ||
+       gridtype == GRID_PROJECTION  ||
+       gridtype == GRID_GENERIC )
+    {
+      if ( gridtype == GRID_GENERIC )
+        {
+          if ( size == 1 && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 )
+            {
+              /* no grid information */
+              streamptr->ncgrid[gridindex].gridID = gridID;
+            }
+          else
+            {
+              bool lx = false, ly = false;
+              if ( gridInqXsize(gridID) > 0 /*&& gridInqXvals(gridID, NULL) > 0*/ )
+                {
+                  cdfDefXaxis(streamptr, gridID, gridindex, 1);
+                  lx = true;
+                }
+
+              if ( gridInqYsize(gridID) > 0 /*&& gridInqYvals(gridID, NULL) > 0*/ )
+                {
+                  cdfDefYaxis(streamptr, gridID, gridindex, 1);
+                  ly = true;
+                }
+
+              if ( !lx && !ly ) cdfDefGdim(streamptr, gridID, gridindex);
+            }
+        }
+      else
+        {
+          int ndims = 1;
+          if ( gridtype == GRID_LONLAT && size == 1 && gridInqHasDims(gridID) == FALSE )
+            ndims = 0;
+
+          if ( gridInqXsize(gridID) > 0 ) cdfDefXaxis(streamptr, gridID, gridindex, ndims);
+          if ( gridInqYsize(gridID) > 0 ) cdfDefYaxis(streamptr, gridID, gridindex, ndims);
+
+          cdf_def_mapping(streamptr, gridID);
+        }
+
+      if ( gridIsRotated(gridID) ) cdfDefPole(streamptr, gridID);
+    }
+  else if ( gridtype == GRID_CURVILINEAR )
+    {
+      cdfDefCurvilinear(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_UNSTRUCTURED )
+    {
+      cdfDefUnstructured(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+    {
+      cdfDefRgrid(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_SPECTRAL )
+    {
+      cdfDefComplex(streamptr, gridID, gridindex);
+      cdfDefSP(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_FOURIER )
+    {
+      cdfDefComplex(streamptr, gridID, gridindex);
+      cdfDefFC(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_TRAJECTORY )
+    {
+      cdfDefTrajLon(streamptr, gridID, gridindex);
+      cdfDefTrajLat(streamptr, gridID, gridindex);
+    }
+  else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 )
+    {
+      cdfDefXaxis(streamptr, gridID, gridindex, 1);
+      cdfDefYaxis(streamptr, gridID, gridindex, 1);
+
+      cdfDefMapping(streamptr, gridID);
+    }
+  /*
+  else if ( gridtype == GRID_LCC )
+    {
+      cdfDefLcc(streamptr, gridID);
+    }
+  */
+  else
+    {
+      Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+    }
+}
+
+
+void cdfDefHistory(stream_t *streamptr, int size, const char *history)
+{
+  int ncid = streamptr->fileID;
+  cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history);
+}
+
+
+void cdfDefVars(stream_t *streamptr)
+{
+  int index = 0;
+  int vlistID = streamptr->vlistID;
+  if ( vlistID == UNDEFID )
+    Error("Internal problem! vlist undefined for streamptr %p", streamptr);
+
+  int ngrids = vlistNgrids(vlistID);
+  streamptr->ncgrid = (ncgrid_t*) Malloc(2*ngrids*sizeof(ncgrid_t));
+  for ( index = 0; index < 2*ngrids; ++index )
+    {
+      streamptr->ncgrid[index].gridID = UNDEFID;
+      streamptr->ncgrid[index].xdimID = UNDEFID;
+      streamptr->ncgrid[index].ydimID = UNDEFID;
+      streamptr->ncgrid[index].xvarID = UNDEFID;
+      streamptr->ncgrid[index].yvarID = UNDEFID;
+      streamptr->ncgrid[index].avarID = UNDEFID;
+    }
+
+  for ( index = 0; index < ngrids; ++index )
+    {
+      int gridID = vlistGrid(vlistID, index);
+      cdfDefGrid(streamptr, gridID, index);
+    }
+  index = ngrids-1;
+  for ( int i = 0; i < ngrids; ++i )
+    {
+      int gridID = vlistGrid(vlistID, i);
+      int projID = gridInqProj(gridID);
+      if ( projID != CDI_UNDEFID ) cdfDefGrid(streamptr, projID, ++index);
+    }
+
+  int nzaxis = vlistNzaxis(vlistID);
+  for ( int index = 0; index < nzaxis; ++index )
+    {
+      int zaxisID = vlistZaxis(vlistID, index);
+      if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID);
+    }
+}
+
+#endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/stream_cgribex.c b/src/stream_cgribex.c
index 474e33117898c8cba62ffbb28037e32b9cb394b8..3214b8309913d1c46ad0f9dead5a846be191187c 100644
--- a/src/stream_cgribex.c
+++ b/src/stream_cgribex.c
@@ -36,17 +36,21 @@ int cgribexGetGridType(int *isec2)
 
   switch (ISEC2_GridType)
     {
-    case  GRIB1_GTYPE_LATLON:     { if ( ISEC2_Reduced )      break; }
-    case  GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT;   break; }
-    case  GRIB1_GTYPE_LCC:        { gridtype = GRID_LCC;      break; }
+    case  GRIB1_GTYPE_LATLON:     { gridtype = GRID_LONLAT;     break; }
+#ifdef TEST_PROJECTION
+    case  GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_PROJECTION; break; }
+#else
+    case  GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT;     break; }
+#endif
+    case  GRIB1_GTYPE_LCC:        { gridtype = GRID_LCC;        break; }
     case  GRIB1_GTYPE_GAUSSIAN:   { if ( ISEC2_Reduced )
 	                              gridtype = GRID_GAUSSIAN_REDUCED;
                          	    else
 				      gridtype = GRID_GAUSSIAN;
           	                    break;
                                   }
-    case  GRIB1_GTYPE_SPECTRAL:   { gridtype = GRID_SPECTRAL; break; }
-    case  GRIB1_GTYPE_GME:        { gridtype = GRID_GME;      break; }
+    case  GRIB1_GTYPE_SPECTRAL:   { gridtype = GRID_SPECTRAL;   break; }
+    case  GRIB1_GTYPE_GME:        { gridtype = GRID_GME;        break; }
     }
 
   return gridtype;
@@ -55,9 +59,7 @@ int cgribexGetGridType(int *isec2)
 static
 bool cgribexGetIsRotated(int *isec2)
 {
-  bool isRotated = (ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT) ? true : false;
-
-  return isRotated;
+  return (ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT);
 }
 
 static
@@ -147,6 +149,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
 {
   bool compyinc = true;
   int gridtype = cgribexGetGridType(isec2);
+  int projtype = (gridtype == GRID_PROJECTION && cgribexGetIsRotated(isec2)) ? CDI_PROJ_RLL : CDI_UNDEFID;
 
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
     {
@@ -161,192 +164,178 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
 
   grid_init(grid);
   cdiGridTypeInit(grid, gridtype, 0);
-  switch (gridtype)
+
+  if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL )
     {
-    case GRID_LONLAT:
-    case GRID_GAUSSIAN:
+      if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
+        Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
+      grid->size  = ISEC4_NumValues;
+      grid->x.size = ISEC2_NumLon;
+      grid->y.size = ISEC2_NumLat;
+      if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar;
+      grid->x.inc  = 0;
+      grid->y.inc  = 0;
+      grid->x.flag = 0;
+      /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
       {
-	if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
-	  Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
-	grid->size  = ISEC4_NumValues;
-	grid->xsize = ISEC2_NumLon;
-	grid->ysize = ISEC2_NumLat;
-        if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar;
-	grid->xinc  = 0;
-	grid->yinc  = 0;
-	grid->xdef  = 0;
-	/* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
-	  {
-	    if ( grid->xsize > 1 )
-	      {
-                bool recompinc = true;
+        if ( grid->x.size > 1 )
+          {
+            bool recompinc = true;
 
-                if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
+            if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
 
-		if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+            if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+              {
+                if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->x.size-1))) <= 2 )
                   {
-                    if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->xsize-1))) <= 2 )
-                      {
-                        recompinc = false;
-                        grid->xinc = ISEC2_LonIncr * 0.001;
-                      }
+                    recompinc = false;
+                    grid->x.inc = ISEC2_LonIncr * 0.001;
                   }
+              }
 
-		/* recompute xinc if necessary */
-                if ( recompinc ) grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize-1);
-
-		/* correct xinc if necessary */
-		if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 )
-		  {
-		    double xinc = 360. / grid->xsize;
+            /* recompute xinc if necessary */
+            if ( recompinc ) grid->x.inc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->x.size-1);
 
-		    if ( fabs(grid->xinc-xinc) > 0.0 )
-		      {
-			grid->xinc = xinc;
-			if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
-		      }
-		  }
-	      }
-	    grid->xfirst = ISEC2_FirstLon * 0.001;
-	    grid->xlast  = ISEC2_LastLon  * 0.001;
-	    grid->xdef   = 2;
-	  }
-	grid->ydef  = 0;
-	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
-	  {
-	    if ( grid->ysize > 1 && compyinc )
-	      {
-                bool recompinc = true;
-		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+            /* correct xinc if necessary */
+            if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 )
+              {
+                double xinc = 360. / grid->x.size;
+                if ( fabs(grid->x.inc-xinc) > 0.0 )
                   {
-                    if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
-                      {
-                        recompinc = false;
-                        grid->yinc = ISEC2_LatIncr * 0.001;
-                      }
+                    grid->x.inc = xinc;
+                    if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc);
                   }
-
-		/* recompute yinc if necessary */
-                if ( recompinc ) grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
-	      }
-	    grid->yfirst = ISEC2_FirstLat * 0.001;
-	    grid->ylast  = ISEC2_LastLat  * 0.001;
-	    grid->ydef   = 2;
-	  }
-	break;
-      }
-    case GRID_GAUSSIAN_REDUCED:
-      {
-        grid->np      = ISEC2_NumPar;
-	grid->size    = ISEC4_NumValues;
-        grid->rowlon  = ISEC2_RowLonPtr;
-	grid->nrowlon = ISEC2_NumLat;
-	grid->ysize   = ISEC2_NumLat;
-	grid->xinc    = 0;
-	grid->yinc    = 0;
-	grid->xdef    = 0;
-	/* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
-	  {
-	    if ( grid->xsize > 1 )
-	      {
-                if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
-
-		if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
-		  grid->xinc = ISEC2_LonIncr * 0.001;
-		else
-		  grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize - 1);
-	      }
-	    grid->xfirst = ISEC2_FirstLon * 0.001;
-	    grid->xlast  = ISEC2_LastLon  * 0.001;
-	    grid->xdef   = 2;
-	  }
-	grid->ydef  = 0;
-	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
-	  {
-	    if ( grid->ysize > 1 )
-	      {
-		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
-		  grid->yinc = ISEC2_LatIncr * 0.001;
-		else
-		  grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
-	      }
-	    grid->yfirst = ISEC2_FirstLat * 0.001;
-	    grid->ylast  = ISEC2_LastLat  * 0.001;
-	    grid->ydef   = 2;
-	  }
-	break;
+              }
+          }
+        grid->x.first = ISEC2_FirstLon * 0.001;
+        grid->x.last  = ISEC2_LastLon  * 0.001;
+        grid->x.flag  = 2;
       }
-    case GRID_LCC:
+      grid->y.flag = 0;
+      /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
       {
-	if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
-	  Error("numberOfPoints (%d) and gridSize (%d) differ!",
-		ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
-
-	grid->size  = ISEC4_NumValues;
-	grid->xsize = ISEC2_NumLon;
-	grid->ysize = ISEC2_NumLat;
-
-	grid->lcc_xinc      = ISEC2_Lambert_dx;
-	grid->lcc_yinc      = ISEC2_Lambert_dy;
-	grid->lcc_originLon = ISEC2_FirstLon * 0.001;
-	grid->lcc_originLat = ISEC2_FirstLat * 0.001;
-	grid->lcc_lonParY   = ISEC2_Lambert_Lov * 0.001;
-	grid->lcc_lat1      = ISEC2_Lambert_LatS1 * 0.001;
-	grid->lcc_lat2      = ISEC2_Lambert_LatS2 * 0.001;
-	grid->lcc_projflag  = ISEC2_Lambert_ProjFlag;
-	grid->lcc_scanflag  = ISEC2_ScanFlag;
-
-	grid->xdef   = 0;
-	grid->ydef   = 0;
+        if ( grid->y.size > 1 && compyinc )
+          {
+            bool recompinc = true;
+            if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+              {
+                if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->y.size-1))) <= 2 )
+                  {
+                    recompinc = false;
+                    grid->y.inc = ISEC2_LatIncr * 0.001;
+                  }
+              }
 
-	break;
+            /* recompute yinc if necessary */
+            if ( recompinc ) grid->y.inc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->y.size - 1);
+          }
+        grid->y.first = ISEC2_FirstLat * 0.001;
+        grid->y.last  = ISEC2_LastLat  * 0.001;
+        grid->y.flag  = 2;
       }
-    case GRID_SPECTRAL:
+    }
+  else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+    {
+      grid->np      = ISEC2_NumPar;
+      grid->size    = ISEC4_NumValues;
+      grid->rowlon  = ISEC2_RowLonPtr;
+      grid->nrowlon = ISEC2_NumLat;
+      grid->y.size  = ISEC2_NumLat;
+      grid->x.inc   = 0;
+      grid->y.inc   = 0;
+      grid->x.flag  = 0;
+      /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
       {
-	grid->size  = ISEC4_NumValues;
-	grid->trunc = ISEC2_PentaJ;
-	if ( ISEC2_RepMode == 2 )
-	  grid->lcomplex = 1;
-	else
-	  grid->lcomplex = 0;
+        if ( grid->x.size > 1 )
+          {
+            if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
 
-	break;
-      }
-    case GRID_GME:
-      {
-	grid->size  = ISEC4_NumValues;
-	grid->nd    = ISEC2_GME_ND;
-	grid->ni    = ISEC2_GME_NI;
-	grid->ni2   = ISEC2_GME_NI2;
-	grid->ni3   = ISEC2_GME_NI3;
-	break;
-      }
-    case GRID_GENERIC:
-      {
-	grid->size  = ISEC4_NumValues;
-	grid->xsize = 0;
-	grid->ysize = 0;
-	break;
+            if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+              grid->x.inc = ISEC2_LonIncr * 0.001;
+            else
+              grid->x.inc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->x.size - 1);
+          }
+        grid->x.first = ISEC2_FirstLon * 0.001;
+        grid->x.last  = ISEC2_LastLon  * 0.001;
+        grid->x.flag  = 2;
       }
-    default:
+      grid->y.flag = 0;
+      /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
       {
-	Error("Unsupported grid type: %s", gridNamePtr(gridtype));
-	break;
+        if ( grid->y.size > 1 )
+          {
+            if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+              grid->y.inc = ISEC2_LatIncr * 0.001;
+            else
+              grid->y.inc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->y.size - 1);
+          }
+        grid->y.first = ISEC2_FirstLat * 0.001;
+        grid->y.last  = ISEC2_LastLat  * 0.001;
+        grid->y.flag  = 2;
       }
     }
+  else if ( gridtype == GRID_LCC )
+    {
+      if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
+        Error("numberOfPoints (%d) and gridSize (%d) differ!",
+              ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
+
+      grid->size  = ISEC4_NumValues;
+      grid->x.size = ISEC2_NumLon;
+      grid->y.size = ISEC2_NumLat;
+
+      grid->lcc.xinc      = ISEC2_Lambert_dx;
+      grid->lcc.yinc      = ISEC2_Lambert_dy;
+      grid->lcc.originLon = ISEC2_FirstLon * 0.001;
+      grid->lcc.originLat = ISEC2_FirstLat * 0.001;
+      grid->lcc.lonParY   = ISEC2_Lambert_Lov * 0.001;
+      grid->lcc.lat1      = ISEC2_Lambert_LatS1 * 0.001;
+      grid->lcc.lat2      = ISEC2_Lambert_LatS2 * 0.001;
+      grid->lcc.projflag  = ISEC2_Lambert_ProjFlag;
+      grid->lcc.scanflag  = ISEC2_ScanFlag;
+
+      grid->x.flag = 0;
+      grid->y.flag = 0;
+    }
+  else if ( gridtype == GRID_SPECTRAL )
+    {
+      grid->size  = ISEC4_NumValues;
+      grid->trunc = ISEC2_PentaJ;
+      if ( ISEC2_RepMode == 2 )
+        grid->lcomplex = 1;
+      else
+        grid->lcomplex = 0;
+    }
+  else if ( gridtype == GRID_GME )
+    {
+      grid->size  = ISEC4_NumValues;
+      grid->gme.nd    = ISEC2_GME_ND;
+      grid->gme.ni    = ISEC2_GME_NI;
+      grid->gme.ni2   = ISEC2_GME_NI2;
+      grid->gme.ni3   = ISEC2_GME_NI3;
+    }
+  else if ( gridtype == GRID_GENERIC )
+    {
+      grid->size  = ISEC4_NumValues;
+      grid->x.size = 0;
+      grid->y.size = 0;
+    }
+  else
+    {
+      Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+    }
 
   grid->isRotated = FALSE;
   if ( cgribexGetIsRotated(isec2) )
     {
       grid->isRotated = TRUE;
-      grid->ypole     = - ISEC2_LatSP*0.001;
-      grid->xpole     =   ISEC2_LonSP*0.001 - 180;
-      grid->angle     = - FSEC2_RotAngle;
+      grid->rll.xpole =   ISEC2_LonSP*0.001 - 180;
+      grid->rll.ypole = - ISEC2_LatSP*0.001;
+      grid->rll.angle = - FSEC2_RotAngle;
     }
 
-  grid->xvals = NULL;
-  grid->yvals = NULL;
-  grid->type  = gridtype;
+  grid->type = gridtype;
+  grid->projtype = projtype;
 }
 
 static
@@ -380,7 +369,7 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
   grid_t *gridptr = (grid_t*) Malloc(sizeof(*gridptr));
   cgribexGetGrid(streamptr, isec2, fsec2, isec4, gridptr, iret);
 
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, gridptr, 0);
+  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, gridptr, 0);
   int gridID = gridAdded.Id;
   if ( gridAdded.isNew )
     {
@@ -391,6 +380,13 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
           gridptr->rowlon = (int*) Malloc(nrowlon * sizeof(int));
           memcpy(gridptr->rowlon, rowlon, nrowlon * sizeof(int));
         }
+      else if ( gridptr->projtype == CDI_PROJ_RLL )
+        {
+          double xpole =   ISEC2_LonSP*0.001 - 180;
+          double ypole = - ISEC2_LatSP*0.001;
+          double angle = - FSEC2_RotAngle;
+          gridDefProjParamRLL(gridID, xpole, ypole, angle);
+        }
     }
   else
     Free(gridptr);
@@ -659,10 +655,10 @@ int cgribexScanTimestep1(stream_t * streamptr)
       rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
       if ( rstatus ) break;
 
-      comptype = COMPRESS_NONE;
+      comptype = CDI_COMPRESS_NONE;
       if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
 	{
-	  comptype = COMPRESS_SZIP;
+	  comptype = CDI_COMPRESS_SZIP;
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
 	  if ( buffersize < (size_t)unzipsize )
 	    {
@@ -1616,8 +1612,8 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
 static
 void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID)
 {
+  bool lrotated = false;
   bool lcurvi = false;
-  static bool lwarning = true;
 
   memset(isec2, 0, 16*sizeof(int));
 
@@ -1655,6 +1651,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
     }
   else if ( gridtype == GRID_CURVILINEAR )
     {
+      static bool lwarning = true;
       if ( lwarning && gridInqSize(gridID) > 1 )
 	{
 	  lwarning = false;
@@ -1664,6 +1661,12 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
       lcurvi = true;
     }
 
+  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+    {
+      gridtype = GRID_LONLAT;
+      lrotated = true;
+    }
+
   ISEC2_Reduced  = FALSE;
   ISEC2_ScanFlag = 0;
 
@@ -1680,7 +1683,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 
 	if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
           ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN;
-        else if ( gridtype == GRID_LONLAT && isRotated )
+        else if ( gridtype == GRID_LONLAT && (isRotated || lrotated) )
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT;
 	else
 	  ISEC2_GridType = GRIB1_GTYPE_LATLON;
@@ -1696,25 +1699,19 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	  }
 	else
 	  {
-	    if ( nlon == 0 )
-	      {
-		nlon = 1;
-	      }
+	    if ( nlon == 0 ) nlon = 1;
 	    else
 	      {
-		xfirst = gridInqXval(gridID,      0);
+		xfirst = gridInqXval(gridID, 0);
                 xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
 		xinc   = gridInqXinc(gridID);
 	      }
 	  }
 
-	if ( nlat == 0 )
-	  {
-	    nlat = 1;
-	  }
+	if ( nlat == 0 ) nlat = 1;
 	else
 	  {
-	    yfirst = gridInqYval(gridID,      0);
+	    yfirst = gridInqYval(gridID, 0);
             ylast  = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1);
 	    yinc   = fabs(gridInqYinc(gridID));
 	  }
@@ -1756,14 +1753,23 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 
         ISEC2_ResFlag = ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) ? 0 : 128;
 
-	if ( isRotated )
-	  {
-	    ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000);
-	    ISEC2_LonSP =   (int)lround((gridInqXpole(gridID) + 180) * 1000);
-            double angle = gridInqAngle(gridID);
+	if ( isRotated || lrotated )
+          {
+            double xpole = 0, ypole = 0, angle = 0;
+            if ( isRotated )
+              {
+                xpole = gridInqXpole(gridID);
+                ypole = gridInqYpole(gridID);
+                angle = gridInqAngle(gridID);
+              }
+            else
+              gridInqProjParamRLL(gridID, &xpole, &ypole, &angle);
+
+	    ISEC2_LatSP = - (int)lround(ypole * 1000);
+	    ISEC2_LonSP =   (int)lround((xpole + 180) * 1000);
             if ( fabs(angle) > 0 ) angle = -angle;
             FSEC2_RotAngle = angle;
-	  }
+          }
 
 	/* East -> West */
 	if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
@@ -1849,6 +1855,14 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
     }
 }
 
+static
+void isec1DefLevel(int *isec1, int leveltype, int level1, int level2)
+{
+  ISEC1_LevelType = leveltype;
+  ISEC1_Level1    = level1;
+  ISEC1_Level2    = level2;
+}
+
 static
 void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int levelID)
 {
@@ -1861,8 +1875,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
   if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
     {
       Message("Changed zaxis type from %s to %s",
-	      zaxisNamePtr(zaxistype),
-	      zaxisNamePtr(ZAXIS_PRESSURE));
+	      zaxisNamePtr(zaxistype), zaxisNamePtr(ZAXIS_PRESSURE));
       zaxistype = ZAXIS_PRESSURE;
       zaxisChangeType(zaxisID, zaxistype);
       zaxisDefUnits(zaxisID, "Pa");
@@ -1880,9 +1893,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_DEPTH_BELOW_SEA:
     case ZAXIS_ISENTROPIC:
       {
-        ISEC1_LevelType = grib_ltype;
-	ISEC1_Level1    = (int) (zaxisInqLevel(zaxisID, levelID));
-	ISEC1_Level2    = 0;
+        isec1DefLevel(isec1, grib_ltype, (int) zaxisInqLevel(zaxisID, levelID), 0);
 	break;
       }
     case ZAXIS_CLOUD_BASE:
@@ -1892,26 +1903,17 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_SEA_BOTTOM:
     case ZAXIS_ATMOSPHERE:
       {
-        ISEC1_LevelType = grib_ltype;
-	ISEC1_Level1    = 0;
-	ISEC1_Level2    = 0;
+        isec1DefLevel(isec1, grib_ltype, 0, 0);
 	break;
       }
     case ZAXIS_HYBRID:
     case ZAXIS_HYBRID_HALF:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_HYBRID_LAYER;
-	    ISEC1_Level1    = (int) (zaxisInqLbound(zaxisID, levelID));
-	    ISEC1_Level2    = (int) (zaxisInqUbound(zaxisID, levelID));
-	  }
+          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID),
+                        (int)zaxisInqUbound(zaxisID, levelID));
 	else
-	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_HYBRID;
-	    ISEC1_Level1    = (int) (zaxisInqLevel(zaxisID, levelID));
-	    ISEC1_Level2    = 0;
-	  }
+          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID, (int) zaxisInqLevel(zaxisID, levelID), 0);
 
 	int vctsize = zaxisInqVctSize(zaxisID);
 	if ( vctsize > 255 )
@@ -1933,8 +1935,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_PRESSURE:
       {
 	level = zaxisInqLevel(zaxisID, levelID);
-	if ( level < 0 )
-	  Warning("Pressure level of %f Pa is below zero!", level);
+	if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level);
 
 	char units[128];
 	zaxisInqUnits(zaxisID, units);
@@ -1942,16 +1943,11 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 
 	double dum;
 	if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
-	  {
-	    grib_ltype = GRIB1_LTYPE_99;
-	  }
+          grib_ltype = GRIB1_LTYPE_99;
 	else
-	  {
-	    level = level/100;
-	  }
-        ISEC1_LevelType = grib_ltype;
-        ISEC1_Level1    = (int) level;
-        ISEC1_Level2    = 0;
+          level = level/100;
+
+        isec1DefLevel(isec1, grib_ltype, (int) level, 0);
 	break;
       }
     case ZAXIS_HEIGHT:
@@ -1967,26 +1963,16 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
             else if ( units[0] == 'k' ) level *= 1000;
           }
 
-	ISEC1_LevelType = grib_ltype;
-	ISEC1_Level1    = (int) level;
-	ISEC1_Level2    = 0;
-
+        isec1DefLevel(isec1, grib_ltype, (int) level, 0);
 	break;
       }
     case ZAXIS_SIGMA:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_SIGMA_LAYER;
-	    ISEC1_Level1    = (int) zaxisInqLbound(zaxisID, levelID);
-	    ISEC1_Level2    = (int) zaxisInqUbound(zaxisID, levelID);
-	  }
+          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA_LAYER, (int) zaxisInqLbound(zaxisID, levelID),
+                        (int) zaxisInqUbound(zaxisID, levelID));
 	else
-	  {
-            ISEC1_LevelType = GRIB1_LTYPE_SIGMA;
-            ISEC1_Level1    = (int) zaxisInqLevel(zaxisID, levelID);
-            ISEC1_Level2    = 0;
-          }
+          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA, (int) zaxisInqLevel(zaxisID, levelID), 0);
 
 	break;
       }
@@ -2002,26 +1988,16 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
         else                                           factor = 100; // meter
 
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH_LAYER;
-	    ISEC1_Level1    = (int) (factor*zaxisInqLbound(zaxisID, levelID));
-	    ISEC1_Level2    = (int) (factor*zaxisInqUbound(zaxisID, levelID));
-	  }
+          isec1DefLevel(isec1, GRIB1_LTYPE_LANDDEPTH_LAYER, (int) (factor*zaxisInqLbound(zaxisID, levelID)),
+                        (int) (factor*zaxisInqUbound(zaxisID, levelID)));
 	else
-	  {
-	    ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH;
-	    ISEC1_Level1    = (int) (factor*zaxisInqLevel(zaxisID, levelID));
-	    ISEC1_Level2    = 0;
-	  }
+          isec1DefLevel(isec1, GRIB1_LTYPE_LANDDEPTH, (int) (factor*zaxisInqLevel(zaxisID, levelID)), 0);
 
 	break;
       }
     case ZAXIS_GENERIC:
       {
-	ISEC1_LevelType = ltype;
-	ISEC1_Level1    = (int) zaxisInqLevel(zaxisID, levelID);
-	ISEC1_Level2    = 0;
-
+        isec1DefLevel(isec1, ltype, (int) zaxisInqLevel(zaxisID, levelID), 0);
 	break;
       }
     default:
diff --git a/src/stream_ext.c b/src/stream_ext.c
index 048de7007e88ab6a5d1eca7f465a1ba76834707d..54d59f3fc29cc2d8c44a073d954419c3d4feb5c4 100644
--- a/src/stream_ext.c
+++ b/src/stream_ext.c
@@ -13,18 +13,16 @@
 #include "cdi.h"
 #include "cdi_int.h"
 #include "stream_ext.h"
-#include "stream_fcommon.h"
 #include "varscan.h"
 #include "datetime.h"
 #include "extra.h"
 #include "vlist.h"
+#include "exse.h"
 
 
 #undef  UNDEFID
 #define UNDEFID  CDI_UNDEFID
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
 
 #if defined (HAVE_LIBEXTRA)
 
@@ -40,17 +38,11 @@ int extInqDatatype(int prec, int number)
   int datatype;
 
   if ( number == 2 )
-    {
-      if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_CPX64;
-      else                            datatype = DATATYPE_CPX32;
-    }
+    datatype = (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_CPX64 : DATATYPE_CPX32;
   else
-    {
-      if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
-      else                            datatype = DATATYPE_FLT32;
-    }
+    datatype = (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32;
 
-  return (datatype);
+  return datatype;
 }
 
 static
@@ -61,15 +53,9 @@ void extDefDatatype(int datatype, int *prec, int *number)
        datatype != DATATYPE_CPX32 && datatype != DATATYPE_CPX64 )
     datatype = DATATYPE_FLT32;
 
-  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
-    *number = 2;
-  else
-    *number = 1;
+  *number = (datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64) ? 2 : 1;
 
-  if ( datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64 )
-    *prec = DOUBLE_PRECISION;
-  else 
-    *prec = SINGLE_PRECISION;
+  *prec = (datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
 }
 
 /* not used
@@ -90,7 +76,7 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
   *levelID = -1;
 
   status = extRead(fileID, extp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 ) return 0;
 
   extInqHeader(extp, header);
 
@@ -105,49 +91,40 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
 
   *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
 
-  return (1);
+  return 1;
 }
 */
 
 void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
-  int vlistID, fileID;
-  int status;
-  int recID, vrecID, tsID;
-  off_t recpos;
-  int header[4];
-  int varID, gridID;
-  int i, size;
-  double missval;
-  void *extp = streamptr->record->exsep;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-  tsID    = streamptr->curTsID;
-  vrecID  = streamptr->tsteps[tsID].curRecID;
-  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr->tsteps[tsID].records[recID].position;
-  varID   = streamptr->tsteps[tsID].records[recID].varID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+  int tsID    = streamptr->curTsID;
+  int vrecID  = streamptr->tsteps[tsID].curRecID;
+  int recID   = streamptr->tsteps[tsID].recIDs[vrecID];
+  int varID   = streamptr->tsteps[tsID].records[recID].varID;
+  off_t recpos = streamptr->tsteps[tsID].records[recID].position;
 
   fileSetPos(fileID, recpos, SEEK_SET);
 
-  status = extRead(fileID, extp);
-  if ( status != 0 )
-    Error("Failed to read EXTRA record");
+  void *extp = streamptr->record->exsep;
+  int status = extRead(fileID, extp);
+  if ( status != 0 ) Error("Failed to read EXTRA record");
 
+  int header[4];
   extInqHeader(extp, header);
   extInqDataDP(extp, data);
 
-  missval = vlistInqVarMissval(vlistID, varID);
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  size    = gridInqSize(gridID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int size    = gridInqSize(gridID);
 
   streamptr->numvals += size;
 
   *nmiss = 0;
   if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
     {
-      for ( i = 0; i < size; i++ )
+      for ( int i = 0; i < size; i++ )
 	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
 	  {
 	    data[i] = missval;
@@ -156,7 +133,7 @@ void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
     }
   else
     {
-      for ( i = 0; i < 2*size; i+=2 )
+      for ( int i = 0; i < 2*size; i+=2 )
 	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
 	  {
 	    data[i] = missval;
@@ -174,21 +151,18 @@ void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 
 void extDefRecord(stream_t *streamptr)
 {
-  int gridID;
-  int header[4];
   int pdis, pcat, pnum;
-  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
-
-  gridID   = streamptr->record->gridID;
-
   cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
+
+  int header[4];
   header[0] = streamptr->record->date;
   header[1] = pnum;
   header[2] = streamptr->record->level;
+  int gridID = streamptr->record->gridID;
   header[3] = gridInqSize(gridID);
 
+  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
   extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
-
   extDefHeader(extp, header);
 }
 
@@ -219,11 +193,9 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
   grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
   grid_init(grid);
   cdiGridTypeInit(grid, GRID_GENERIC, xysize);
-  grid->xsize = xysize;
-  grid->ysize = 0;
-  grid->xvals = NULL;
-  grid->yvals = NULL;
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+  grid->x.size = xysize;
+  grid->y.size = 0;
+  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
   int gridID = gridAdded.Id;
   if (!gridAdded.isNew) Free(grid);
   /*
@@ -243,46 +215,36 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
   streamptr->nrecs++;
 
   if ( CDI_Debug )
-    Message("varID = %d gridID = %d levelID = %d",
-	    varID, gridID, levelID);
+    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
 }
 
 static
 void extScanTimestep1(stream_t *streamptr)
 {
   int header[4];
-  int status;
-  int fileID;
-  int rxysize = 0;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   DateTime datetime0 = { LONG_MIN, LONG_MIN };
-  int tsID;
   int varID;
+  off_t recpos = 0;
   long recsize;
-  off_t recpos;
-  int nrecords, nrecs, recID;
-  int taxisID = -1;
-  taxis_t *taxis;
-  int vlistID;
+  int recID;
   extcompvar_t compVar, compVar0;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
 
   streamptr->curTsID = 0;
 
-  tsID  = tstepsNewEntry(streamptr);
-  taxis = &streamptr->tsteps[tsID].taxis;
+  int tsID  = tstepsNewEntry(streamptr);
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   if ( tsID != 0 )
     Error("Internal problem! tstepsNewEntry returns %d", tsID);
 
-  fileID = streamptr->fileID;
+  int fileID = streamptr->fileID;
 
-  nrecs = 0;
+  int nrecs = 0;
   while ( TRUE )
     {
       recpos = fileGetPos(fileID);
-      status = extRead(fileID, extp);
+      int status = extRead(fileID, extp);
       if ( status != 0 )
 	{
 	  streamptr->ntsteps = 1;
@@ -292,13 +254,13 @@ void extScanTimestep1(stream_t *streamptr)
 
       extInqHeader(extp, header);
 
-      vdate   = header[0];
-      vtime   = 0;
-      rcode   = header[1];
-      rlevel  = header[2];
-      rxysize = header[3];
+      int vdate   = header[0];
+      int vtime   = 0;
+      int rcode   = header[1];
+      int rlevel  = header[2];
+      int rxysize = header[3];
 
-      param = cdiEncodeParam(rcode, 255, 255);
+      int param = cdiEncodeParam(rcode, 255, 255);
 
       if ( nrecs == 0 )
 	{
@@ -334,17 +296,17 @@ void extScanTimestep1(stream_t *streamptr)
 
   cdi_generate_vars(streamptr);
 
-  taxisID = taxisCreate(TAXIS_ABSOLUTE);
+  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
   taxis->vdate = (int)datetime0.date;
   taxis->vtime = (int)datetime0.time;
 
-  vlistID = streamptr->vlistID;
+  int vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
 
   vlist_check_contents(vlistID);
 
-  nrecords = streamptr->tsteps[0].nallrecs;
+  int nrecords = streamptr->tsteps[0].nallrecs;
   if ( nrecords < streamptr->tsteps[0].recordSize )
     {
       streamptr->tsteps[0].recordSize = nrecords;
@@ -384,43 +346,33 @@ static
 int extScanTimestep2(stream_t *streamptr)
 {
   int header[4];
-  int status;
-  int fileID;
-  // int rxysize = 0;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  int tsID;
   int varID;
   off_t recpos = 0;
-  int nrecords, nrecs, recID, rindex;
-  int nextstep;
-  taxis_t *taxis;
-  int vlistID;
   extcompvar_t compVar, compVar0;
   void *extp = streamptr->record->exsep;
 
   streamptr->curTsID = 1;
 
-  fileID  = streamptr->fileID;
-  vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
 
-  tsID = streamptr->rtsteps;
+  int tsID = streamptr->rtsteps;
   if ( tsID != 1 )
     Error("Internal problem! unexpected timestep %d", tsID+1);
 
-  taxis = &streamptr->tsteps[tsID].taxis;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
   cdi_create_records(streamptr, tsID);
 
-  nrecords = streamptr->tsteps[0].nallrecs;
+  int nrecords = streamptr->tsteps[0].nallrecs;
   streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
 
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
       varID = streamptr->tsteps[0].records[recID].varID;
       streamptr->tsteps[tsID].records[recID].position =
@@ -429,10 +381,10 @@ int extScanTimestep2(stream_t *streamptr)
 	streamptr->tsteps[0].records[recID].size;
     }
 
-  for ( rindex = 0; rindex <= nrecords; rindex++ )
+  for ( int rindex = 0; rindex <= nrecords; rindex++ )
     {
       recpos = fileGetPos(fileID);
-      status = extRead(fileID, extp);
+      int status = extRead(fileID, extp);
       if ( status != 0 )
 	{
 	  streamptr->ntsteps = 2;
@@ -442,13 +394,13 @@ int extScanTimestep2(stream_t *streamptr)
 
       extInqHeader(extp, header);
 
-      vdate  = header[0];
-      vtime  = 0;
-      rcode  = header[1];
-      rlevel = header[2];
+      int vdate  = header[0];
+      int vtime  = 0;
+      int rcode  = header[1];
+      int rlevel = header[2];
       // rxysize = header[3];
 
-      param = cdiEncodeParam(rcode, 255, 255);
+      int param = cdiEncodeParam(rcode, 255, 255);
 
       if ( rindex == 0 )
 	{
@@ -459,7 +411,8 @@ int extScanTimestep2(stream_t *streamptr)
 
       compVar.param = param;
       compVar.level = rlevel;
-      nextstep = FALSE;
+      bool nextstep = false;
+      int recID;
       for ( recID = 0; recID < nrecords; recID++ )
 	{
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
@@ -469,7 +422,7 @@ int extScanTimestep2(stream_t *streamptr)
 	    {
 	      if ( streamptr->tsteps[tsID].records[recID].used )
 		{
-		  nextstep = TRUE;
+		  nextstep = true;
 		}
 	      else
 		{
@@ -482,7 +435,7 @@ int extScanTimestep2(stream_t *streamptr)
       if ( recID == nrecords )
 	{
 	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( nextstep ) break;
@@ -501,14 +454,14 @@ int extScanTimestep2(stream_t *streamptr)
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
     }
 
-  nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  int nrecs = 0;
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
       if ( ! streamptr->tsteps[tsID].records[recID].used )
 	{
@@ -534,40 +487,32 @@ int extScanTimestep2(stream_t *streamptr)
       streamptr->tsteps[tsID].position = recpos;
     }
 
-  return (0);
+  return 0;
 }
 
 
 int extInqContents(stream_t *streamptr)
 {
-  int fileID;
-  int status = 0;
-
-  fileID = streamptr->fileID;
-
   streamptr->curTsID = 0;
 
   extScanTimestep1(streamptr);
 
+  int status = 0;
   if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamptr);
 
+  int fileID = streamptr->fileID;
   fileSetPos(fileID, 0, SEEK_SET);
 
-  return (status);
+  return status;
 }
 
 static
 long extScanTimestep(stream_t *streamptr)
 {
   int header[4];
-  int status;
-  int fileID;
-  // int rxysize = 0;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   off_t recpos = 0;
   int recID;
-  int rindex, nrecs = 0;
+  int nrecs = 0;
   extcompvar_t compVar, compVar0;
   void *extp = streamptr->record->exsep;
   /*
@@ -594,14 +539,14 @@ long extScanTimestep(stream_t *streamptr)
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
-      fileID = streamptr->fileID;
+      int fileID = streamptr->fileID;
 
       fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
-      for ( rindex = 0; rindex <= nrecs; rindex++ )
+      for ( int rindex = 0; rindex <= nrecs; rindex++ )
 	{
 	  recpos = fileGetPos(fileID);
-	  status = extRead(fileID, extp);
+	  int status = extRead(fileID, extp);
 	  if ( status != 0 )
 	    {
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
@@ -611,13 +556,13 @@ long extScanTimestep(stream_t *streamptr)
 
 	  extInqHeader(extp, header);
 
-	  vdate  = header[0];
-	  vtime  = 0;
-	  rcode  = header[1];
-	  rlevel = header[2];
+	  int vdate  = header[0];
+	  int vtime  = 0;
+	  int rcode  = header[1];
+	  int rlevel = header[2];
 	  // rxysize = header[3];
 
-	  param = cdiEncodeParam(rcode, 255, 255);
+	  int param = cdiEncodeParam(rcode, 255, 255);
 
 	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
 	  if ( rindex == nrecs ) continue;
@@ -673,131 +618,54 @@ long extScanTimestep(stream_t *streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  return (streamptr->ntsteps);
+  return streamptr->ntsteps;
 }
 
 
 int extInqTimestep(stream_t *streamptr, int tsID)
 {
-  int nrecs;
-  long ntsteps;
-
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
 
   if ( CDI_Debug )
     Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
 
-  ntsteps = UNDEFID;
+  long ntsteps = UNDEFID;
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = extScanTimestep(streamptr);
 
-  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
-    {
-      nrecs = 0;
-    }
-  else
+  int nrecs = 0;
+  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) )
     {
       streamptr->curTsID = tsID;
       nrecs = streamptr->tsteps[tsID].nrecs;
     }
 
-  return (nrecs);
-}
-
-
-void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
-{
-  int vlistID, fileID;
-  int levID, nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int header[4];
-  int tsid;
-  int recID;
-  int i;
-  double missval;
-  void *extp = streamptr->record->exsep;
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
-  currentfilepos = fileGetPos(fileID);
-
-  for (levID = 0; levID < nlevs; levID++)
-    {
-      /* NOTE: tiles are not supported here! */
-      recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-      recpos = streamptr->tsteps[tsid].records[recID].position;
-      fileSetPos(fileID, recpos, SEEK_SET);
-      extRead(fileID, extp);
-      extInqHeader(extp, header);
-      extInqDataDP(extp, &data[levID*gridsize]);
-    }
-  fileSetPos(fileID, currentfilepos, SEEK_SET);
-
-  *nmiss = 0;
-  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
-    {
-      for ( i = 0; i < nlevs*gridsize; i++ )
-	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
-	  {
-	    data[i] = missval;
-	    (*nmiss)++;
-	  }
-    }
-  else
-    {
-      for ( i = 0; i < 2*nlevs*gridsize; i+=2 )
-	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
-	  {
-	    data[i] = missval;
-	    (*nmiss)++;
-	  }
-    }
+  return nrecs;
 }
 
 
 void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
 {
-  int vlistID, fileID;
-  int nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int header[4];
-  int tsid;
-  int recID;
-  int i;
-  double missval;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
+
   void *extp = streamptr->record->exsep;
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
   /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
+  int tsid     = streamptr->curTsID;
 
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d",
-	     nlevs, gridID, gridsize);
-
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
   /* NOTE: tiles are not supported here! */
-  recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-  recpos = streamptr->tsteps[tsid].records[recID].position;
+  int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+  off_t recpos = streamptr->tsteps[tsid].records[recID].position;
   fileSetPos(fileID, recpos, SEEK_SET);
   extRead(fileID, extp);
+  int header[4];
   extInqHeader(extp, header);
   extInqDataDP(extp, data);
 
@@ -806,7 +674,7 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
   *nmiss = 0;
   if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
     {
-      for ( i = 0; i < gridsize; i++ )
+      for ( int i = 0; i < gridsize; i++ )
 	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
 	  {
 	    data[i] = missval;
@@ -815,7 +683,7 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
     }
   else
     {
-      for ( i = 0; i < 2*gridsize; i+=2 )
+      for ( int i = 0; i < 2*gridsize; i+=2 )
 	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
 	  {
 	    data[i] = missval;
@@ -825,88 +693,59 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
 }
 
 
-void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
+void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
 {
-  int fileID;
-  int levID, nlevs, gridID, gridsize;
-  int zaxisID;
-  double level;
-  int header[4];
-  int tsID;
-  int vlistID;
-  int pdis, pcat, pnum;
-  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
-
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  nlevs    = zaxisInqSize(zaxisID);
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
-  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
-
-  header[0] = streamptr->tsteps[tsID].taxis.vdate;
-  header[1] = pnum;
-  header[3] = gridInqSize(gridID);
-
-  extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
-
-  for ( levID = 0;  levID < nlevs; levID++ )
-    {
-      level = zaxisInqLevel(zaxisID, levID);
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) streamptr->vars[varID].recordTable[0].nlevs;
 
-      header[2] = (int) level;
-      extDefHeader(extp, header);
-      extDefDataDP(extp, &data[levID*gridsize]);
-      extWrite(fileID, extp);
-    }
+  for ( size_t levID = 0; levID < nlevs; levID++)
+    extReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss);
 }
 
 
 void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
 {
-  int fileID;
-  int gridID;
-  int zaxisID;
-  double level;
-  int header[4];
-  int tsID;
-  int vlistID;
-  int pdis, pcat, pnum;
-  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  level    = zaxisInqLevel(zaxisID, levID);
-
-  if ( CDI_Debug )
-    Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
+  int tsID     = streamptr->curTsID;
 
+  int pdis, pcat, pnum;
   cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
 
+  int header[4];
   header[0] = streamptr->tsteps[tsID].taxis.vdate;
   header[1] = pnum;
-  header[2] = (int) level;
-  header[3] = gridInqSize(gridID);
+  header[2] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID);
+  header[3] = gridInqSize(vlistInqVarGrid(vlistID, varID));
 
+  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
   extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
-
   extDefHeader(extp, header);
+
   extDefDataDP(extp, data);
   extWrite(fileID, extp);
 }
 
+
+void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
+{
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
+
+  for ( size_t levID = 0;  levID < nlevs; levID++ )
+    extWriteVarSliceDP(streamptr, varID, levID, &data[levID*gridsize]);
+}
+
 #endif /* HAVE_LIBEXTRA */
+
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/src/stream_fcommon.c b/src/stream_fcommon.c
deleted file mode 100644
index 482a031675146499babeb217d472bd68927deb24..0000000000000000000000000000000000000000
--- a/src/stream_fcommon.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <stdlib.h>
-
-#include "cdi_int.h"
-#include "dmemory.h"
-#include "file.h"
-#include "stream_fcommon.h"
-
-
-void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name)
-{
-  int fileID1 = streamptr1->fileID;
-  int fileID2 = streamptr2->fileID;
-
-  int tsID    = streamptr1->curTsID;
-  int vrecID  = streamptr1->tsteps[tsID].curRecID;
-  int recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  off_t recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  if (fileSetPos(fileID1, recpos, SEEK_SET) != 0)
-    Error("Cannot seek input file for %s record copy!", container_name);
-
-  char *buffer = (char *) Malloc(recsize);
-
-  if (fileRead(fileID1, buffer, recsize) != recsize)
-    Error("Failed to read record from %s file for copying!", container_name);
-
-  if (fileWrite(fileID2, buffer, recsize) != recsize)
-    Error("Failed to write record to %s file when copying!", container_name);
-
-  Free(buffer);
-}
-
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/src/stream_fcommon.h b/src/stream_fcommon.h
deleted file mode 100644
index f021f8644625f27a9fa9258929132089452634b9..0000000000000000000000000000000000000000
--- a/src/stream_fcommon.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef STREAM_FCOMMON_H
-#define STREAM_FCOMMON_H
-
-#ifndef  _CDI_INT_H
-#include "cdi_int.h"
-#endif
-
-void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
-                       const char *container_name);
-
-#endif
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/src/stream_gribapi.c b/src/stream_gribapi.c
index 8189a769583a2fd37adee4b8fa12a1dfd3fe8e9c..0fc59acdef91b8589364e1e06d2c5e8b5376de27 100644
--- a/src/stream_gribapi.c
+++ b/src/stream_gribapi.c
@@ -459,12 +459,24 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
   //       I. e. kick the fixed size array and allocate enough space, whatever that may be.
   strncpy(record->varname, varname, sizeof(record->varname));
 
-  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+  grid_t *grid = (grid_t *)Malloc(sizeof(*grid));
   gribapiGetGrid(gh, grid);
 
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
   int gridID = gridAdded.Id;
-  if (!gridAdded.isNew) Free(grid);
+  if ( !gridAdded.isNew ) Free(grid);
+  else if ( grid->projtype == CDI_PROJ_RLL )
+    {
+      double xpole = 0, ypole = 0, angle = 0;
+      grib_get_double(gh, "latitudeOfSouthernPoleInDegrees",  &ypole);
+      grib_get_double(gh, "longitudeOfSouthernPoleInDegrees", &xpole);
+      grib_get_double(gh, "angleOfRotation", &angle);
+      xpole =  xpole - 180;
+      if ( fabs(ypole) > 0 ) ypole = -ypole; // change from south to north pole
+      if ( fabs(angle) > 0 ) angle = -angle;
+
+      gridDefProjParamRLL(gridID, xpole, ypole, angle);
+    }
 
   int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1);
 
@@ -693,8 +705,8 @@ grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, vo
       if ( grib_get_string(gh, "packingType", typeOfPacking, &len) == 0 )
         {
           // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking);
-          if      ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = COMPRESS_JPEG;
-          else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = COMPRESS_SZIP;
+          if      ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = CDI_COMPRESS_JPEG;
+          else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = CDI_COMPRESS_SZIP;
           else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = true;
         }
     }
@@ -702,12 +714,12 @@ grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, vo
     {
       if( gribGetZip((long)recsize, *gribbuffer, outUnzipsize) > 0 )
         {
-          *outCompressionType = COMPRESS_SZIP;
+          *outCompressionType = CDI_COMPRESS_SZIP;
           ensureBufferSize((size_t)*outUnzipsize + 100, buffersize, gribbuffer);
         }
       else
         {
-          *outCompressionType = COMPRESS_NONE;
+          *outCompressionType = CDI_COMPRESS_NONE;
         }
     }
 
@@ -1663,7 +1675,7 @@ void gribapiDefStepUnits(int editionNumber, grib_handle *gh, int timeunit, int p
       else if ( grib2ProDefTempHasStatisticalDef(proDefTempNum) )
         {
           GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
-          //  GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+          GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
         }
       else
         {
@@ -1842,13 +1854,13 @@ getGribApiCompTypeMsg(grib_handle *gh, int comptype, int gridsize)
   const char *mesg;
   size_t len;
 
-  if ( comptype == COMPRESS_JPEG && gridsize > 1 )
+  if ( comptype == CDI_COMPRESS_JPEG && gridsize > 1 )
     {
       static const char mesg_grid_jpeg[] = "grid_jpeg";
       len = sizeof (mesg_grid_jpeg) - 1;
       mesg = mesg_grid_jpeg;
     }
-  else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
+  else if ( comptype == CDI_COMPRESS_SZIP && gridsize > 1 )
     {
       static const char mesg_grid_ccsds[] = "grid_ccsds";
       len = sizeof (mesg_grid_ccsds) - 1;
@@ -1869,6 +1881,8 @@ static
 void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, bool lieee, int datatype, int nmiss, int gcinit)
 {
   UNUSED(nmiss);
+  bool lrotated = false;
+  bool lcurvi = false;
 
   int gridtype = gridInqType(gridID);
   int gridsize = gridInqSize(gridID);
@@ -1904,13 +1918,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
     }
   else if ( gridtype == GRID_CURVILINEAR )
     {
-      static bool lwarn = true;
-      if ( lwarn && gridsize > 1 )
+      static bool lwarning = true;
+      if ( lwarning && gridsize > 1 )
 	{
-	  lwarn = false;
+	  lwarning = false;
 	  Warning("Curvilinear grids are unsupported in GRIB format! Created wrong Grid Description Section!");
 	}
       gridtype = GRID_LONLAT;
+      lcurvi = true;
+    }
+
+  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+    {
+      gridtype = GRID_LONLAT;
+      lrotated = true;
     }
 
   if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
@@ -1940,43 +1961,39 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	double yfirst = 0, ylast = 0, yinc = 0;
 	double latIncr;
 
-        {
-          const char *mesg;
-          size_t len;
-          if ( gridtype == GRID_GAUSSIAN )
-            {
-              static const char mesg_gaussian[] = "regular_gg";
-              len = sizeof (mesg_gaussian) - 1;
-              mesg = mesg_gaussian;
-            }
-          else if ( gridtype == GRID_GAUSSIAN_REDUCED )
-            {
-              static const char mesg_gaussian_reduced[] = "reduced_gg";
-              len = sizeof (mesg_gaussian_reduced) - 1;
-              mesg = mesg_gaussian_reduced;
-            }
-          else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
-            {
-              static const char mesg_rot_lonlat[] = "rotated_ll";
-              len = sizeof (mesg_rot_lonlat) - 1;
-              mesg = mesg_rot_lonlat;
-            }
-          else
-            {
-              static const char mesg_regular_ll[] = "regular_ll";
-              len = sizeof (mesg_regular_ll) - 1;
-              mesg = mesg_regular_ll;
-	  }
-          GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-        }
+        const char *mesg;
+        size_t len;
+        if ( gridtype == GRID_GAUSSIAN )
+          {
+            static const char mesg_gaussian[] = "regular_gg";
+            len = sizeof(mesg_gaussian) - 1;
+            mesg = mesg_gaussian;
+          }
+        else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+          {
+            static const char mesg_gaussian_reduced[] = "reduced_gg";
+            len = sizeof(mesg_gaussian_reduced) - 1;
+            mesg = mesg_gaussian_reduced;
+          }
+        else if ( gridtype == GRID_LONLAT && (gridIsRotated(gridID) || lrotated) )
+          {
+            static const char mesg_rot_lonlat[] = "rotated_ll";
+            len = sizeof(mesg_rot_lonlat) - 1;
+            mesg = mesg_rot_lonlat;
+          }
+        else
+          {
+            static const char mesg_regular_ll[] = "regular_ll";
+            len = sizeof(mesg_regular_ll) - 1;
+            mesg = mesg_regular_ll;
+          }
+        GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
 
 	long nlon = gridInqXsize(gridID);
 	long nlat = gridInqYsize(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN_REDUCED )
 	  {
-            //GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize), 0);
-
 	    nlon = 0;
 
 	    int *rowlon = (int *) Malloc((size_t)nlat*sizeof(int));
@@ -1995,26 +2012,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	  }
 	else
 	  {
-	    if ( nlon == 0 )
-	      {
-		nlon = 1;
-	      }
+	    if ( nlon == 0 ) nlon = 1;
 	    else
 	      {
-		xfirst = gridInqXval(gridID,      0);
-		xlast  = gridInqXval(gridID, nlon-1);
+		xfirst = gridInqXval(gridID, 0);
+                xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
 		xinc   = gridInqXinc(gridID);
 	      }
 	  }
 
-	if ( nlat == 0 )
-	  {
-	    nlat = 1;
-	  }
+	if ( nlat == 0 ) nlat = 1;
 	else
 	  {
-	    yfirst = gridInqYval(gridID,      0);
-	    ylast  = gridInqYval(gridID, nlat-1);
+	    yfirst = gridInqYval(gridID, 0);
+            ylast  = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1);
 	    yinc   = gridInqYinc(gridID);
 	  }
 
@@ -2032,10 +2043,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
           if ( yfirst < ylast ) jscan = 1;
           GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jscan), 0);
         }
-	/*
-	if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON )
-	  ISEC2_LonIncr = 0;
-	*/
+
 	if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
           {
             int np = gridInqNP(gridID);
@@ -2047,67 +2055,46 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	    latIncr = yinc;
 	    if ( latIncr < 0 ) latIncr = -latIncr;
 	    GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", latIncr), 0);
-	    /*
-	    if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON )
-	      ISEC2_LatIncr = 0;
-	    */
 	  }
-	/*
-	if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
-	  if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr;
 
-	if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
-	  if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
-
-	if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
-	  ISEC2_ResFlag = 0;
-	else
-	  ISEC2_ResFlag = 128;
-	*/
-	if ( gridIsRotated(gridID) )
+	if ( gridIsRotated(gridID) || lrotated )
 	  {
-	    double xpole = gridInqXpole(gridID);
-	    double ypole = gridInqYpole(gridID);
-	    double angle = gridInqAngle(gridID);
-	    /* change from north to south pole */
-	    if ( fabs(ypole) > 0 ) ypole = -ypole;
-	    xpole =  xpole + 180;
-            if ( fabs(angle) > 0 ) angle = -angle;
-	    GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees",  ypole), 0);
-	    GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0);
-	    GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0);
-	  }
-
-	/* East -> West */
-	//if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
+            double xpole = 0, ypole = 0, angle = 0;
+            if ( gridIsRotated(gridID) )
+              {
+                xpole = gridInqXpole(gridID);
+                ypole = gridInqYpole(gridID);
+                angle = gridInqAngle(gridID);
+              }
+            else
+              gridInqProjParamRLL(gridID, &xpole, &ypole, &angle);
 
-	/* South -> North */
-	//if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
+            xpole =  xpole + 180;
+            if ( fabs(ypole) > 0 ) ypole = -ypole; // change from north to south pole
+            if ( fabs(angle) > 0 ) angle = -angle;
+            GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees",  ypole), 0);
+            GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0);
+            GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0);
+          }
 
         if ( editionNumber != 2 ) { lieee = false; comptype = 0; }
 
-        {
-          const char *mesg;
-          size_t len;
-          if ( lieee )
-            {
-              static const char mesg_grid_ieee[] = "grid_ieee";
-              len = sizeof (mesg_grid_ieee) - 1;
-              mesg = mesg_grid_ieee;
-            }
-          else
-            {
-              struct gribApiMsg gaMsg
-                = getGribApiCompTypeMsg(gh, comptype, gridsize);
-              len = gaMsg.msgLen;
-              mesg = gaMsg.msg;
-            }
-          GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-          if ( lieee )
-            GRIB_CHECK(my_grib_set_long(gh, "precision",
-                                        datatype == DATATYPE_FLT64 ? 2 : 1), 0);
-
-        }
+        if ( lieee )
+          {
+            static const char mesg_grid_ieee[] = "grid_ieee";
+            len = sizeof (mesg_grid_ieee) - 1;
+            mesg = mesg_grid_ieee;
+          }
+        else
+          {
+            struct gribApiMsg gaMsg = getGribApiCompTypeMsg(gh, comptype, gridsize);
+            len = gaMsg.msgLen;
+            mesg = gaMsg.msg;
+          }
+        GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+        if ( lieee )
+          GRIB_CHECK(my_grib_set_long(gh, "precision",
+                                      datatype == DATATYPE_FLT64 ? 2 : 1), 0);
 
 	break;
       }
@@ -2202,7 +2189,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
 	GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridsize), 0);
 
-        if ( comptype == COMPRESS_SZIP )
+        if ( comptype == CDI_COMPRESS_SZIP )
           {
             static const char mesg[] = "grid_ccsds";
             size_t len = sizeof (mesg) -1;
@@ -2238,7 +2225,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	      Warning("Can't write UUID!");
 	  }
 
-        if ( comptype == COMPRESS_SZIP )
+        if ( comptype == CDI_COMPRESS_SZIP )
           {
             static const char mesg[] = "grid_ccsds";
             size_t len = sizeof (mesg) -1;
@@ -2614,7 +2601,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
   long editionNumber = 2;
   char name[256];
   char stdname[256];
-  gribContainer_t *gc = (gribContainer_t *) gribContainer;
+
   // extern unsigned char _grib_template_GRIB2[];
 
   int param    = vlistInqVarParam(vlistID, varID);
@@ -2628,8 +2615,11 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 #if defined(GRIBAPIENCODETEST)
   grib_handle *gh = (grib_handle *) gribHandleNew(editionNumber);
 #else
+  gribContainer_t *gc = (gribContainer_t *) gribContainer;
+  assert(gc != NULL);
   grib_handle *gh = (struct grib_handle *)gc->gribHandle;
 #endif
+
   GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
 
   if ( editionNumber == 2 )
diff --git a/src/stream_ieg.c b/src/stream_ieg.c
index 20c08f97ccf306ea72b27861d46d4e65c071105c..4696222924ac4e15735d83dde3364fa6e398bf43 100644
--- a/src/stream_ieg.c
+++ b/src/stream_ieg.c
@@ -19,16 +19,14 @@
 #include "varscan.h"
 #include "datetime.h"
 #include "ieg.h"
-#include "stream_fcommon.h"
 #include "stream_ieg.h"
 #include "vlist.h"
+#include "exse.h"
 
 
 #undef  UNDEFID
 #define UNDEFID  CDI_UNDEFID
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
 
 #if defined (HAVE_LIBIEG)
 
@@ -36,34 +34,25 @@
 typedef struct {
   int param;
   int level;
-} IEGCOMPVAR;
+} iegcompvar_t;
 
 
-static int iegInqDatatype(int prec)
+static
+int iegInqDatatype(int prec)
 {
-  int datatype;
-
-  if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
-  else                            datatype = DATATYPE_FLT32;
-
-  return (datatype);
+  return (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32;
 }
 
-
-static int iegDefDatatype(int datatype)
+static
+int iegDefDatatype(int datatype)
 {
-  int prec;
-
   if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
     Error("CDI/IEG library does not support complex numbers!");
 
   if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
     datatype = DATATYPE_FLT32;
 
-  if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION;
-  else                              prec = SINGLE_PRECISION;
-
-  return (prec);
+  return (datatype == DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
 }
 
 /* not used
@@ -83,7 +72,7 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
   *levelID = -1;
 
   status = iegRead(fileID, iegp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 ) return 0;
 
   icode  = IEG_P_Parameter(iegp->ipdb);
   if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
@@ -99,45 +88,37 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
 
   *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
 
-  return (1);
+  return 1;
 }
 */
 
 void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
-  int vlistID, fileID;
-  int status;
-  int recID, vrecID, tsID;
-  off_t recpos;
-  int varID, gridID;
-  int i, size;
-  double missval;
-  void *iegp = streamptr->record->exsep;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-  tsID    = streamptr->curTsID;
-  vrecID  = streamptr->tsteps[tsID].curRecID;
-  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr->tsteps[tsID].records[recID].position;
-  varID   = streamptr->tsteps[tsID].records[recID].varID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+  int tsID    = streamptr->curTsID;
+  int vrecID  = streamptr->tsteps[tsID].curRecID;
+  int recID   = streamptr->tsteps[tsID].recIDs[vrecID];
+  int varID   = streamptr->tsteps[tsID].records[recID].varID;
+  off_t recpos = streamptr->tsteps[tsID].records[recID].position;
 
   fileSetPos(fileID, recpos, SEEK_SET);
 
-  status = iegRead(fileID, iegp);
+  void *iegp = streamptr->record->exsep;
+  int status = iegRead(fileID, iegp);
   if ( status != 0 )
     Error("Could not read IEG record!");
 
   iegInqDataDP(iegp, data);
 
-  missval = vlistInqVarMissval(vlistID, varID);
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  size    = gridInqSize(gridID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int size    = gridInqSize(gridID);
 
   streamptr->numvals += size;
 
   *nmiss = 0;
-  for ( i = 0; i < size; i++ )
+  for ( int i = 0; i < size; i++ )
     if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
       {
 	data[i] = missval;
@@ -197,19 +178,18 @@ int iegGetZaxisType(int iegleveltype)
       }
     }
 
-  return (leveltype);
+  return leveltype;
 }
 
 
 static void iegDefTime(int *pdb, int date, int time, int taxisID)
 {
-  int year, month, day, hour, minute, second;
   int timetype = -1;
-
   if ( taxisID != -1 ) timetype = taxisInqType(taxisID);
 
   if ( timetype == TAXIS_ABSOLUTE || timetype == TAXIS_RELATIVE )
     {
+      int year, month, day, hour, minute, second;
       cdiDecodeDate(date, &year, &month, &day);
       cdiDecodeTime(time, &hour, &minute, &second);
 
@@ -260,21 +240,25 @@ calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylas
         }
     }
 
-  return (resfac);
+  return resfac;
 }
 
 static
 void iegDefGrid(int *gdb, int gridID)
 {
+  int projID = gridInqProj(gridID);
+  if ( projID != CDI_UNDEFID && gridInqProjType(projID) == CDI_PROJ_RLL ) gridID = projID;
+
   int gridtype = gridInqType(gridID);
 
-  if ( gridtype == GRID_GENERIC )
-    {
-      int xsize, ysize;
+  int projtype = CDI_UNDEFID;
+  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL ) projtype = CDI_PROJ_RLL;
 
-      xsize = gridInqXsize(gridID);
-      ysize = gridInqYsize(gridID);
+  int xsize = gridInqXsize(gridID);
+  int ysize = gridInqYsize(gridID);
 
+  if ( gridtype == GRID_GENERIC )
+    {
       if ( (ysize == 32  || ysize == 48 || ysize == 64 ||
 	    ysize == 96  || ysize == 160) &&
 	   (xsize == 2*ysize || xsize == 1) )
@@ -298,39 +282,32 @@ void iegDefGrid(int *gdb, int gridID)
       gridtype = GRID_LONLAT;
     }
 
-  if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+  bool lrotated = ((gridtype == GRID_LONLAT && gridIsRotated(gridID)) || projtype == CDI_PROJ_RLL);
+
+  if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL )
     {
       double xfirst = 0, xlast = 0, xinc = 0;
       double yfirst = 0, ylast = 0, yinc = 0;
 
-      int nlon = gridInqXsize(gridID),
-        nlat = gridInqYsize(gridID);
-
-      if ( nlon == 0 )
-	{
-	  nlon = 1;
-	}
+      if ( xsize == 0 ) xsize = 1;
       else
 	{
-	  xfirst = gridInqXval(gridID,      0);
-	  xlast  = gridInqXval(gridID, nlon-1);
+	  xfirst = gridInqXval(gridID,       0);
+	  xlast  = gridInqXval(gridID, xsize-1);
 	  xinc   = gridInqXinc(gridID);
 	}
 
-      if ( nlat == 0 )
-	{
-	  nlat = 1;
-	}
+      if ( ysize == 0 ) ysize = 1;
       else
 	{
-	  yfirst = gridInqYval(gridID,      0);
-	  ylast  = gridInqYval(gridID, nlat-1);
+	  yfirst = gridInqYval(gridID,       0);
+	  ylast  = gridInqYval(gridID, ysize-1);
 	  yinc   = gridInqYinc(gridID);
 	}
 
       if ( gridtype == GRID_GAUSSIAN )
 	IEG_G_GridType(gdb) = 4;
-      else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+      else if ( lrotated )
 	IEG_G_GridType(gdb) = 10;
       else
 	IEG_G_GridType(gdb) = 0;
@@ -341,8 +318,8 @@ void iegDefGrid(int *gdb, int gridID)
 
       IEG_G_ResFac(gdb)   = iresfac;
 
-      IEG_G_NumLon(gdb)   = nlon;
-      IEG_G_NumLat(gdb)   = nlat;
+      IEG_G_NumLon(gdb)   = xsize;
+      IEG_G_NumLat(gdb)   = ysize;
       IEG_G_FirstLat(gdb) = (int)lround(yfirst*resfac);
       IEG_G_LastLat(gdb)  = (int)lround(ylast*resfac);
       IEG_G_FirstLon(gdb) = (int)lround(xfirst*resfac);
@@ -352,7 +329,7 @@ void iegDefGrid(int *gdb, int gridID)
 	IEG_G_LonIncr(gdb) = 0;
 
       if ( gridtype == GRID_GAUSSIAN )
-	IEG_G_LatIncr(gdb) = nlat/2;
+	IEG_G_LatIncr(gdb) = ysize/2;
       else
 	{
 	  IEG_G_LatIncr(gdb) = (int)lround(yinc*resfac);
@@ -368,15 +345,22 @@ void iegDefGrid(int *gdb, int gridID)
       if ( IEG_G_NumLon(gdb) == 1 && IEG_G_NumLat(gdb) > 1 )
 	if ( IEG_G_LonIncr(gdb) == 0 && IEG_G_LatIncr(gdb) != 0 ) IEG_G_LonIncr(gdb) = IEG_G_LatIncr(gdb);
 
-      if ( IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0 )
-	IEG_G_ResFlag(gdb) = 0;
-      else
-	IEG_G_ResFlag(gdb) = 128;
+      IEG_G_ResFlag(gdb) = (IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0) ? 0 : 128;
 
-      if ( gridIsRotated(gridID) )
+      if ( lrotated )
 	{
-	  IEG_G_LatSP(gdb) = - (int)lround(gridInqYpole(gridID) * resfac);
-	  IEG_G_LonSP(gdb) =   (int)lround((gridInqXpole(gridID) + 180) * resfac);
+          double xpole = 0, ypole = 0, angle = 0;
+          if ( projtype == CDI_PROJ_RLL )
+            gridInqProjParamRLL(gridID, &xpole, &ypole, &angle);
+          else
+            {
+              xpole = gridInqXpole(gridID);
+              ypole = gridInqYpole(gridID);
+              angle = gridInqAngle(gridID);
+            }
+
+	  IEG_G_LatSP(gdb) = - (int)lround(ypole * resfac);
+	  IEG_G_LonSP(gdb) =   (int)lround((xpole + 180) * resfac);
 	  IEG_G_Size(gdb)  = 42;
 	}
       else
@@ -392,20 +376,26 @@ void iegDefGrid(int *gdb, int gridID)
   IEG_G_ScanFlag(gdb) = 64;
 }
 
+static
+void pdbDefLevel(int *pdb, int leveltype, int level1, int level2)
+{
+  IEG_P_LevelType(pdb) = leveltype;
+  IEG_P_Level1(pdb)    = level1;
+  IEG_P_Level2(pdb)    = level2;
+}
+
 static
 void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 {
   double level;
-  int ilevel, leveltype;
-  static int vct_warning = 1;
+  int ilevel;
 
-  leveltype = zaxisInqType(zaxisID);
+  int leveltype = zaxisInqType(zaxisID);
 
   if ( leveltype == ZAXIS_GENERIC )
     {
       Message("Changed zaxis type from %s to %s",
-	      zaxisNamePtr(leveltype),
-	      zaxisNamePtr(ZAXIS_PRESSURE));
+	      zaxisNamePtr(leveltype), zaxisNamePtr(ZAXIS_PRESSURE));
       leveltype = ZAXIS_PRESSURE;
       zaxisChangeType(zaxisID, leveltype);
       zaxisDefUnits(zaxisID, "Pa");
@@ -417,36 +407,26 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
     {
     case ZAXIS_SURFACE:
       {
-	IEG_P_LevelType(pdb) = IEG_LTYPE_SURFACE;
-	IEG_P_Level1(pdb)    = 0;
-	IEG_P_Level2(pdb)    = (int)(zaxisInqLevel(zaxisID, levelID));
+        pdbDefLevel(pdb, IEG_LTYPE_SURFACE, 0, (int)zaxisInqLevel(zaxisID, levelID));
 	break;
       }
     case ZAXIS_HYBRID:
       {
-	int vctsize;
-
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-	  {
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID_LAYER;
-	    IEG_P_Level1(pdb)    = (int)(zaxisInqLbound(zaxisID, levelID));
-	    IEG_P_Level2(pdb)    = (int)(zaxisInqUbound(zaxisID, levelID));
-	  }
+          pdbDefLevel(pdb, IEG_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID),
+                      (int)zaxisInqUbound(zaxisID, levelID));
 	else
-	  {
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID;
-	    IEG_P_Level1(pdb)    = 0;
-	    IEG_P_Level2(pdb)    = (int)(zaxisInqLevel(zaxisID, levelID));
-	  }
+          pdbDefLevel(pdb, IEG_LTYPE_HYBRID, 0, (int)zaxisInqLevel(zaxisID, levelID));
 
-	vctsize = zaxisInqVctSize(zaxisID);
+	int vctsize = zaxisInqVctSize(zaxisID);
 	if ( vctsize > 100 )
 	  {
+            static bool vct_warning = true;
 	    /*	    IEG_G_NumVCP(gdb) = 0; */
 	    if ( vct_warning )
 	      {
 		Warning("VCT size of %d is too large (maximum is 100). Set to 0!", vctsize);
-		vct_warning = 0;
+		vct_warning = false;
 	      }
 	  }
 	else
@@ -463,8 +443,7 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 	char units[128];
 
 	level = zaxisInqLevel(zaxisID, levelID);
-	if ( level < 0 )
-	  Warning("pressure level of %f Pa is below 0.", level);
+	if ( level < 0 ) Warning("pressure level of %f Pa is below 0.", level);
 
 	zaxisInqUnits(zaxisID, units);
 	if ( memcmp(units, "hPa", 3) == 0 || memcmp(units, "mb",2 ) == 0 )
@@ -472,81 +451,43 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 
 	ilevel = (int) level;
 	if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
-	  {
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_99;
-	    IEG_P_Level1(pdb)    = 0;
-	    IEG_P_Level2(pdb)    = ilevel;
-	  }
+          pdbDefLevel(pdb, IEG_LTYPE_99, 0, ilevel);
 	else
-	  {
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_ISOBARIC;
-	    IEG_P_Level1(pdb)    = 0;
-	    IEG_P_Level2(pdb)    = ilevel/100;
-	  }
-	break;
+          pdbDefLevel(pdb, IEG_LTYPE_ISOBARIC, 0, ilevel/100);
+
+        break;
       }
     case ZAXIS_HEIGHT:
       {
 	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	IEG_P_LevelType(pdb) = IEG_LTYPE_HEIGHT;
-	IEG_P_Level1(pdb)    = 0;
-	IEG_P_Level2(pdb)    = ilevel;
-
+        pdbDefLevel(pdb, IEG_LTYPE_HEIGHT, 0, (int)level);
 	break;
       }
     case ZAXIS_ALTITUDE:
       {
 	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	IEG_P_LevelType(pdb) = IEG_LTYPE_ALTITUDE;
-	IEG_P_Level1(pdb)    = 0;
-	IEG_P_Level2(pdb)    = ilevel;
-
+        pdbDefLevel(pdb, IEG_LTYPE_ALTITUDE, 0, (int)level);
 	break;
       }
     case ZAXIS_DEPTH_BELOW_LAND:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-	  {
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH_LAYER;
-	    IEG_P_Level1(pdb)    = (int)(zaxisInqLbound(zaxisID, levelID));
-	    IEG_P_Level2(pdb)    = (int)(zaxisInqUbound(zaxisID, levelID));
-	  }
+          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH_LAYER, (int)zaxisInqLbound(zaxisID, levelID), (int)zaxisInqUbound(zaxisID, levelID));
 	else
-	  {
-	    level = zaxisInqLevel(zaxisID, levelID);
-
-	    ilevel = (int) level;
-	    IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH;
-	    IEG_P_Level1(pdb)    = 0;
-	    IEG_P_Level2(pdb)    = ilevel;
-	  }
+          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH, 0, (int)zaxisInqLevel(zaxisID, levelID));
 
 	break;
       }
     case ZAXIS_DEPTH_BELOW_SEA:
       {
 	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	IEG_P_LevelType(pdb) = IEG_LTYPE_SEADEPTH;
-	IEG_P_Level1(pdb)    = 0;
-	IEG_P_Level2(pdb)    = ilevel;
-
+        pdbDefLevel(pdb, IEG_LTYPE_SEADEPTH, 0, (int)level);
 	break;
       }
     case ZAXIS_ISENTROPIC:
       {
 	level = zaxisInqLevel(zaxisID, levelID);
-
-	ilevel = (int) level;
-	IEG_P_LevelType(pdb) = 113;
-	IEG_P_Level1(pdb)    = 0;
-	IEG_P_Level2(pdb)    = ilevel;
-
+        pdbDefLevel(pdb, 113, 0, (int)level);
 	break;
       }
     default:
@@ -566,68 +507,55 @@ void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 
 void iegDefRecord(stream_t *streamptr)
 {
-  int vlistID;
-  int gridID;
-  int date, time;
-  int datatype;
-  int i;
-  int param, pdis, pcat, pnum;
-  int varID, levelID, tsID, zaxisID;
-  int byteorder;
-  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+  Record *record = streamptr->record;
+  iegrec_t *iegp = (iegrec_t*) record->exsep;
 
-  vlistID = streamptr->vlistID;
-  byteorder = streamptr->byteorder;
+  int vlistID = streamptr->vlistID;
+  int byteorder = streamptr->byteorder;
 
-  varID   = streamptr->record->varID;
-  levelID = streamptr->record->levelID;
-  tsID    = streamptr->curTsID;
+  int varID   = record->varID;
+  int levelID = record->levelID;
+  int tsID    = streamptr->curTsID;
 
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  zaxisID = vlistInqVarZaxis(vlistID, varID);
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
 
   iegInitMem(iegp);
-  for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
+  for ( int i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
 
   iegp->byteswap = getByteswap(byteorder);
 
-  param =  vlistInqVarParam(vlistID, varID);
+  int param = vlistInqVarParam(vlistID, varID);
+  int pdis, pcat, pnum;
   cdiDecodeParam(param, &pnum, &pcat, &pdis);
   IEG_P_Parameter(iegp->ipdb) = pnum;
   if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
-  date     = streamptr->tsteps[tsID].taxis.vdate;
-  time     = streamptr->tsteps[tsID].taxis.vtime;
 
+  int date = streamptr->tsteps[tsID].taxis.vdate;
+  int time = streamptr->tsteps[tsID].taxis.vtime;
   iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
   iegDefGrid(iegp->igdb, gridID);
   iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levelID);
 
-  datatype = streamptr->record->prec;
-
-  iegp->dprec = iegDefDatatype(datatype);
+  iegp->dprec = iegDefDatatype(record->prec);
 }
 
 
 void iegWriteRecord(stream_t *streamptr, const double *data)
 {
-  int fileID;
-  int i, gridsize, gridID;
-  double refval;
-  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
-
-  fileID = streamptr->fileID;
-  gridID = streamptr->record->gridID;
+  Record *record = streamptr->record;
+  iegrec_t *iegp = (iegrec_t*) record->exsep;
 
-  gridsize = gridInqSize(gridID);
+  int fileID = streamptr->fileID;
+  int gridsize = gridInqSize(record->gridID);
 
-  refval = data[0];
-  for ( i = 1; i < gridsize; i++ )
+  double refval = data[0];
+  for ( int i = 1; i < gridsize; i++ )
     if ( data[i] < refval ) refval = data[i];
 
   iegp->refval = refval;
 
   iegDefDataDP(iegp, data);
-
   iegWrite(fileID, iegp);
 }
 
@@ -635,7 +563,6 @@ static
 void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
 		  size_t recsize, off_t position, int prec)
 {
-  int levelID = 0;
   int vlistID = streamptr->vlistID;
   int tsID    = streamptr->curTsID;
   int recID   = recordNewEntry(streamptr, tsID);
@@ -661,18 +588,25 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
   record->ilevel2  = level2;
   record->ltype    = IEG_P_LevelType(pdb);
 
-  int gridtype =
-   ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 ) ? GRID_LONLAT :
-    ( IEG_G_GridType(gdb) == 4 ) ? GRID_GAUSSIAN : GRID_GENERIC;
+#ifdef TEST_PROJECTION
+  int gridtype = (IEG_G_GridType(gdb) == 0) ? GRID_LONLAT :
+                 (IEG_G_GridType(gdb) == 10) ? GRID_PROJECTION :
+                 (IEG_G_GridType(gdb) == 4) ? GRID_GAUSSIAN : GRID_GENERIC;
+#else
+  int gridtype = (IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10) ? GRID_LONLAT :
+                 (IEG_G_GridType(gdb) == 4) ? GRID_GAUSSIAN : GRID_GENERIC;
+#endif
 
   grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
   grid_init(grid);
   cdiGridTypeInit(grid, gridtype, IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb));
-  grid->xsize = IEG_G_NumLon(gdb);
-  grid->ysize = IEG_G_NumLat(gdb);
-  grid->xinc  = 0;
-  grid->yinc  = 0;
-  grid->xdef  = 0;
+  int xsize = IEG_G_NumLon(gdb);
+  int ysize = IEG_G_NumLat(gdb);
+  grid->x.size = xsize;
+  grid->y.size = ysize;
+  grid->x.inc  = 0;
+  grid->y.inc  = 0;
+  grid->x.flag = 0;
 
   int iresfac = IEG_G_ResFac(gdb);
   if ( iresfac == 0 ) iresfac = 1000;
@@ -680,78 +614,74 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
 
   /* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */
   {
-    if ( grid->xsize > 1 )
+    if ( xsize > 1 )
       {
 	if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 )
-	  grid->xinc = IEG_G_LonIncr(gdb) * resfac;
+	  grid->x.inc = IEG_G_LonIncr(gdb) * resfac;
 	else
-	  grid->xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid->xsize - 1);
+	  grid->x.inc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (xsize - 1);
 
 	/* correct xinc if necessary */
 	if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 )
 	  {
-	    double xinc = 360. / grid->xsize;
-            /* FIXME: why not use grid->xinc != xinc as condition? */
-	    if ( fabs(grid->xinc-xinc) > 0.0 )
+	    double xinc = 360. / xsize;
+            /* FIXME: why not use grid->x.inc != xinc as condition? */
+	    if ( fabs(grid->x.inc-xinc) > 0.0 )
 	      {
-		grid->xinc = xinc;
-		if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
+		grid->x.inc = xinc;
+		if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc);
 	      }
 	  }
       }
-    grid->xfirst = IEG_G_FirstLon(gdb) * resfac;
-    grid->xlast  = IEG_G_LastLon(gdb)  * resfac;
-    grid->xdef   = 2;
+    grid->x.first = IEG_G_FirstLon(gdb) * resfac;
+    grid->x.last  = IEG_G_LastLon(gdb)  * resfac;
+    grid->x.flag  = 2;
   }
-  grid->ydef  = 0;
+  grid->y.flag = 0;
   /* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */
   {
-    if ( grid->ysize > 1 )
+    if ( ysize > 1 )
       {
 	if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 )
-	  grid->yinc = IEG_G_LatIncr(gdb) * resfac;
+	  grid->y.inc = IEG_G_LatIncr(gdb) * resfac;
 	else
-	  grid->yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid->ysize - 1);
+	  grid->y.inc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (ysize - 1);
       }
-    grid->yfirst = IEG_G_FirstLat(gdb) * resfac;
-    grid->ylast  = IEG_G_LastLat(gdb)  * resfac;
-    grid->ydef   = 2;
+    grid->y.first = IEG_G_FirstLat(gdb) * resfac;
+    grid->y.last  = IEG_G_LastLat(gdb)  * resfac;
+    grid->y.flag  = 2;
   }
-  /*
-  grid->xfirst= IEG_G_FirstLon(gdb) * resfac;
-  grid->xlast = IEG_G_LastLon(gdb) * resfac;
-  grid->xinc  = IEG_G_LonIncr(gdb) * resfac;
-  grid->xdef  = 2;
-  grid->yfirst= IEG_G_FirstLat(gdb) * resfac;
-  grid->ylast = IEG_G_LastLat(gdb) * resfac;
-  grid->yinc  = IEG_G_LatIncr(gdb) * resfac;
-  grid->ydef  = 2;
-  */
-  grid->xvals = NULL;
-  grid->yvals = NULL;
 
   grid->isRotated = FALSE;
+  double xpole = 0, ypole = 0;
   if ( IEG_G_GridType(gdb) == 10 )
     {
-      grid->isRotated = TRUE;
-      grid->ypole     = - IEG_G_LatSP(gdb) * resfac;
-      grid->xpole     =   IEG_G_LonSP(gdb) * resfac - 180;
-      grid->angle     = 0;
+      xpole =   IEG_G_LonSP(gdb) * resfac - 180;
+      ypole = - IEG_G_LatSP(gdb) * resfac;
+      if ( gridtype == GRID_LONLAT )
+        {
+          grid->isRotated = TRUE;
+          grid->rll.xpole = xpole;
+          grid->rll.ypole = ypole;
+          grid->rll.angle = 0;
+        }
+      else
+        grid->projtype = CDI_PROJ_RLL;
     }
 
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
   int gridID = gridAdded.Id;
-  if (!gridAdded.isNew) Free(grid);
+  if ( !gridAdded.isNew ) Free(grid);
+  else if ( gridtype == GRID_PROJECTION ) gridDefProjParamRLL(gridID, xpole, ypole, 0);
 
   int leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
-
   if ( leveltype == ZAXIS_HYBRID )
     {
       double tmpvct[100];
       size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
 
-      for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
-      for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50];
+      for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
+      for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50];
 
       varDefVCT(vctsize, tmpvct);
     }
@@ -761,6 +691,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
   int datatype = iegInqDatatype(prec);
 
   int varID;
+  int levelID = 0;
   varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
 	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
                NULL, NULL, NULL, NULL, NULL, NULL);
@@ -772,8 +703,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
   streamptr->nrecs++;
 
   if ( CDI_Debug )
-    Message("varID = %d gridID = %d levelID = %d",
-	    varID, gridID, levelID);
+    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
 }
 
 #if 0
@@ -783,9 +713,8 @@ void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int
 {
   int varID = 0;
   int levelID = 0;
-  record_t *record;
 
-  record  = &streamptr->tsteps[tsID].records[recID];
+  record_t *record  = &streamptr->tsteps[tsID].records[recID];
 
   if ( param != (*record).param || level != (*record).ilevel )
     Error("inconsistent timestep");
@@ -805,17 +734,15 @@ void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int
 }
 #endif
 
-static void iegDateTime(int *pdb, int *date, int *time)
+static
+void iegDateTime(int *pdb, int *date, int *time)
 {
-  int ryear, rmonth, rday, rhour, rminute;
-
-  ryear   = IEG_P_Year(pdb);
-
-  rmonth  = IEG_P_Month(pdb);
-  rday    = IEG_P_Day(pdb);
+  int ryear   = IEG_P_Year(pdb);
+  int rmonth  = IEG_P_Month(pdb);
+  int rday    = IEG_P_Day(pdb);
 
-  rhour   = IEG_P_Hour(pdb);
-  rminute = IEG_P_Minute(pdb);
+  int rhour   = IEG_P_Hour(pdb);
+  int rminute = IEG_P_Minute(pdb);
 
   if ( rminute == -1 ) rminute = 0;
 
@@ -826,51 +753,39 @@ static void iegDateTime(int *pdb, int *date, int *time)
 static
 void iegScanTimestep1(stream_t *streamptr)
 {
-  int prec = 0;
-  int status;
-  int fileID;
-  int tabnum;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   DateTime datetime0 = { LONG_MIN, LONG_MIN };
-  int tsID;
-  int varID;
-  size_t recsize;
   off_t recpos;
-  int nrecords, nrecs, recID;
-  int taxisID = -1;
-  taxis_t *taxis;
-  int vlistID;
-  IEGCOMPVAR compVar, compVar0;
+  iegcompvar_t compVar, compVar0;
   iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
 
   streamptr->curTsID = 0;
 
-  tsID  = tstepsNewEntry(streamptr);
-  taxis = &streamptr->tsteps[tsID].taxis;
+  int tsID = tstepsNewEntry(streamptr);
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   if ( tsID != 0 )
     Error("Internal problem! tstepsNewEntry returns %d", tsID);
 
-  fileID = streamptr->fileID;
+  int fileID = streamptr->fileID;
 
-  nrecs = 0;
+  int nrecs = 0;
   while ( TRUE )
     {
       recpos = fileGetPos(fileID);
-      status = iegRead(fileID, iegp);
+      int status = iegRead(fileID, iegp);
       if ( status != 0 )
 	{
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      recsize = (size_t)(fileGetPos(fileID) - recpos);
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
-      prec   = iegp->dprec;
-      rcode  = IEG_P_Parameter(iegp->ipdb);
-      tabnum = IEG_P_CodeTable(iegp->ipdb);
-      param  = cdiEncodeParam(rcode, tabnum, 255);
+      int prec   = iegp->dprec;
+      int rcode  = IEG_P_Parameter(iegp->ipdb);
+      int tabnum = IEG_P_CodeTable(iegp->ipdb);
+      int param  = cdiEncodeParam(rcode, tabnum, 255);
 
+      int rlevel = 0;
       if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
 	rlevel = IEG_P_Level1(iegp->ipdb);
       else
@@ -878,6 +793,7 @@ void iegScanTimestep1(stream_t *streamptr)
 
       if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
 
+      int vdate = 0, vtime = 0;
       iegDateTime(iegp->ipdb, &vdate, &vtime);
 
       if ( nrecs == 0 )
@@ -889,12 +805,13 @@ void iegScanTimestep1(stream_t *streamptr)
 	{
 	  compVar.param = param;
           compVar.level = rlevel;
+          int recID = 0;
 	  for ( recID = 0; recID < nrecs; recID++ )
 	    {
 	      compVar0.param = streamptr->tsteps[0].records[recID].param;
 	      compVar0.level = streamptr->tsteps[0].records[recID].ilevel;
 
-	      if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 ) break;
+	      if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 ) break;
 	    }
 	  if ( recID < nrecs ) break;
 	  DateTime datetime = { .date = vdate, .time = vtime};
@@ -914,17 +831,17 @@ void iegScanTimestep1(stream_t *streamptr)
 
   cdi_generate_vars(streamptr);
 
-  taxisID = taxisCreate(TAXIS_ABSOLUTE);
+  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
   taxis->vdate = (int)datetime0.date;
   taxis->vtime = (int)datetime0.time;
 
-  vlistID = streamptr->vlistID;
+  int vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
 
   vlist_check_contents(vlistID);
 
-  nrecords = streamptr->tsteps[0].nallrecs;
+  int nrecords = streamptr->tsteps[0].nallrecs;
   if ( nrecords < streamptr->tsteps[0].recordSize )
     {
       streamptr->tsteps[0].recordSize = nrecords;
@@ -935,7 +852,7 @@ void iegScanTimestep1(stream_t *streamptr)
 
   streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
 
   if ( streamptr->ntsteps == -1 )
@@ -953,7 +870,7 @@ void iegScanTimestep1(stream_t *streamptr)
       if ( taxis->vdate == 0 && taxis->vtime == 0 )
 	{
 	  streamptr->ntsteps = 0;
-	  for ( varID = 0; varID < streamptr->nvars; varID++ )
+	  for ( int varID = 0; varID < streamptr->nvars; varID++ )
 	    {
 	      vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
 	    }
@@ -964,67 +881,55 @@ void iegScanTimestep1(stream_t *streamptr)
 static
 int iegScanTimestep2(stream_t *streamptr)
 {
-  int status;
-  int fileID;
-  int tabnum;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  int tsID;
-  int varID;
-  size_t recsize;
   off_t recpos = 0;
-  int nrecords, nrecs, recID, rindex;
-  int nextstep;
-  taxis_t *taxis;
-  int vlistID;
-  IEGCOMPVAR compVar, compVar0;
+  iegcompvar_t compVar, compVar0;
   iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
 
   streamptr->curTsID = 1;
 
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  tsID = streamptr->rtsteps;
+  int tsID = streamptr->rtsteps;
   if ( tsID != 1 )
     Error("Internal problem! unexpected timestep %d", tsID+1);
 
-  taxis = &streamptr->tsteps[tsID].taxis;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
   cdi_create_records(streamptr, tsID);
 
-  nrecords = streamptr->tsteps[0].nallrecs;
+  int nrecords = streamptr->tsteps[0].nallrecs;
   streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
   streamptr->tsteps[1].nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
 
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
-      varID = streamptr->tsteps[0].records[recID].varID;
       streamptr->tsteps[tsID].records[recID].position =
 	streamptr->tsteps[0].records[recID].position;
       streamptr->tsteps[tsID].records[recID].size     =
 	streamptr->tsteps[0].records[recID].size;
     }
 
-  for ( rindex = 0; rindex <= nrecords; rindex++ )
+  for ( int rindex = 0; rindex <= nrecords; rindex++ )
     {
       recpos = fileGetPos(fileID);
-      status = iegRead(fileID, iegp);
+      int status = iegRead(fileID, iegp);
       if ( status != 0 )
 	{
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = (size_t)(fileGetPos(fileID) - recpos);
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
-      rcode  = IEG_P_Parameter(iegp->ipdb);
-      tabnum = IEG_P_CodeTable(iegp->ipdb);
-      param  = cdiEncodeParam(rcode, tabnum, 255);
+      int rcode  = IEG_P_Parameter(iegp->ipdb);
+      int tabnum = IEG_P_CodeTable(iegp->ipdb);
+      int param  = cdiEncodeParam(rcode, tabnum, 255);
 
+      int rlevel = 0;
       if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
 	rlevel = IEG_P_Level1(iegp->ipdb);
       else
@@ -1032,6 +937,7 @@ int iegScanTimestep2(stream_t *streamptr)
 
       if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
 
+      int vdate = 0, vtime = 0;
       iegDateTime(iegp->ipdb, &vdate, &vtime);
 
       if ( rindex == 0 )
@@ -1043,17 +949,18 @@ int iegScanTimestep2(stream_t *streamptr)
 
       compVar.param = param;
       compVar.level = rlevel;
-      nextstep = FALSE;
+      bool nextstep = false;
+      int recID = 0;
       for ( recID = 0; recID < nrecords; recID++ )
 	{
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
 	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
-	  if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 )
+	  if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 )
 	    {
 	      if ( streamptr->tsteps[tsID].records[recID].used )
 		{
-		  nextstep = TRUE;
+		  nextstep = true;
 		}
 	      else
 		{
@@ -1068,7 +975,7 @@ int iegScanTimestep2(stream_t *streamptr)
 	  char paramstr[32];
 	  cdiParamToString(param, paramstr, sizeof(paramstr));
 	  Warning("param %s level %d not defined at timestep 1", paramstr, rlevel);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( nextstep ) break;
@@ -1081,24 +988,24 @@ int iegScanTimestep2(stream_t *streamptr)
       compVar0.param = streamptr->tsteps[tsID].records[recID].param;
       compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
-      if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
+      if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
     }
 
-  nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  int nrecs = 0;
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
       if ( ! streamptr->tsteps[tsID].records[recID].used )
 	{
-	  varID = streamptr->tsteps[tsID].records[recID].varID;
+	  int varID = streamptr->tsteps[tsID].records[recID].varID;
           vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
 	}
       else
@@ -1120,43 +1027,31 @@ int iegScanTimestep2(stream_t *streamptr)
       streamptr->tsteps[tsID].position = recpos;
     }
 
-  return (0);
+  return 0;
 }
 
 
 int iegInqContents(stream_t *streamptr)
 {
-  int fileID;
-  int status = 0;
-
-  fileID = streamptr->fileID;
+  int fileID = streamptr->fileID;
 
   streamptr->curTsID = 0;
 
   iegScanTimestep1(streamptr);
 
+  int status = 0;
   if ( streamptr->ntsteps == -1 ) status = iegScanTimestep2(streamptr);
 
   fileSetPos(fileID, 0, SEEK_SET);
 
-  return (status);
+  return status;
 }
 
 static
 long iegScanTimestep(stream_t *streamptr)
 {
-  int status;
-  int fileID;
-  int tsID;
-  int tabnum;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  size_t recsize = 0;
   off_t recpos = 0;
-  int recID;
-  taxis_t *taxis;
-  int rindex, nrecs = 0;
-  IEGCOMPVAR compVar, compVar0;
+  iegcompvar_t compVar, compVar0;
   iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
 
   if ( CDI_Debug )
@@ -1170,9 +1065,10 @@ long iegScanTimestep(stream_t *streamptr)
   if ( streamptr->rtsteps == 0 )
     Error("Internal problem! Missing contents.");
 
-  tsID  = streamptr->rtsteps;
-  taxis = &streamptr->tsteps[tsID].taxis;
+  int tsID = streamptr->rtsteps;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
+  int nrecs = 0;
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
       cdi_create_records(streamptr, tsID);
@@ -1182,28 +1078,29 @@ long iegScanTimestep(stream_t *streamptr)
       streamptr->tsteps[tsID].nrecs = nrecs;
       streamptr->tsteps[tsID].recIDs
         = (int *) Malloc((size_t)nrecs * sizeof (int));
-      for ( recID = 0; recID < nrecs; recID++ )
+      for ( int recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
-      fileID = streamptr->fileID;
+      int fileID = streamptr->fileID;
 
       fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
-      for ( rindex = 0; rindex <= nrecs; rindex++ )
+      for ( int rindex = 0; rindex <= nrecs; rindex++ )
 	{
 	  recpos = fileGetPos(fileID);
-	  status = iegRead(fileID, iegp);
+	  int status = iegRead(fileID, iegp);
 	  if ( status != 0 )
 	    {
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = (size_t)(fileGetPos(fileID) - recpos);
+	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
-	  rcode  = IEG_P_Parameter(iegp->ipdb);
-	  tabnum = IEG_P_CodeTable(iegp->ipdb);
-	  param  = cdiEncodeParam(rcode, tabnum, 255);
+	  int rcode  = IEG_P_Parameter(iegp->ipdb);
+	  int tabnum = IEG_P_CodeTable(iegp->ipdb);
+	  int param  = cdiEncodeParam(rcode, tabnum, 255);
 
+          int rlevel = 0;
 	  if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
 	    rlevel = IEG_P_Level1(iegp->ipdb);
 	  else
@@ -1211,11 +1108,12 @@ long iegScanTimestep(stream_t *streamptr)
 
 	  if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
 
+          int vdate = 0, vtime = 0;
 	  iegDateTime(iegp->ipdb, &vdate, &vtime);
 
 	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
 	  if ( rindex == nrecs ) continue;
-	  recID = streamptr->tsteps[tsID].recIDs[rindex];
+	  int recID = streamptr->tsteps[tsID].recIDs[rindex];
 
 	  if ( rindex == 0 )
 	    {
@@ -1229,7 +1127,7 @@ long iegScanTimestep(stream_t *streamptr)
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
 	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
-	  if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
+	  if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) != 0 )
 	    {
 	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		      tsID, recID,
@@ -1249,7 +1147,7 @@ long iegScanTimestep(stream_t *streamptr)
 
       if ( streamptr->ntsteps != streamptr->rtsteps )
 	{
-	  tsID = tstepsNewEntry(streamptr);
+	  int tsID = tstepsNewEntry(streamptr);
 	  if ( tsID != streamptr->rtsteps )
 	    Error("Internal error. tsID = %d", tsID);
 
@@ -1267,14 +1165,12 @@ long iegScanTimestep(stream_t *streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  return (streamptr->ntsteps);
+  return streamptr->ntsteps;
 }
 
 
 int iegInqTimestep(stream_t *streamptr, int tsID)
 {
-  int nrecs;
-
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
 
@@ -1285,95 +1181,35 @@ int iegInqTimestep(stream_t *streamptr, int tsID)
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = iegScanTimestep(streamptr);
 
-  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
-    {
-      nrecs = 0;
-    }
-  else
+  int nrecs = 0;
+  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) )
     {
       streamptr->curTsID = tsID;
       nrecs = streamptr->tsteps[tsID].nrecs;
     }
 
-  return (nrecs);
-}
-
-
-void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
-{
-  int vlistID, fileID;
-  int levID, nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int tsid;
-  int recID;
-  int i;
-  double missval;
-  void *iegp = streamptr->record->exsep;
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
-  currentfilepos = fileGetPos(fileID);
-
-  for (levID = 0; levID < nlevs; levID++)
-    {
-      /* NOTE: tiles are not supported here! */
-      recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-      recpos = streamptr->tsteps[tsid].records[recID].position;
-      fileSetPos(fileID, recpos, SEEK_SET);
-      iegRead(fileID, iegp);
-      iegInqDataDP(iegp, &data[levID*gridsize]);
-    }
-  fileSetPos(fileID, currentfilepos, SEEK_SET);
-
-  *nmiss = 0;
-  for ( i = 0; i < nlevs*gridsize; i++ )
-    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
-      {
-	data[i] = missval;
-	(*nmiss)++;
-      }
+  return nrecs;
 }
 
 
 void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
 {
-  int vlistID, fileID;
-  int nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int tsid;
-  int recID;
-  int i;
-  double missval;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
+
   void *iegp = streamptr->record->exsep;
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
   /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d",
-	     nlevs, gridID, gridsize);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
+  int tsid     = streamptr->curTsID;
 
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
   /* NOTE: tiles are not supported here! */
-  recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-  recpos = streamptr->tsteps[tsid].records[recID].position;
+  int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+  off_t recpos = streamptr->tsteps[tsid].records[recID].position;
   fileSetPos(fileID, recpos, SEEK_SET);
   iegRead(fileID, iegp);
   iegInqDataDP(iegp, data);
@@ -1381,7 +1217,7 @@ void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
   fileSetPos(fileID, currentfilepos, SEEK_SET);
 
   *nmiss = 0;
-  for ( i = 0; i < gridsize; i++ )
+  for ( int i = 0; i < gridsize; i++ )
     if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
       {
 	data[i] = missval;
@@ -1390,101 +1226,70 @@ void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
 }
 
 
-void iegWriteVarDP(stream_t *streamptr, int varID, const double *data)
+void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
 {
-  int fileID;
-  int levID, nlevs, gridID, gridsize;
-  int zaxisID;
-  int datatype;
-  int tsID;
-  int vlistID;
-  int i;
-  int date, time;
-  int param, pdis, pcat, pnum;
-  double refval;
-  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
-  if ( CDI_Debug )
-    Message("streamID = %d  varID = %d", streamptr->self, varID);
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) streamptr->vars[varID].recordTable[0].nlevs;
 
-  iegInitMem(iegp);
-  for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
+  for ( size_t levID = 0; levID < nlevs; levID++)
+    iegReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss);
+}
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  nlevs    = zaxisInqSize(zaxisID);
 
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
+{
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
+
+  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+  iegInitMem(iegp);
+  for ( int i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
 
-  param    = vlistInqVarParam(vlistID, varID);
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
+  int tsID     = streamptr->curTsID;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int zaxisID  = vlistInqVarZaxis(vlistID, varID);
+
+  int param    = vlistInqVarParam(vlistID, varID);
+  int pdis, pcat, pnum;
   cdiDecodeParam(param, &pnum, &pcat, &pdis);
   IEG_P_Parameter(iegp->ipdb) = pnum;
   if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
-  date     = streamptr->tsteps[tsID].taxis.vdate;
-  time     = streamptr->tsteps[tsID].taxis.vtime;
 
+  int date     = streamptr->tsteps[tsID].taxis.vdate;
+  int time     = streamptr->tsteps[tsID].taxis.vtime;
   iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
   iegDefGrid(iegp->igdb, gridID);
+  iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID);
 
-  datatype = vlistInqVarDatatype(vlistID, varID);
-
-  iegp->dprec = iegDefDatatype(datatype);
+  iegp->dprec = iegDefDatatype(vlistInqVarDatatype(vlistID, varID));
 
-  for ( levID = 0;  levID < nlevs; levID++ )
-    {
-      iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID);
+  int gridsize = gridInqSize(gridID);
 
-      refval = data[0];
-      for ( i = 1; i < gridsize; i++ )
-	if ( data[levID*gridsize+i] < refval ) refval = data[levID*gridsize+i];
+  double refval = data[0];
+  for ( int i = 1; i < gridsize; i++ )
+    if ( data[i] < refval ) refval = data[i];
 
-      iegp->refval = refval;
+  iegp->refval = refval;
 
-      iegDefDataDP(iegp, &data[levID*gridsize]);
-      iegWrite(fileID, iegp);
-    }
+  iegDefDataDP(iegp, data);
+  iegWrite(fileID, iegp);
 }
 
 
-void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
+void iegWriteVarDP(stream_t *streamptr, int varID, const double *data)
 {
-  int fileID;
-  int gridID;
-  int zaxisID;
-  /* double level; */
-  int datatype;
-  /* int tsID; */
-  int vlistID;
-  /* int param, date, time, datasize; */
-  iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  /* tsID     = streamptr->curTsID; */
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  (void)levID;
-  /* level    = zaxisInqLevel(zaxisID, levID); */
-
-  if ( CDI_Debug )
-    Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
-  /* param = vlistInqVarParam(vlistID, varID); */
-  /* date = streamptr->tsteps[tsID].taxis.vdate; */
-  /* time = streamptr->tsteps[tsID].taxis.vtime; */
-  /* datasize = gridInqSize(gridID); */
-
-  datatype = vlistInqVarDatatype(vlistID, varID);
-
-  iegp->dprec = iegDefDatatype(datatype);
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
 
-  iegDefDataDP(iegp, data);
-  iegWrite(fileID, iegp);
+  for ( size_t levID = 0;  levID < nlevs; levID++ )
+    iegWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
 }
 
 #endif /* HAVE_LIBIEG */
diff --git a/src/stream_record.c b/src/stream_record.c
index ea43cd1d605c6f3e6dbd5a130bc7bb8c65e31a78..23b1f4060145d17a5ea6ecdbc6c6056f9245d3fe 100644
--- a/src/stream_record.c
+++ b/src/stream_record.c
@@ -86,18 +86,19 @@ int recordNewEntry(stream_t *streamptr, int tsID)
 static
 void cdiInitRecord(stream_t *streamptr)
 {
-  streamptr->record = (Record *) Malloc(sizeof(Record));
-
-  streamptr->record->param      = 0;
-  streamptr->record->level      = 0;
-  streamptr->record->date       = 0;
-  streamptr->record->time       = 0;
-  streamptr->record->gridID     = 0;
-  streamptr->record->buffer     = NULL;
-  streamptr->record->buffersize = 0;
-  streamptr->record->position   = 0;
-  streamptr->record->varID      = 0;
-  streamptr->record->levelID    = CDI_UNDEFID;
+  Record *record = (Record *) Malloc(sizeof(Record));
+  streamptr->record = record;
+
+  record->param      = 0;
+  record->level      = 0;
+  record->date       = 0;
+  record->time       = 0;
+  record->gridID     = 0;
+  record->buffer     = NULL;
+  record->buffersize = 0;
+  record->position   = 0;
+  record->varID      = 0;
+  record->levelID    = CDI_UNDEFID;
 }
 
 
@@ -170,14 +171,15 @@ void streamDefRecord(int streamID, int varID, int levelID)
   int param   = vlistInqVarParam(vlistID, varID);
   int level   = (int)(zaxisInqLevel(zaxisID, levelID));
 
-  streamptr->record->varID    = varID;
-  streamptr->record->levelID  = levelID;
-  streamptr->record->param    = param;
-  streamptr->record->level    = level;
-  streamptr->record->date     = streamptr->tsteps[tsID].taxis.vdate;
-  streamptr->record->time     = streamptr->tsteps[tsID].taxis.vtime;
-  streamptr->record->gridID   = gridID;
-  streamptr->record->prec     = vlistInqVarDatatype(vlistID, varID);
+  Record *record = streamptr->record;
+  record->varID    = varID;
+  record->levelID  = levelID;
+  record->param    = param;
+  record->level    = level;
+  record->date     = streamptr->tsteps[tsID].taxis.vdate;
+  record->time     = streamptr->tsteps[tsID].taxis.vtime;
+  record->gridID   = gridID;
+  record->prec     = vlistInqVarDatatype(vlistID, varID);
 
   switch (streamptr->filetype)
     {
@@ -295,7 +297,6 @@ void streamCopyRecord(int streamID2, int streamID1)
 void cdi_create_records(stream_t *streamptr, int tsID)
 {
   unsigned nrecords, maxrecords;
-  record_t *records;
 
   tsteps_t *sourceTstep = streamptr->tsteps;
   tsteps_t *destTstep = sourceTstep + tsID;
@@ -339,10 +340,8 @@ void cdi_create_records(stream_t *streamptr, int tsID)
     }
   //  printf("tsID, nrecords %d %d\n", tsID, nrecords);
 
-  if ( maxrecords > 0 )
-    records = (record_t *) Malloc(maxrecords*sizeof(record_t));
-  else
-    records = NULL;
+  record_t *records = NULL;
+  if ( maxrecords > 0 ) records = (record_t *) Malloc(maxrecords*sizeof(record_t));
 
   destTstep->records    = records;
   destTstep->recordSize = (int)maxrecords;
@@ -373,6 +372,33 @@ void cdi_create_records(stream_t *streamptr, int tsID)
 	}
     }
 }
+
+#include "file.h"
+
+void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name)
+{
+  int fileID1 = streamptr1->fileID;
+  int fileID2 = streamptr2->fileID;
+
+  int tsID    = streamptr1->curTsID;
+  int vrecID  = streamptr1->tsteps[tsID].curRecID;
+  int recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
+  off_t recpos  = streamptr1->tsteps[tsID].records[recID].position;
+  size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
+
+  if (fileSetPos(fileID1, recpos, SEEK_SET) != 0)
+    Error("Cannot seek input file for %s record copy!", container_name);
+
+  char *buffer = (char *) Malloc(recsize);
+
+  if (fileRead(fileID1, buffer, recsize) != recsize)
+    Error("Failed to read record from %s file for copying!", container_name);
+
+  if (fileWrite(fileID2, buffer, recsize) != recsize)
+    Error("Failed to write record to %s file when copying!", container_name);
+
+  Free(buffer);
+}
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/src/stream_srv.c b/src/stream_srv.c
index 52752b0df7b9766c11664817fc49fec52fcd165d..8d05996f261f15b61add82b78e93ea47d6f20e23 100644
--- a/src/stream_srv.c
+++ b/src/stream_srv.c
@@ -16,16 +16,14 @@
 #include "varscan.h"
 #include "datetime.h"
 #include "service.h"
-#include "stream_fcommon.h"
 #include "stream_srv.h"
 #include "vlist.h"
+#include "exse.h"
 
 
 #undef  UNDEFID
 #define UNDEFID  CDI_UNDEFID
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
 
 #if defined (HAVE_LIBSERVICE)
 
@@ -33,34 +31,25 @@
 typedef struct {
   int param;
   int level;
-} SRVCOMPVAR;
+} srvcompvar_t;
 
 
-static int srvInqDatatype(int prec)
+static
+int srvInqDatatype(int prec)
 {
-  int datatype;
-
-  if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
-  else                            datatype = DATATYPE_FLT32;
-
-  return (datatype);
+  return (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32;
 }
 
-
-static int srvDefDatatype(int datatype)
+static
+int srvDefDatatype(int datatype)
 {
-  int prec;
-
   if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
     Error("CDI/SERVICE library does not support complex numbers!");
 
   if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
     datatype = DATATYPE_FLT32;
 
-  if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION;
-  else                              prec = SINGLE_PRECISION;
-
-  return (prec);
+  return (datatype == DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
 }
 
 /* not used
@@ -96,19 +85,12 @@ int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
 
   *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
 
-  return (1);
+  return 1;
 }
 */
 
 void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
-  int status;
-  int header[8];
-  int gridID;
-  int i, size;
-  double missval;
-  void *srvp = streamptr->record->exsep;
-
   int vlistID  = streamptr->vlistID;
   int fileID   = streamptr->fileID;
   int tsID     = streamptr->curTsID;
@@ -119,21 +101,23 @@ void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 
   fileSetPos(fileID, recpos, SEEK_SET);
 
-  status = srvRead(fileID, srvp);
+  void *srvp = streamptr->record->exsep;
+  int status = srvRead(fileID, srvp);
   if ( status != 0 )
     Error("Failed to read record from SRV file");
 
+  int header[8];
   srvInqHeader(srvp, header);
   srvInqDataDP(srvp, data);
 
-  missval = vlistInqVarMissval(vlistID, varID);
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  size    = gridInqSize(gridID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int size    = gridInqSize(gridID);
 
   streamptr->numvals += size;
 
   *nmiss = 0;
-  for ( i = 0; i < size; i++ )
+  for ( int i = 0; i < size; i++ )
     if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
       {
 	data[i] = missval;
@@ -150,20 +134,21 @@ void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 
 void srvDefRecord(stream_t *streamptr)
 {
-  int header[8];
-  Record *restrict record = streamptr->record;
-  srvrec_t *restrict srvp = (srvrec_t*) record->exsep;
-  int gridID = record->gridID;
+  Record *record = streamptr->record;
+  srvrec_t *srvp = (srvrec_t*) record->exsep;
 
   int pdis, pcat, pnum;
   cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
+
+  int header[8];
   header[0] = pnum;
   header[1] = record->level;
   header[2] = record->date;
   header[3] = record->time;
 
+  int gridID = record->gridID;
   int xsize = gridInqXsize(gridID),
-    ysize = gridInqYsize(gridID);
+      ysize = gridInqYsize(gridID);
   if ( xsize == 0 || ysize == 0 )
     {
       xsize = gridInqSize(gridID);
@@ -179,7 +164,6 @@ void srvDefRecord(stream_t *streamptr)
   header[7] = 0;
 
   int datatype = record->prec;
-
   srvp->dprec = srvDefDatatype(datatype);
 
   srvDefHeader(srvp, header);
@@ -209,14 +193,12 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
   record->param    = param;
   record->ilevel   = level;
 
-  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+  grid_t *grid = (grid_t*) Malloc(sizeof(*grid));
   grid_init(grid);
   cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize);
-  grid->xsize = xsize;
-  grid->ysize = ysize;
-  grid->xvals = NULL;
-  grid->yvals = NULL;
-  struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+  grid->x.size = xsize;
+  grid->y.size = ysize;
+  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
   int gridID = gridAdded.Id;
   if (!gridAdded.isNew) Free(grid);
   /*
@@ -241,8 +223,7 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
   streamptr->nrecs++;
 
   if ( CDI_Debug )
-    Message("varID = %d gridID = %d levelID = %d",
-	    varID, gridID, levelID);
+    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
 }
 
 static
@@ -262,7 +243,6 @@ void srvScanTimestep1(stream_t *streamptr)
     taxis = &streamptr->tsteps[tsID].taxis;
   }
 
-
   int fileID = streamptr->fileID;
 
   int nrecs = 0;
@@ -368,54 +348,43 @@ static
 int srvScanTimestep2(stream_t *streamptr)
 {
   int header[8];
-  int status;
-  int fileID;
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  int tsID;
-  int varID;
   off_t recpos = 0;
-  int nrecords, nrecs, recID, rindex;
-  int nextstep;
-  taxis_t *taxis;
-  int vlistID;
-  SRVCOMPVAR compVar, compVar0;
+  srvcompvar_t compVar, compVar0;
   void *srvp = streamptr->record->exsep;
 
   streamptr->curTsID = 1;
 
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  tsID = streamptr->rtsteps;
+  int tsID = streamptr->rtsteps;
   if ( tsID != 1 )
     Error("Internal problem! unexpected timestep %d", tsID+1);
 
-  taxis = &streamptr->tsteps[tsID].taxis;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
   cdi_create_records(streamptr, tsID);
 
-  nrecords = streamptr->tsteps[0].nallrecs;
+  int nrecords = streamptr->tsteps[0].nallrecs;
   streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
 
-  for ( recID = 0; recID < nrecords; recID++ )
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
-      varID = streamptr->tsteps[0].records[recID].varID;
       streamptr->tsteps[tsID].records[recID].position =
 	streamptr->tsteps[0].records[recID].position;
       streamptr->tsteps[tsID].records[recID].size     =
 	streamptr->tsteps[0].records[recID].size;
     }
 
-  for ( rindex = 0; rindex <= nrecords; rindex++ )
+  for ( int rindex = 0; rindex <= nrecords; rindex++ )
     {
       recpos = fileGetPos(fileID);
-      status = srvRead(fileID, srvp);
+      int status = srvRead(fileID, srvp);
       if ( status != 0 )
 	{
 	  streamptr->ntsteps = 2;
@@ -425,12 +394,12 @@ int srvScanTimestep2(stream_t *streamptr)
 
       srvInqHeader(srvp, header);
 
-      rcode  = header[0];
-      rlevel = header[1];
-      vdate  = header[2];
-      vtime  = header[3];
+      int rcode  = header[0];
+      int rlevel = header[1];
+      int vdate  = header[2];
+      int vtime  = header[3];
 
-      param = cdiEncodeParam(rcode, 255, 255);
+      int param = cdiEncodeParam(rcode, 255, 255);
 
       if ( rindex == 0 )
 	{
@@ -441,17 +410,18 @@ int srvScanTimestep2(stream_t *streamptr)
 
       compVar.param = param;
       compVar.level = rlevel;
-      nextstep = FALSE;
+      bool nextstep = false;
+      int recID;
       for ( recID = 0; recID < nrecords; recID++ )
 	{
 	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
 	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
-	  if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) == 0 )
+	  if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) == 0 )
 	    {
 	      if ( streamptr->tsteps[tsID].records[recID].used )
 		{
-		  nextstep = TRUE;
+		  nextstep = true;
 		}
 	      else
 		{
@@ -464,7 +434,7 @@ int srvScanTimestep2(stream_t *streamptr)
       if ( recID == nrecords )
 	{
 	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       if ( nextstep ) break;
@@ -477,24 +447,24 @@ int srvScanTimestep2(stream_t *streamptr)
       compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
       compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
-      if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) != 0 )
+      if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
 		  streamptr->tsteps[tsID].records[recID].param, param,
 		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	  return (CDI_EUFSTRUCT);
+	  return CDI_EUFSTRUCT;
 	}
 
       streamptr->tsteps[1].records[recID].position = recpos;
     }
 
-  nrecs = 0;
-  for ( recID = 0; recID < nrecords; recID++ )
+  int nrecs = 0;
+  for ( int recID = 0; recID < nrecords; recID++ )
     {
       if ( ! streamptr->tsteps[tsID].records[recID].used )
 	{
-	  varID = streamptr->tsteps[tsID].records[recID].varID;
+	  int varID = streamptr->tsteps[tsID].records[recID].varID;
           vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
 	}
       else
@@ -516,40 +486,33 @@ int srvScanTimestep2(stream_t *streamptr)
       streamptr->tsteps[tsID].position = recpos;
     }
 
-  return (0);
+  return 0;
 }
 
 
 int srvInqContents(stream_t *streamptr)
 {
-  int fileID;
-  int status = 0;
-
-  fileID = streamptr->fileID;
-
   streamptr->curTsID = 0;
 
   srvScanTimestep1(streamptr);
 
+  int status = 0;
   if ( streamptr->ntsteps == -1 ) status = srvScanTimestep2(streamptr);
 
+  int fileID = streamptr->fileID;
   fileSetPos(fileID, 0, SEEK_SET);
 
-  return (status);
+  return status;
 }
 
 static
 long srvScanTimestep(stream_t *streamptr)
 {
   int header[8];
-  int status;
-  int fileID;
   /* int rxsize = 0, rysize = 0; */
-  int param = 0;
-  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   off_t recpos = 0;
   int recID;
-  int rindex, nrecs = 0;
+  int nrecs = 0;
   void *srvp = streamptr->record->exsep;
   /*
   if ( CDI_Debug )
@@ -575,14 +538,14 @@ long srvScanTimestep(stream_t *streamptr)
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
-      fileID = streamptr->fileID;
+      int fileID = streamptr->fileID;
 
       fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
 
-      for ( rindex = 0; rindex <= nrecs; rindex++ )
+      for ( int rindex = 0; rindex <= nrecs; rindex++ )
 	{
 	  recpos = fileGetPos(fileID);
-	  status = srvRead(fileID, srvp);
+	  int status = srvRead(fileID, srvp);
 	  if ( status != 0 )
 	    {
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
@@ -592,14 +555,14 @@ long srvScanTimestep(stream_t *streamptr)
 
 	  srvInqHeader(srvp, header);
 
-	  rcode  = header[0];
-	  rlevel = header[1];
-	  vdate  = header[2];
-	  vtime  = header[3];
+	  int rcode  = header[0];
+	  int rlevel = header[1];
+	  int vdate  = header[2];
+	  int vtime  = header[3];
           /* rxsize = header[4]; */
           /* rysize = header[5]; */
 
-	  param = cdiEncodeParam(rcode, 255, 255);
+	  int param = cdiEncodeParam(rcode, 255, 255);
 
 	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
 	  if ( rindex == nrecs ) continue;
@@ -651,128 +614,61 @@ long srvScanTimestep(stream_t *streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  return (streamptr->ntsteps);
+  return streamptr->ntsteps;
 }
 
 
 int srvInqTimestep(stream_t *streamptr, int tsID)
 {
-  long ntsteps;
-  int nrecs;
-
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
 
   if ( CDI_Debug )
     Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
 
-  ntsteps = UNDEFID;
+  long ntsteps = UNDEFID;
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = srvScanTimestep(streamptr);
 
-  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID )
-    {
-      nrecs = 0;
-    }
-  else
+  int nrecs = 0;
+  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID) )
     {
       streamptr->curTsID = tsID;
       nrecs = streamptr->tsteps[tsID].nrecs;
     }
 
-  return (nrecs);
-}
-
-
-void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
-{
-  int vlistID, fileID;
-  int levID, nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int header[8];
-  int tsid;
-  int recID;
-  int i;
-  double missval;
-  void *srvp = streamptr->record->exsep;
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
-  currentfilepos = fileGetPos(fileID);
-
-  for (levID = 0; levID < nlevs; levID++)
-    {
-      /* NOTE: tiles are not supported here! */
-      recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-      recpos = streamptr->tsteps[tsid].records[recID].position;
-      fileSetPos(fileID, recpos, SEEK_SET);
-      if (srvRead(fileID, srvp) < 0)
-        abort();
-      srvInqHeader(srvp, header);
-      srvInqDataDP(srvp, &data[levID*gridsize]);
-    }
-  fileSetPos(fileID, currentfilepos, SEEK_SET);
-
-  *nmiss = 0;
-  for ( i = 0; i < nlevs*gridsize; i++ )
-    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
-      {
-	data[i] = missval;
-	(*nmiss)++;
-      }
+  return nrecs;
 }
 
 
 void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
 {
-  int vlistID, fileID;
-  int nlevs, gridID, gridsize;
-  off_t recpos, currentfilepos;
-  int header[8];
-  int tsid;
-  int recID;
-  int i;
-  double missval;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
+
   void *srvp = streamptr->record->exsep;
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
   /* NOTE: tiles are not supported here! */
-  nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
-  missval  = vlistInqVarMissval(vlistID, varID);
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsid     = streamptr->curTsID;
+  double missval = vlistInqVarMissval(vlistID, varID);
+  int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
+  int tsid     = streamptr->curTsID;
 
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d",
-	     nlevs, gridID, gridsize);
-
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
   /* NOTE: tiles are not supported here! */
-  recID = streamptr->vars[varID].recordTable[0].recordID[levID];
-  recpos = streamptr->tsteps[tsid].records[recID].position;
+  int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+  off_t recpos = streamptr->tsteps[tsid].records[recID].position;
   fileSetPos(fileID, recpos, SEEK_SET);
-  if (srvRead(fileID, srvp) < 0)
-    abort();
+  if ( srvRead(fileID, srvp) < 0 ) abort();
+  int header[8];
   srvInqHeader(srvp, header);
   srvInqDataDP(srvp, data);
 
   fileSetPos(fileID, currentfilepos, SEEK_SET);
 
   *nmiss = 0;
-  for ( i = 0; i < gridsize; i++ )
+  for ( int i = 0; i < gridsize; i++ )
     if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
       {
 	data[i] = missval;
@@ -781,105 +677,39 @@ void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data,
 }
 
 
-void srvWriteVarDP(stream_t *streamptr, int varID, const double *data)
+void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
 {
-  int fileID;
-  int levID, nlevs, gridID, gridsize;
-  int zaxisID;
-  double level;
-  int header[8];
-  int xsize, ysize;
-  int datatype;
-  int tsID;
-  int vlistID;
-  int pdis, pcat, pnum;
-  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
-
-  if ( CDI_Debug )
-    Message("streamID = %d  varID = %d", streamptr->self, varID);
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  nlevs    = zaxisInqSize(zaxisID);
-
-  if ( CDI_Debug )
-    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
-  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
-
-  header[0] = pnum;
-  header[2] = streamptr->tsteps[tsID].taxis.vdate;
-  header[3] = streamptr->tsteps[tsID].taxis.vtime;
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
-  xsize = gridInqXsize(gridID);
-  ysize = gridInqYsize(gridID);
-  if ( xsize == 0 || ysize == 0 )
-    {
-      xsize = gridInqSize(gridID);
-      ysize = 1;
-    }
-  if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
-  if ( gridInqSize(gridID) != xsize*ysize )
-    Error("Internal problem with gridsize!");
-
-  header[4] = xsize;
-  header[5] = ysize;
-  header[6] = 0;
-  header[7] = 0;
-
-  datatype = vlistInqVarDatatype(vlistID, varID);
-
-  srvp->dprec = srvDefDatatype(datatype);
-
-  for ( levID = 0; levID < nlevs; levID++ )
-    {
-      level = zaxisInqLevel(zaxisID, levID);
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) streamptr->vars[varID].recordTable[0].nlevs;
 
-      header[1] = (int) level;
-      srvDefHeader(srvp, header);
-      srvDefDataDP(srvp, &data[levID*gridsize]);
-      srvWrite(fileID, srvp);
-    }
+  for ( size_t levID = 0; levID < nlevs; levID++)
+    srvReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss);
 }
 
 
 void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
 {
-  int fileID;
-  int gridID;
-  int zaxisID;
-  double level;
-  int header[8];
-  int xsize, ysize;
-  int datatype;
-  int tsID;
-  int vlistID;
-  int pdis, pcat, pnum;
-  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
-
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-  level    = zaxisInqLevel(zaxisID, levID);
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
 
-  if ( CDI_Debug )
-    Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+  int vlistID  = streamptr->vlistID;
+  int fileID   = streamptr->fileID;
+  int tsID     = streamptr->curTsID;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
 
+  int pdis, pcat, pnum;
   cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
 
+  int header[8];
   header[0] = pnum;
-  header[1] = (int) level;
+  header[1] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID);
   header[2] = streamptr->tsteps[tsID].taxis.vdate;
   header[3] = streamptr->tsteps[tsID].taxis.vtime;
 
-  xsize = gridInqXsize(gridID);
-  ysize = gridInqYsize(gridID);
+  int xsize = gridInqXsize(gridID);
+  int ysize = gridInqYsize(gridID);
   if ( xsize == 0 || ysize == 0 )
     {
       xsize = gridInqSize(gridID);
@@ -894,8 +724,9 @@ void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
   header[6] = 0;
   header[7] = 0;
 
-  datatype = vlistInqVarDatatype(vlistID, varID);
+  int datatype = vlistInqVarDatatype(vlistID, varID);
 
+  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
   srvp->dprec = srvDefDatatype(datatype);
 
   srvDefHeader(srvp, header);
@@ -903,7 +734,21 @@ void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
   srvWrite(fileID, srvp);
 }
 
+
+void srvWriteVarDP(stream_t *streamptr, int varID, const double *data)
+{
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
+
+  for ( size_t levID = 0; levID < nlevs; levID++ )
+    srvWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
+}
+
 #endif /* HAVE_LIBSERVICE */
+
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/src/taxis.c b/src/taxis.c
index a0db8d524df3a7ff27d62327eaaf9b873b2d3808..111358562e1ce094c6e5c341a270759a6698e2a9 100644
--- a/src/taxis.c
+++ b/src/taxis.c
@@ -112,7 +112,7 @@ const char *tunitNamePtr(int unitID)
   else
     name = Timeunits[0];
 
-  return (name);
+  return name;
 }
 
 #if 0
@@ -150,7 +150,7 @@ static
 void taxisDefaultValue(taxis_t* taxisptr)
 {
   taxisptr->self        = CDI_UNDEFID;
-  taxisptr->used        = FALSE;
+  taxisptr->used        = false;
   taxisptr->type        = DefaultTimeType;
   taxisptr->vdate       = 0;
   taxisptr->vtime       = 0;
@@ -161,8 +161,8 @@ void taxisDefaultValue(taxis_t* taxisptr)
   taxisptr->calendar    = cdiDefaultCalendar;
   taxisptr->unit        = DefaultTimeUnit;
   taxisptr->numavg      = 0;
-  taxisptr->climatology = FALSE;
-  taxisptr->has_bounds  = FALSE;
+  taxisptr->climatology = false;
+  taxisptr->has_bounds  = false;
   taxisptr->vdate_lb    = 0;
   taxisptr->vtime_lb    = 0;
   taxisptr->vdate_ub    = 0;
@@ -187,20 +187,19 @@ taxisNewEntry(cdiResH resH)
       reshReplace(resH, taxisptr, &taxisOps);
     }
 
-  return (taxisptr);
+  return taxisptr;
 }
 
 static
 void taxisInit (void)
 {
-  static int taxisInitialized = 0;
-  char *env;
+  static bool taxisInitialized = false;
 
   if ( taxisInitialized ) return;
 
-  taxisInitialized = 1;
+  taxisInitialized = true;
 
-  env = getenv("TAXIS_DEBUG");
+  char *env = getenv("TAXIS_DEBUG");
   if ( env ) TAXIS_Debug = atoi(env);
 }
 
@@ -248,8 +247,7 @@ taxisDefRtime(taxisID, 120000);
 */
 int taxisCreate(int taxistype)
 {
-  if ( CDI_Debug )
-    Message("taxistype: %d", taxistype);
+  if ( CDI_Debug ) Message("taxistype: %d", taxistype);
 
   taxisInit ();
 
@@ -258,10 +256,9 @@ int taxisCreate(int taxistype)
 
   int taxisID = taxisptr->self;
 
-  if ( CDI_Debug )
-    Message("taxisID: %d", taxisID);
+  if ( CDI_Debug ) Message("taxisID: %d", taxisID);
 
-  return (taxisID);
+  return taxisID;
 }
 
 void taxisDestroyKernel(taxis_t *taxisptr)
@@ -303,11 +300,11 @@ int taxisDuplicate(int taxisID1)
 
   int taxisID2 = taxisptr2->self;
 
-  if ( CDI_Debug )
-    Message("taxisID2: %d", taxisID2);
+  if ( CDI_Debug ) Message("taxisID2: %d", taxisID2);
 
   ptaxisCopy(taxisptr2, taxisptr1);
-  return (taxisID2);
+
+  return taxisID2;
 }
 
 
@@ -555,7 +552,7 @@ int taxisInqType(int taxisID)
 {
   taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
-  return (taxisptr->type);
+  return taxisptr->type;
 }
 
 
@@ -563,7 +560,7 @@ int taxisHasBounds(int taxisID)
 {
   taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
-  return (taxisptr->has_bounds);
+  return taxisptr->has_bounds;
 }
 
 
@@ -571,9 +568,9 @@ void taxisDeleteBounds(int taxisID)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  if (taxisptr->has_bounds != FALSE)
+  if ( taxisptr->has_bounds )
     {
-      taxisptr->has_bounds = FALSE;
+      taxisptr->has_bounds = false;
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -630,7 +627,7 @@ int taxisInqVdate(int taxisID)
 {
   taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
-  return (taxisptr->vdate);
+  return taxisptr->vdate;
 }
 
 
@@ -647,13 +644,13 @@ void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  if (taxisptr->vdate_lb != vdate_lb
-      || taxisptr->vdate_ub != vdate_ub
-      || taxisptr->has_bounds != TRUE)
+  if ( taxisptr->vdate_lb != vdate_lb
+       || taxisptr->vdate_ub != vdate_ub
+       || taxisptr->has_bounds == false )
     {
       taxisptr->vdate_lb = vdate_lb;
       taxisptr->vdate_ub = vdate_ub;
-      taxisptr->has_bounds = TRUE;
+      taxisptr->has_bounds = true;
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -678,7 +675,7 @@ int taxisInqVtime(int taxisID)
 {
   taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
-  return (taxisptr->vtime);
+  return taxisptr->vtime;
 }
 
 
@@ -695,13 +692,13 @@ void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  if (taxisptr->vtime_lb != vtime_lb
-      || taxisptr->vtime_ub != vtime_ub
-      || taxisptr->has_bounds != TRUE)
+  if ( taxisptr->vtime_lb != vtime_lb
+       || taxisptr->vtime_ub != vtime_ub
+       || taxisptr->has_bounds == false )
     {
       taxisptr->vtime_lb = vtime_lb;
       taxisptr->vtime_ub = vtime_ub;
-      taxisptr->has_bounds = TRUE;
+      taxisptr->has_bounds = true;
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -733,7 +730,7 @@ int taxisInqRdate(int taxisID)
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
-  return (taxisptr->rdate);
+  return taxisptr->rdate;
 }
 
 /*
@@ -763,7 +760,7 @@ int taxisInqRtime(int taxisID)
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
-  return (taxisptr->rtime);
+  return taxisptr->rtime;
 }
 
 /*
@@ -792,7 +789,7 @@ int taxisInqFdate(int taxisID)
       taxisptr->ftime = taxisptr->vtime;
     }
 
-  return (taxisptr->fdate);
+  return taxisptr->fdate;
 }
 
 /*
@@ -821,7 +818,7 @@ int taxisInqFtime(int taxisID)
       taxisptr->ftime = taxisptr->vtime;
     }
 
-  return (taxisptr->ftime);
+  return taxisptr->ftime;
 }
 
 /*
@@ -847,7 +844,7 @@ int taxisInqCalendar(int taxisID)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  return (taxisptr->calendar);
+  return taxisptr->calendar;
 }
 
 
@@ -855,7 +852,7 @@ int taxisInqTunit(int taxisID)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  return (taxisptr->unit);
+  return taxisptr->unit;
 }
 
 
@@ -879,7 +876,7 @@ int taxisInqNumavg(int taxisID)
 {
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
-  return (taxisptr->numavg);
+  return taxisptr->numavg;
 }
 
 
@@ -887,7 +884,7 @@ taxis_t *taxisPtr(int taxisID)
 {
   taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
-  return (taxisptr);
+  return taxisptr;
 }
 
 void
@@ -918,8 +915,6 @@ ptaxisDefLongname(taxis_t *taxisptr, const char *longname)
 static void
 cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
 {
-  static int lwarn = TRUE;
-
   *days = 0;
   *secs = 0;
 
@@ -964,10 +959,11 @@ cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
     }
   else
     {
+      static bool lwarn = true;
       if ( lwarn )
 	{
 	  Warning("timeunit %s unsupported!", tunitNamePtr(timeunit));
-	  lwarn = FALSE;
+	  lwarn = false;
 	}
     }
 }
@@ -975,8 +971,6 @@ cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
 static
 void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
 {
-  static int lwarn = TRUE;
-
   if ( timeunit == TUNIT_SECOND )
     {
       *timevalue = days*86400. + secs;
@@ -1000,10 +994,11 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
     }
   else
     {
+      static bool lwarn = true;
       if ( lwarn )
 	{
 	  Warning("timeunit %s unsupported!", tunitNamePtr(timeunit));
-	  lwarn = FALSE;
+	  lwarn = false;
 	}
     }
 }
@@ -1087,7 +1082,7 @@ double vtime2timeval(int vdate, int vtime, taxis_t *taxis)
       rtime  = (*taxis).vtime;
     }
 
-  if ( rdate == 0 && rtime == 0 && vdate == 0 && vtime == 0 ) return(value);
+  if ( rdate == 0 && rtime == 0 && vdate == 0 && vtime == 0 ) return value;
 
   cdiDecodeDate(rdate, &ryear, &rmonth, &day);
   cdiDecodeTime(rtime, &hour, &minute, &second);
@@ -1140,7 +1135,7 @@ double vtime2timeval(int vdate, int vtime, taxis_t *taxis)
       value /= 30;
     }
 
-  return (value);
+  return value;
 }
 
 
@@ -1172,7 +1167,6 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time)
   int vdate = 0, vtime = 0;
   int hour, minute, second;
   int year, month, day;
-  static int lwarn = TRUE;
 
   if ( timeunit == TUNIT_SECOND )
     {
@@ -1212,10 +1206,11 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time)
     }
   else
     {
+      static bool lwarn = true;
       if ( lwarn )
 	{
 	  Warning("timeunit %s unsupported!", tunitNamePtr(timeunit));
-	  lwarn = FALSE;
+	  lwarn = false;
 	}
     }
 
@@ -1236,9 +1231,10 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time)
       vdate = cdiEncodeDate(year, month, day);
       vtime = cdiEncodeTime(hour, minute, second);
 
+      static bool lwarn = true;
       if ( lwarn )
         {
-          lwarn = FALSE;
+          lwarn = false;
           Warning("Reset wrong date/time to %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d!",
                   year, month, day, hour, minute, second);
         }
@@ -1355,7 +1351,7 @@ double cdiEncodeTimeval(int date, int time, taxis_t *taxis)
   else
     timevalue = vtime2timeval(date, time, taxis);
 
-  return (timevalue);
+  return timevalue;
 }
 
 
@@ -1435,13 +1431,13 @@ taxisPrintKernel(taxis_t * taxisptr, FILE * fp)
           "fc_unit     = %d\n"
           "fc_period   = %g\n"
           "\n", taxisptr->self, taxisptr->self,
-          taxisptr->used, taxisptr->type,
+          (int)taxisptr->used, taxisptr->type,
           taxisptr->vdate, taxisptr->vtime,
           taxisptr->rdate, taxisptr->rtime,
           taxisptr->fdate, taxisptr->ftime,
           taxisptr->calendar, taxisptr->unit,
-          taxisptr->numavg, taxisptr->climatology,
-          taxisptr->has_bounds,
+          taxisptr->numavg, (int)taxisptr->climatology,
+          (int) taxisptr->has_bounds,
           vdate_lb, vtime_lb, vdate_ub, vtime_ub,
           taxisptr->fc_unit, taxisptr->fc_period );
 }
diff --git a/src/taxis.h b/src/taxis.h
index 78cf402d688d6b154f31d2f764fe20ad3246e975..122071e162a7103ff3e26a2fa17d103ab935cff1 100644
--- a/src/taxis.h
+++ b/src/taxis.h
@@ -1,6 +1,8 @@
 #ifndef _TAXIS_H
 #define _TAXIS_H
 
+#include <stdbool.h>
+
 #ifndef RESOURCE_HANDLE_H
 #include "resource_handle.h"
 #endif
@@ -9,7 +11,7 @@ typedef struct {
   /* Date format  YYYYMMDD */
   /* Time format    hhmmss */
   int     self;
-  short   used;
+  bool    used;
   short   has_bounds;
   int     type;           // time type
   int     vdate;          // verification date
@@ -21,7 +23,7 @@ typedef struct {
   int     calendar;
   int     unit;           // time unit
   int     numavg;
-  int     climatology;
+  bool    climatology;
   int     vdate_lb;       // lower bounds of vdate
   int     vtime_lb;       // lower bounds of vtime
   int     vdate_ub;       // upper bounds of vdate
diff --git a/src/util.c b/src/util.c
index cef54cf8356bcec52f95075f96a14b590b059276..42c62a9c28747cc9ffb1a465517efd7b1e12dd70 100644
--- a/src/util.c
+++ b/src/util.c
@@ -30,6 +30,7 @@ void cdiPrintDatatypes(void)
            "+-------------+-------+\n"
            "| char        |   %3d |\n"
            "+-------------+-------+\n"
+           "| bool        |   %3d |\n"
            "| short       |   %3d |\n"
            "| int         |   %3d |\n"
            "| long        |   %3d |\n"
@@ -48,7 +49,7 @@ void cdiPrintDatatypes(void)
            "| FLT64       | %-9s |\n"
            "+-------------+-----------+\n"
            "\n  byte ordering is %s\n\n",
-           (int) sizeof(void *), (int) sizeof(char),
+           (int) sizeof(void *), (int) sizeof(char), (int) sizeof(bool),
            (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long),
            (int) sizeof(size_t), (int) sizeof(off_t),
            (int) sizeof(float), (int) sizeof(double), (int) sizeof(long double),
diff --git a/src/varscan.c b/src/varscan.c
index d89fa3297dc0e2edd083cf3f8661c7d0d4454022..c9898ace450f59154de332d1c42d5be79bad1ff4 100644
--- a/src/varscan.c
+++ b/src/varscan.c
@@ -122,7 +122,7 @@ paramInitEntry(unsigned varID, int param)
   vartable[varID].tableID        = UNDEFID;
   vartable[varID].typeOfGeneratingProcess   = UNDEFID;
   vartable[varID].productDefinitionTemplate = UNDEFID;
-  vartable[varID].comptype       = COMPRESS_NONE;
+  vartable[varID].comptype       = CDI_COMPRESS_NONE;
   vartable[varID].complevel      = 1;
   vartable[varID].lmissval       = 0;
   vartable[varID].missval        = 0;
@@ -1054,7 +1054,7 @@ void varDefMissval(int varID, double missval)
 
 void varDefCompType(int varID, int comptype)
 {
-  if ( vartable[varID].comptype == COMPRESS_NONE )
+  if ( vartable[varID].comptype == CDI_COMPRESS_NONE )
     vartable[varID].comptype = comptype;
 }
 
diff --git a/src/vlist.c b/src/vlist.c
index f941413990d66391de32e1df6ecc91d8f566cbc6..7db10e1192db9441c6045fb02133784ce00956ed 100644
--- a/src/vlist.c
+++ b/src/vlist.c
@@ -12,7 +12,7 @@
 #include "namespace.h"
 #include "resource_handle.h"
 #include "vlist_var.h"
-#include "vlist_att.h"
+#include "cdi_att.h"
 
 #include "resource_unpack.h"
 #include "serialize.h"
@@ -47,8 +47,7 @@ static int vlistIsInitialized = 0;
 static int
 vlist_compare(vlist_t *a, vlist_t *b)
 {
-  int diff;
-  diff = (a->nvars != b->nvars) | (a->ngrids != b->ngrids)
+  int diff = (a->nvars != b->nvars) | (a->ngrids != b->ngrids)
     | (a->nzaxis != b->nzaxis) | (a->instID != b->instID)
     | (a->modelID != b->modelID) | (a->tableID != b->tableID)
     | (a->ntsteps != b->ntsteps) | (a->atts.nelems != b->atts.nelems);
@@ -57,7 +56,7 @@ vlist_compare(vlist_t *a, vlist_t *b)
     diff |= vlistVarCompare(a, varID, b, varID);
   size_t natts = a->atts.nelems;
   for (size_t attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, (int)attID);
+    diff |= cdi_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, (int)attID);
   return diff;
 }
 
@@ -77,8 +76,8 @@ const
 resOps vlistOps = {
   (valCompareFunc)vlist_compare,
   (valDestroyFunc)vlist_delete,
-  (valPrintFunc)vlistPrintKernel
-  , vlistGetSizeP,
+  (valPrintFunc)vlistPrintKernel,
+  vlistGetSizeP,
   vlistPackP,
   vlistTxCode
 };
@@ -87,7 +86,7 @@ resOps vlistOps = {
 vlist_t *vlist_to_pointer(int vlistID)
 {
   VLIST_INIT();
-  return (vlist_t*) reshGetVal(vlistID, &vlistOps );
+  return (vlist_t*) reshGetVal(vlistID, &vlistOps);
 }
 
 static
@@ -109,7 +108,7 @@ void vlist_init_entry(vlist_t *vlistptr)
   vlistptr->atts.nalloc    = MAX_ATTRIBUTES;
   vlistptr->atts.nelems    = 0;
   vlistptr->nsubtypes      = 0;
-  for (int i=0; i<MAX_SUBTYPES_PS; i++)
+  for ( int i = 0; i < MAX_SUBTYPES_PS; i++ )
     vlistptr->subtypeIDs[i] = CDI_UNDEFID;
 }
 
@@ -125,15 +124,13 @@ vlist_t *vlist_new_entry(cdiResH resH)
       vlistptr->self = resH;
       reshReplace(resH, vlistptr, &vlistOps);
     }
-  return (vlistptr);
+  return vlistptr;
 }
 
 static
 void vlist_delete_entry(vlist_t *vlistptr)
 {
-  int idx;
-
-  idx = vlistptr->self;
+  int idx = vlistptr->self;
 
   reshRemove(idx, &vlistOps );
 
@@ -146,9 +143,7 @@ void vlist_delete_entry(vlist_t *vlistptr)
 static
 void vlist_initialize(void)
 {
-  char *env;
-
-  env = getenv("VLIST_DEBUG");
+  char *env = getenv("VLIST_DEBUG");
   if ( env ) VLIST_Debug = atoi(env);
 #ifndef HAVE_LIBPTHREAD
   vlistIsInitialized = TRUE;
@@ -210,7 +205,7 @@ int vlistCreate(void)
 
   vlist_t *vlistptr = vlist_new_entry(CDI_UNDEFID);
   if ( CDI_Debug ) Message("create vlistID = %d", vlistptr->self);
-  return (vlistptr->self);
+  return vlistptr->self;
 }
 
 static void
@@ -219,7 +214,7 @@ vlist_delete(vlist_t *vlistptr)
   int vlistID = vlistptr->self;
   if ( CDI_Debug ) Message("call to vlist_delete, vlistID = %d", vlistID);
 
-  vlistDelAtts(vlistID, CDI_GLOBAL);
+  cdiDelAtts(vlistID, CDI_GLOBAL);
 
   int nvars = vlistptr->nvars;
   var_t *vars = vlistptr->vars;
@@ -245,7 +240,7 @@ vlist_delete(vlist_t *vlistptr)
       vlistptr->vars[varID].opt_grib_kvpair_size = 0;
       vlistptr->vars[varID].opt_grib_kvpair      = NULL;
 
-      vlistDelAtts(vlistID, varID);
+      cdiDelAtts(vlistID, varID);
     }
 
   if ( vars ) Free(vars);
@@ -348,7 +343,7 @@ void vlistCopy(int vlistID2, int vlistID1)
   var_t *vars2 = vlistptr2->vars;
   vlist_copy(vlistptr2, vlistptr1);
 
-  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
+  cdiCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
 
   if ( vars1 )
     {
@@ -365,7 +360,7 @@ void vlistCopy(int vlistID2, int vlistID1)
           var_copy_entries(&vars2[varID], &vars1[varID]);
 
           vlistptr2->vars[varID].atts.nelems = 0;
-	  vlistCopyVarAtts(vlistID1, varID, vlistID2, varID);
+	  cdiCopyVarAtts(vlistID1, varID, vlistID2, varID);
 
           if ( vars1[varID].levinfo )
             {
@@ -399,22 +394,21 @@ int vlistDuplicate(int vlistID)
 
   int vlistIDnew = vlistCreate();
   vlistCopy(vlistIDnew, vlistID);
-  return (vlistIDnew);
+  return vlistIDnew;
 }
 
 
 void vlistClearFlag(int vlistID)
 {
-  int varID, levID;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  for ( varID = 0; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     {
       vlistptr->vars[varID].flag = FALSE;
       if ( vlistptr->vars[varID].levinfo )
         {
           int nlevs = zaxisInqSize(vlistptr->vars[varID].zaxisID);
-          for ( levID = 0; levID < nlevs; levID++ )
+          for ( int levID = 0; levID < nlevs; levID++ )
             vlistptr->vars[varID].levinfo[levID].flag = FALSE;
         }
     }
@@ -506,7 +500,7 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, const double *
       vlistptr->nzaxis++;
     }
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 /*
@@ -532,7 +526,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 
   vlist_copy(vlistptr2, vlistptr1);
 
-  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
+  cdiCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
 
   if ( vlistptr1->vars )
     {
@@ -574,7 +568,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
             var_copy_entries(&vars2[varID2], &vars1[varID]);
 
 	    vlistptr2->vars[varID2].atts.nelems = 0;
-	    vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
+	    cdiCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
 	    int nlevs  = zaxisInqSize(vars1[varID].zaxisID);
 	    int nlevs2 = 0;
@@ -738,7 +732,7 @@ void vlistCat(int vlistID2, int vlistID1)
         }
 
       vars2[varID2].atts.nelems = 0;
-      vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
+      cdiCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
       vlistAdd2GridIDs(vlistptr2, vars1[varID].gridID);
       vlistAdd2ZaxisIDs(vlistptr2, vars1[varID].zaxisID);
@@ -896,28 +890,28 @@ The function @func{vlistNvars} returns the number of variables in the variable l
 int vlistNvars(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->nvars);
+  return vlistptr->nvars;
 }
 
 
 int vlistNrecs(int vlistID)
 {
-  int nrecs = 0;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
+  int nrecs = 0;
   for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     nrecs +=  zaxisInqSize(vlistptr->vars[varID].zaxisID);
 
-  return (nrecs);
+  return nrecs;
 }
 
 
 int vlistNumber(int vlistID)
 {
-  int number, number2, datatype;
+  int number, number2;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  datatype = vlistptr->vars[0].datatype;
+  int datatype = vlistptr->vars[0].datatype;
   if (  datatype== DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
     number = CDI_COMP;
   else
@@ -938,7 +932,7 @@ int vlistNumber(int vlistID)
         }
     }
 
-  return (number);
+  return number;
 }
 
 /*
@@ -961,7 +955,7 @@ int vlistNgrids(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->ngrids);
+  return vlistptr->ngrids;
 }
 
 /*
@@ -984,7 +978,7 @@ int vlistNzaxis(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->nzaxis);
+  return vlistptr->nzaxis;
 }
 
 
@@ -992,7 +986,7 @@ int vlistNsubtypes(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->nsubtypes);
+  return vlistptr->nsubtypes;
 }
 
 
@@ -1000,7 +994,7 @@ void vlistDefNtsteps(int vlistID, int nts)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if (vlistptr->ntsteps != nts)
+  if ( vlistptr->ntsteps != nts )
     {
       vlistptr->ntsteps = nts;
       reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
@@ -1122,7 +1116,7 @@ void vlistDefTaxis(int vlistID, int taxisID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if (vlistptr->taxisID != taxisID)
+  if ( vlistptr->taxisID != taxisID )
     {
       //FIXME: This code seems to leak a taxis_t object if `vlistptr->taxisID` was valid before the call to vlistDefTaxis.
       vlistptr->taxisID = taxisID;
@@ -1150,7 +1144,7 @@ int vlistInqTaxis(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->taxisID);
+  return vlistptr->taxisID;
 }
 
 
@@ -1158,7 +1152,7 @@ void vlistDefTable(int vlistID, int tableID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if (vlistptr->tableID != tableID)
+  if ( vlistptr->tableID != tableID )
     {
       vlistptr->tableID = tableID;
       reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
@@ -1170,7 +1164,7 @@ int vlistInqTable(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->tableID);
+  return vlistptr->tableID;
 }
 
 
@@ -1178,7 +1172,7 @@ void vlistDefInstitut(int vlistID, int instID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if (vlistptr->instID != instID)
+  if ( vlistptr->instID != instID )
     {
       vlistptr->instID = instID;
       reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
@@ -1205,7 +1199,7 @@ int vlistInqInstitut(int vlistID)
       vlistDefInstitut(vlistID, instID);
     }
 
-  return (instID);
+  return instID;
 }
 
 
@@ -1213,7 +1207,7 @@ void vlistDefModel(int vlistID, int modelID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if (vlistptr->modelID != modelID)
+  if ( vlistptr->modelID != modelID )
     {
       vlistptr->modelID = modelID;
       reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
@@ -1241,7 +1235,7 @@ int vlistInqModel(int vlistID)
       vlistDefModel(vlistID, modelID);
     }
 
-  return (modelID);
+  return modelID;
 }
 
 
@@ -1257,7 +1251,7 @@ int vlistGridsizeMax(int vlistID)
       if ( gridsize > gridsizemax ) gridsizemax = gridsize;
     }
 
-  return (gridsizemax);
+  return gridsizemax;
 }
 
 
@@ -1269,7 +1263,7 @@ int vlistGrid(int vlistID, int index)
   if ( index < vlistptr->ngrids && index >= 0 )
     gridID = vlistptr->gridIDs[index];
 
-  return (gridID);
+  return gridID;
 }
 
 
@@ -1283,7 +1277,7 @@ int vlistGridIndex(int vlistID, int gridID)
 
   if ( index == vlistptr->ngrids ) index = -1;
 
-  return (index);
+  return index;
 }
 
 
@@ -1337,7 +1331,7 @@ int vlistZaxis(int vlistID, int index)
   if ( index < vlistptr->nzaxis && index >= 0 )
     zaxisID = vlistptr->zaxisIDs[index];
 
-  return (zaxisID);
+  return zaxisID;
 }
 
 
@@ -1351,7 +1345,7 @@ int vlistZaxisIndex(int vlistID, int zaxisID)
 
   if ( index == vlistptr->nzaxis ) index = -1;
 
-  return (index);
+  return index;
 }
 
 
@@ -1455,15 +1449,14 @@ int vlistHasTime(int vlistID)
         break;
       }
 
-  return (hastime);
+  return hastime;
 }
 
 enum {
   vlist_nints=6,
 };
 
-static int
-vlistTxCode ( void )
+static int vlistTxCode ( void )
 {
   return VLIST;
 }
@@ -1476,7 +1469,7 @@ int  vlistGetSizeP ( void * vlistptr, void *context)
   vlist_t *p = (vlist_t*) vlistptr;
   txsize = serializeGetSize(vlist_nints, DATATYPE_INT, context);
   txsize += serializeGetSize(1, DATATYPE_LONG, context);
-  txsize += vlistAttsGetSize(p, CDI_GLOBAL, context);
+  txsize += cdiAttsGetSize(p, CDI_GLOBAL, context);
   for ( varID = 0; varID <  p->nvars; varID++ )
     txsize += vlistVarGetPackSize(p, varID, context);
   return txsize;
@@ -1498,7 +1491,7 @@ void vlistPackP ( void * vlistptr, void * buf, int size, int *position,
   serializePack(tempbuf, vlist_nints, DATATYPE_INT, buf, size, position, context);
   serializePack(&p->ntsteps, 1, DATATYPE_LONG, buf, size, position, context);
 
-  vlistAttsPack(p, CDI_GLOBAL, buf, size, position, context);
+  cdiAttsPack(p, CDI_GLOBAL, buf, size, position, context);
   for ( varID = 0; varID < p->nvars; varID++ )
     {
       vlistVarPack(p, varID, (char *)buf, size, position, context);
@@ -1522,7 +1515,7 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
   p->instID = namespaceAdaptKey(tempbuf[4], originNamespace);
   p->modelID = namespaceAdaptKey(tempbuf[5], originNamespace);
   serializeUnpack(buf, size, position, &p->ntsteps, 1, DATATYPE_LONG, context);
-  vlistAttsUnpack(targetID, CDI_GLOBAL, buf, size, position, context);
+  cdiAttsUnpack(targetID, CDI_GLOBAL, buf, size, position, context);
   for (int varID = 0; varID < nvars; varID++ )
     vlistVarUnpack(targetID, buf, size, position, originNamespace, context);
   reshSetStatus(targetID, &vlistOps,
@@ -1532,11 +1525,10 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
 
 void vlist_check_contents(int vlistID)
 {
-  int index, nzaxis, zaxisID;
+  int zaxisID;
+  int nzaxis = vlistNzaxis(vlistID);
 
-  nzaxis = vlistNzaxis(vlistID);
-
-  for ( index = 0; index < nzaxis; index++ )
+  for ( int index = 0; index < nzaxis; index++ )
     {
       zaxisID = vlistZaxis(vlistID, index);
       if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
diff --git a/src/vlist.h b/src/vlist.h
index 0179579653421d4468d407ebe9874d5b58492169..be254df7690440a7d2e25d467be99d264bdf5546 100644
--- a/src/vlist.h
+++ b/src/vlist.h
@@ -17,30 +17,7 @@
 
 #define VALIDMISS 1.e+303
 
-/*
- * CDI attribute
- */
-typedef struct {
-  size_t    xsz;	  /* amount of space at xvalue                      */
-  size_t    namesz;       /* size of name                                   */
-  char     *name;         /* attribute name                                 */
-  int       indtype;	  /* internal data type of xvalue (INT, FLT or TXT) */
-  int       exdtype;      /* external data type                             */
-                          /* indtype    exdtype                             */
-                          /* TXT        TXT                                 */
-                          /* INT        INT16, INT32                        */
-                          /* FLT        FLT32, FLT64                        */
-  size_t    nelems;    	  /* number of elements                             */
-  void     *xvalue;       /* the actual data                                */
-} cdi_att_t;
-
-
-typedef struct {
-  size_t     nalloc;		/* number allocated >= nelems */
-  size_t     nelems;		/* length of the array */
-  cdi_att_t  value[MAX_ATTRIBUTES];
-} cdi_atts_t;
-
+#include "cdi_att.h"
 
 typedef struct
 {
@@ -117,9 +94,9 @@ var_t;
 typedef struct
 {
   //set when a vlist is passed to streamDefVlist() to safeguard against modifications of the wrong vlist object
-  bool    immutable;
+  bool        immutable;
   //set if this vlist has been created by CDI itself, and must not be destroyed by the user, consequently
-  bool    internal;
+  bool        internal;
   int         self;
   int         nvars;        /* number of variables                */
   int         ngrids;
@@ -154,8 +131,8 @@ void     vlistDefVarTsteptype(int vlistID, int varID, int tsteptype);
 int      vlistInqVarMissvalUsed(int vlistID, int varID);
 int      vlistHasTime(int vlistID);
 
-int      vlistDelAtts(int vlistID, int varID);
-int      vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2);
+int      cdiDelAtts(int vlistID, int varID);
+int      cdiCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2);
 
 void     vlistUnpack(char * buffer, int bufferSize, int * pos,
                      int originNamespace, void *context, int force_id);
@@ -168,7 +145,7 @@ int     vlistInqVarValidrange(int vlistID, int varID, double *validrange);
 
 void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]);
 
-int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
+int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
 
 void resize_opt_grib_entries(var_t *var, int nentries);
 
diff --git a/src/vlist_att.h b/src/vlist_att.h
deleted file mode 100644
index c42b36438b56ad453aea959feb26494ffcf86175..0000000000000000000000000000000000000000
--- a/src/vlist_att.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef VLIST_ATT_H
-#define VLIST_ATT_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-int
-vlistAttsGetSize(vlist_t *p, int varID, void *context);
-
-void
-vlistAttsPack(vlist_t *p, int varID,
-              void * buf, int size, int *position, void *context);
-
-void
-vlistAttsUnpack(int vlistID, int varID,
-                void * buf, int size, int *position, void *context);
-
-
-#endif
-
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/src/vlist_var.c b/src/vlist_var.c
index 12b63f0138a98ca2b74745275aaa9dd841acd756..a38cc5a0be6110f9a4405c608506970cbabe4b79 100644
--- a/src/vlist_var.c
+++ b/src/vlist_var.c
@@ -10,7 +10,7 @@
 #include "vlist.h"
 #include "vlist_var.h"
 #include "resource_handle.h"
-#include "vlist_att.h"
+#include "cdi_att.h"
 #include "namespace.h"
 #include "serialize.h"
 #include "error.h"
@@ -54,7 +54,7 @@ void vlistvarInitEntry(int vlistID, int varID)
   vlistptr->vars[varID].units         = NULL;
   vlistptr->vars[varID].extra         = NULL;
   vlistptr->vars[varID].levinfo       = NULL;
-  vlistptr->vars[varID].comptype      = COMPRESS_NONE;
+  vlistptr->vars[varID].comptype      = CDI_COMPRESS_NONE;
   vlistptr->vars[varID].complevel     = 1;
   vlistptr->vars[varID].atts.nalloc   = MAX_ATTRIBUTES;
   vlistptr->vars[varID].atts.nelems   = 0;
@@ -114,7 +114,7 @@ int vlistvarNewEntry(int vlistID)
 
   vlistptr->vars[varID].isUsed = TRUE;
 
-  return (varID);
+  return varID;
 }
 
 void vlistCheckVarID(const char *caller, int vlistID, int varID)
@@ -134,12 +134,12 @@ void vlistCheckVarID(const char *caller, int vlistID, int varID)
 
 int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int tilesetID)
 {
-  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   if ( CDI_Debug )
     Message("gridID = %d  zaxisID = %d  tsteptype = %d", gridID, zaxisID, tsteptype);
 
   int varID = vlistvarNewEntry(vlistID);
 
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   vlistptr->nvars++;
   vlistptr->vars[varID].gridID    = gridID;
   vlistptr->vars[varID].zaxisID   = zaxisID;
@@ -158,7 +158,8 @@ int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int ti
 
   vlistptr->vars[varID].param = cdiEncodeParam(-(varID + 1), 255, 255);
   reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
-  return (varID);
+
+  return varID;
 }
 
 /*
@@ -317,7 +318,7 @@ int vlistInqVarGrid(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].gridID);
+  return vlistptr->vars[varID].gridID;
 }
 
 /*
@@ -343,7 +344,7 @@ int vlistInqVarZaxis(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].zaxisID);
+  return vlistptr->vars[varID].zaxisID;
 }
 
 
@@ -364,7 +365,8 @@ int vlistInqVarSubtype(int vlistID, int varID)
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
-  return (vlistptr->vars[varID].subtypeID);
+
+  return vlistptr->vars[varID].subtypeID;
 }
 
 
@@ -391,7 +393,7 @@ int vlistInqVarParam(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].param);
+  return vlistptr->vars[varID].param;
 }
 
 /*
@@ -428,7 +430,7 @@ int vlistInqVarCode(int vlistID, int varID)
       tableInqParCode(vlistptr->vars[varID].tableID, vlistptr->vars[varID].name, &code);
     }
 
-  return (code);
+  return code;
 }
 
 
@@ -438,7 +440,7 @@ const char *vlistInqVarNamePtr(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].name);
+  return vlistptr->vars[varID].name;
 }
 
 
@@ -448,7 +450,7 @@ const char *vlistInqVarLongnamePtr(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].longname);
+  return vlistptr->vars[varID].longname;
 }
 
 
@@ -458,7 +460,7 @@ const char *vlistInqVarStdnamePtr(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].stdname);
+  return vlistptr->vars[varID].stdname;
 }
 
 
@@ -468,7 +470,7 @@ const char *vlistInqVarUnitsPtr(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].units);
+  return vlistptr->vars[varID].units;
 }
 
 /*
@@ -715,10 +717,10 @@ int vlistInqVarID(int vlistID, int code)
       int param = vlistptr->vars[varID].param;
       int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
-      if ( pnum == code ) return (varID);
+      if ( pnum == code ) return varID;
     }
 
-  return (CDI_UNDEFID);
+  return CDI_UNDEFID;
 }
 
 
@@ -726,8 +728,7 @@ int vlistInqVarSize(int vlistID, int varID)
 {
   vlistCheckVarID(__func__, vlistID, varID);
 
-  int zaxisID, gridID;
-  int tsteptype;
+  int zaxisID, gridID, tsteptype;
   vlistInqVar(vlistID, varID, &gridID, &zaxisID, &tsteptype);
 
   int nlevs = zaxisInqSize(zaxisID);
@@ -736,7 +737,7 @@ int vlistInqVarSize(int vlistID, int varID)
 
   int size = gridsize*nlevs;
 
-  return (size);
+  return size;
 }
 
 /*
@@ -765,7 +766,7 @@ int vlistInqVarDatatype(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].datatype);
+  return vlistptr->vars[varID].datatype;
 }
 
 
@@ -780,7 +781,7 @@ int vlistInqVarNumber(int vlistID, int varID)
        vlistptr->vars[varID].datatype == DATATYPE_CPX64 )
     number = CDI_COMP;
 
-  return (number);
+  return number;
 }
 
 /*
@@ -840,7 +841,7 @@ void vlistDefVarInstitut(int vlistID, int varID, int instID)
 int vlistInqVarInstitut(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].instID);
+  return vlistptr->vars[varID].instID;
 }
 
 
@@ -858,7 +859,7 @@ void vlistDefVarModel(int vlistID, int varID, int modelID)
 int vlistInqVarModel(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].modelID);
+  return vlistptr->vars[varID].modelID;
 }
 
 
@@ -884,7 +885,7 @@ void vlistDefVarTable(int vlistID, int varID, int tableID)
 int vlistInqVarTable(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].tableID);
+  return vlistptr->vars[varID].tableID;
 }
 
 /*
@@ -1046,7 +1047,7 @@ double vlistInqVarMissval(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].missval);
+  return vlistptr->vars[varID].missval;
 }
 
 /*
@@ -1156,7 +1157,7 @@ int vlistInqVarValidrange(int vlistID, int varID, double *validrange)
       validrange[1] = vlistptr->vars[varID].validrange[1];
     }
 
-  return (vlistptr->vars[varID].lvalidrange);
+  return vlistptr->vars[varID].lvalidrange;
 }
 
 
@@ -1179,7 +1180,7 @@ double vlistInqVarScalefactor(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].scalefactor);
+  return vlistptr->vars[varID].scalefactor;
 }
 
 
@@ -1189,7 +1190,7 @@ double vlistInqVarAddoffset(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].addoffset);
+  return vlistptr->vars[varID].addoffset;
 }
 
 
@@ -1254,7 +1255,7 @@ The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT},
 int vlistInqVarTsteptype(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].tsteptype);
+  return vlistptr->vars[varID].tsteptype;
 }
 
 
@@ -1272,7 +1273,7 @@ void vlistDefVarTimave(int vlistID, int varID, int timave)
 int vlistInqVarTimave(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].timave);
+  return vlistptr->vars[varID].timave;
 }
 
 
@@ -1290,7 +1291,7 @@ void vlistDefVarTimaccu(int vlistID, int varID, int timaccu)
 int vlistInqVarTimaccu(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].timaccu);
+  return vlistptr->vars[varID].timaccu;
 }
 
 
@@ -1308,7 +1309,7 @@ void vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGenera
 int vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].typeOfGeneratingProcess);
+  return vlistptr->vars[varID].typeOfGeneratingProcess;
 }
 
 
@@ -1327,8 +1328,7 @@ void vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDef
 int vlistInqVarProductDefinitionTemplate(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
-  return (vlistptr->vars[varID].productDefinitionTemplate);
+  return vlistptr->vars[varID].productDefinitionTemplate;
 }
 
 
@@ -1386,7 +1386,7 @@ void vlistDestroyVarUnits(int vlistID, int varID)
 int vlistInqVarMissvalUsed(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].missvalused);
+  return vlistptr->vars[varID].missvalused;
 }
 
 
@@ -1425,7 +1425,7 @@ int vlistInqFlag(int vlistID, int varID, int levID)
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
-    return (vlistptr->vars[varID].levinfo[levID].flag);
+    return vlistptr->vars[varID].levinfo[levID].flag;
   else
     {
       levinfo_t li = DEFAULT_LEVINFO(levID);
@@ -1450,7 +1450,7 @@ int vlistFindVar(int vlistID, int fvarID)
       Message("varID not found for fvarID %d in vlistID %d!", fvarID, vlistID);
     }
 
-  return (varID);
+  return varID;
 }
 
 
@@ -1477,14 +1477,14 @@ int vlistFindLevel(int vlistID, int fvarID, int flevelID)
 	}
     }
 
-  return (levelID);
+  return levelID;
 }
 
 
 int vlistMergedVar(int vlistID, int varID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
-  return (vlistptr->vars[varID].mvarID);
+  return vlistptr->vars[varID].mvarID;
 }
 
 
@@ -1523,7 +1523,7 @@ int vlistInqIndex(int vlistID, int varID, int levelID)
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
-    return (vlistptr->vars[varID].levinfo[levelID].index);
+    return vlistptr->vars[varID].levinfo[levelID].index;
   else
     {
       levinfo_t li = DEFAULT_LEVINFO(levelID);
@@ -1612,7 +1612,7 @@ int vlistInqVarCompType(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].comptype);
+  return vlistptr->vars[varID].comptype;
 }
 
 
@@ -1636,7 +1636,7 @@ int vlistInqVarCompLevel(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].complevel);
+  return vlistptr->vars[varID].complevel;
 }
 
 
@@ -1660,7 +1660,7 @@ int vlistInqVarChunkType(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].chunktype);
+  return vlistptr->vars[varID].chunktype;
 }
 
 static
@@ -1737,7 +1737,7 @@ int vlistInqVarXYZ(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].xyz);
+  return vlistptr->vars[varID].xyz;
 }
 
 /* Ensemble Info Routines */
@@ -1774,7 +1774,7 @@ int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int
       status = 1;
     }
 
-  return (status);
+  return status;
 }
 
 
@@ -2064,7 +2064,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
   if (natts != b->vars[varIDB].atts.nelems)
     return 1;
   for (size_t attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, varIDA, b, varIDB, (int)attID);
+    diff |= cdi_att_compare(a, varIDA, b, varIDB, (int)attID);
   if ((diff |= ((pva->ensdata == NULL) ^ (pvb->ensdata == NULL))))
     return 1;
   if (pva->ensdata)
@@ -2096,7 +2096,7 @@ int vlistVarGetPackSize(vlist_t *p, int varID, void *context)
     varsize += serializeGetSize((int)strlen(var->extra), DATATYPE_TXT, context);
   varsize += serializeGetSize(4 * zaxisInqSize(var->zaxisID),
                               DATATYPE_INT, context);
-  varsize += vlistAttsGetSize(p, varID, context);
+  varsize += cdiAttsGetSize(p, varID, context);
   return varsize;
 }
 
@@ -2164,7 +2164,7 @@ void vlistVarPack(vlist_t *p, int varID, char * buf, int size, int *position,
       serializePack(levbuf, nlevs * 4, DATATYPE_INT,
                     buf, size, position, context);
     }
-  vlistAttsPack(p, varID, buf, size, position, context);
+  cdiAttsPack(p, varID, buf, size, position, context);
 }
 
 static inline int
@@ -2273,7 +2273,7 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
       vlistDefFlag(vlistID, newvar, flagSetLev, levbuf[flagSetLev][0]);
     }
   vlistDefVarIOrank(vlistID, newvar, tempbuf[19]);
-  vlistAttsUnpack(vlistID, newvar, buf, size, position, context);
+  cdiAttsUnpack(vlistID, newvar, buf, size, position, context);
 }
 
 
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 632acad8d7edb5f0ae2cd046e44a1d53e27bfd2b..1e41e342b627643057655f43938bced46eb9958e 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -390,11 +390,9 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-JASPER_LIBS = @JASPER_LIBS@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBOBJS = @LIBOBJS@
-LIBPNG_LIBS = @LIBPNG_LIBS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
@@ -418,7 +416,6 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
-OPENJPEG_LIBS = @OPENJPEG_LIBS@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -500,7 +497,6 @@ localstatedir = @localstatedir@
 mandir = @mandir@
 mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
-openjpeg_LIBS = @openjpeg_LIBS@
 pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
diff --git a/tests/test_cdf_read.c b/tests/test_cdf_read.c
index a870617d74d8b06331c95592300449250b1a6c6d..31f9567f13e0367fdf125f4b74c21c0b66e86b79 100644
--- a/tests/test_cdf_read.c
+++ b/tests/test_cdf_read.c
@@ -81,11 +81,11 @@ printAtts(int vlistID)
       int nAtts, attType, attLen;
       char attName[CDI_MAX_NAME + 1];
       int varID = (int)varIdx - 1;
-      vlistInqNatts(vlistID, varID, &nAtts);
+      cdiInqNatts(vlistID, varID, &nAtts);
       for (size_t attIdx = 0; attIdx < (size_t)nAtts; attIdx++ )
         {
-          int rc = vlistInqAtt(vlistID, varID, (int)attIdx,
-                               attName, &attType, &attLen);
+          int rc = cdiInqAtt(vlistID, varID, (int)attIdx,
+                             attName, &attType, &attLen);
           {
             const char *varDesc = varIdx > 0
               ? (sprintf((char *)buf, "%s%d", varDescPrefix,
@@ -126,14 +126,14 @@ printAtts(int vlistID)
           switch (attType)
             {
             case DATATYPE_TXT:
-              rc = vlistInqAttTxt(vlistID, (int)varID, attName,
-                                  attLen, (char *)buf);
+              rc = cdiInqAttTxt(vlistID, (int)varID, attName,
+                                attLen, (char *)buf);
               if (rc == CDI_NOERR)
                 printf("\"%.*s\"", attLen, (char *)buf);
               break;
             case DATATYPE_FLT:
-              rc = vlistInqAttFlt(vlistID, (int)varID, attName,
-                                  attLen + 1, (double *)buf);
+              rc = cdiInqAttFlt(vlistID, (int)varID, attName,
+                                attLen + 1, (double *)buf);
               if (rc == CDI_NOERR && attLen)
                 {
                   const double *restrict dp = (const double*)buf;
@@ -143,8 +143,8 @@ printAtts(int vlistID)
                 }
               break;
             case DATATYPE_INT:
-              rc = vlistInqAttInt(vlistID, (int)varID, attName,
-                                  attLen + 1, (int *)buf);
+              rc = cdiInqAttInt(vlistID, (int)varID, attName,
+                                attLen + 1, (int *)buf);
               if (rc == CDI_NOERR && attLen)
                 {
                   const int *restrict ip = (const int *)buf;
diff --git a/tests/test_cdf_write.c b/tests/test_cdf_write.c
index 43e01b3f5b0185002bcf47c99edc123824b5c151..def2f4f97ead6904e115b35b02d7846b813799ea 100644
--- a/tests/test_cdf_write.c
+++ b/tests/test_cdf_write.c
@@ -82,8 +82,8 @@ int main(int argc, const char **argv)
   vlistDefVarMissval(vlistID, varID, missValue);
   {
     static const char creatorText[] = "CDI test_cdf_write";
-    vlistDefAttTxt(vlistID, varID, "CDI Text Attribute test, created by",
-                   sizeof (creatorText) - 1, creatorText);
+    cdiDefAttTxt(vlistID, varID, "CDI Text Attribute test, created by",
+                 sizeof (creatorText) - 1, creatorText);
   }
 
   int taxisID = taxisCreate(TAXIS_ABSOLUTE);
diff --git a/tests/test_resource_copy.c b/tests/test_resource_copy.c
index 9d09677055cc4b3b95dceca56e183c003fb42eb8..dcb9a07183c6da60e9e59c8dac0f70c59258c724 100644
--- a/tests/test_resource_copy.c
+++ b/tests/test_resource_copy.c
@@ -164,11 +164,10 @@ static struct idPair defineVlist ( int gridID, int zaxisID, int taxisID )
   vlistDefVarName(vlistID, varID1, "varname1");
   {
     int globfac[] = { 23, 42 };
-    vlistDefAttInt(vlistID, varID1, "seer's globule factors", DATATYPE_INT16,
-                   2, globfac);
+    cdiDefAttInt(vlistID, varID1, "seer's globule factors", DATATYPE_INT16, 2, globfac);
   }
   vlistDefVarName(vlistID, varID2, "varname2");
-  vlistDefAttTxt(vlistID, varID2, "txt demo", 6, "banana");
+  cdiDefAttTxt(vlistID, varID2, "txt demo", 6, "banana");
   vlistDefTaxis(vlistID, taxisID);
   int vlistID2 = vlistCreate();
   vlistDefVar(vlistID2, gridID, zaxisID, TIME_VARIABLE);