[cdo] 64/84: Upstream 1.6.5.1

Alastair McKinstry mckinstry at moszumanska.debian.org
Sat Jun 13 16:48:40 UTC 2015


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch master
in repository cdo.

commit 42f0eba43cd251457e4d64f702a3ce968e291cab
Author: Alastair McKinstry <alastair at debian.sceal.ie>
Date:   Mon Nov 3 17:16:08 2014 +0000

    Upstream 1.6.5.1
---
 ChangeLog                                 |   115 +-
 NEWS                                      |    20 +-
 OPERATORS                                 |     2 +
 cdo.spec                                  |     2 +-
 config/default                            |   196 +-
 configure                                 |   371 +-
 configure.ac                              |    84 +-
 contrib/cdoCompletion.bash                |     4 +
 contrib/cdoCompletion.tcsh                |     4 +
 contrib/cdoCompletion.zsh                 |     4 +
 doc/cdo.pdf                               |   Bin 1452250 -> 1308412 bytes
 doc/cdo_refcard.pdf                       |   Bin 96113 -> 96478 bytes
 libcdi/ChangeLog                          |   100 +
 libcdi/Makefile.in                        |     8 +-
 libcdi/NEWS                               |    19 +
 libcdi/aclocal.m4                         |     1 +
 libcdi/app/Makefile.in                    |     1 +
 libcdi/app/cdi.c                          |    30 +-
 libcdi/app/createtable.c                  |    25 +-
 libcdi/app/printinfo.h                    |     4 +-
 libcdi/config/default                     |     6 +-
 libcdi/configure                          |   291 +-
 libcdi/configure.ac                       |    21 +-
 libcdi/doc/cdi_cman.pdf                   |   Bin 456965 -> 333218 bytes
 libcdi/doc/cdi_fman.pdf                   |   Bin 497919 -> 361058 bytes
 libcdi/examples/Makefile.am               |     5 +-
 libcdi/examples/Makefile.in               |    10 +-
 libcdi/examples/README                    |     9 +
 libcdi/examples/cdi_copy.c                |     6 +-
 libcdi/examples/cdi_read.c                |     1 +
 libcdi/examples/cdi_read_f2003.f90        |    35 +-
 libcdi/examples/cdi_write_ens.c           |    43 +-
 libcdi/examples/cdi_write_f2003.f90       |    12 +-
 libcdi/examples/pio/Makefile.in           |     1 +
 libcdi/examples/pio/collectData.c         |     4 +-
 libcdi/examples/pio/collectDataNStreams.c |     8 +-
 libcdi/interfaces/Makefile.am             |    18 +-
 libcdi/interfaces/Makefile.in             |    15 +-
 libcdi/interfaces/f2003/bindGen.rb        |   499 +
 libcdi/m4/acx_check_strptr_convert.m4     |   103 +
 libcdi/m4/ax_pthread.m4                   |   155 +-
 libcdi/m4/starlink_fpp.m4                 |     2 +
 libcdi/src/Makefile.am                    |     4 +-
 libcdi/src/Makefile.in                    |    15 +-
 libcdi/src/basetime.c                     |    11 +-
 libcdi/src/basetime.h                     |    11 +
 libcdi/src/calendar.c                     |    12 +-
 libcdi/src/cdf.c                          |    11 +-
 libcdi/src/cdf_int.c                      |    39 +-
 libcdi/src/cdf_int.h                      |    64 +-
 libcdi/src/cdi.h                          |    38 +-
 libcdi/src/cdi.inc                        |   376 +-
 libcdi/src/cdiFortran.c                   |    87 +-
 libcdi/src/cdi_cksum.c                    |     9 +-
 libcdi/src/cdi_int.c                      |   619 +-
 libcdi/src/cdi_int.h                      |    38 +-
 libcdi/src/cdi_util.c                     |    24 +-
 libcdi/src/cdilib.c                       | 27447 +++++++++++++++-------------
 libcdi/src/cgribex.h                      |    23 +-
 libcdi/src/cgribexlib.c                   | 16065 +++++++++-------
 libcdi/src/cksum.c                        |    24 +-
 libcdi/src/cksum.h                        |     2 +-
 libcdi/src/config.h.in                    |     9 +-
 libcdi/src/dmemory.c                      |    67 +-
 libcdi/src/extralib.c                     |    45 +-
 libcdi/src/file.c                         |    82 +-
 libcdi/src/gaussgrid.c                    |    51 +-
 libcdi/src/gaussgrid.h                    |     2 +-
 libcdi/src/gribapi.c                      |    36 +-
 libcdi/src/gribapi.h                      |     2 +-
 libcdi/src/grid.c                         |  1150 +-
 libcdi/src/ieglib.c                       |    36 +-
 libcdi/src/institution.c                  |    53 +-
 libcdi/src/mo_cdi.f90                     |  3842 ++--
 libcdi/src/model.c                        |    31 +-
 libcdi/src/namespace.c                    |     6 +-
 libcdi/src/pio_server.c                   |     5 +-
 libcdi/src/resource_handle.c              |   206 +-
 libcdi/src/resource_handle.h              |    32 +-
 libcdi/src/resource_unpack.c              |    11 +-
 libcdi/src/resource_unpack.h              |     1 +
 libcdi/src/service.h                      |     2 +-
 libcdi/src/servicelib.c                   |    45 +-
 libcdi/src/stream.c                       |  1007 +-
 libcdi/src/stream_cdf.c                   |  1597 +-
 libcdi/src/stream_cdf.h                   |    13 +-
 libcdi/src/stream_cgribex.c               |   296 +-
 libcdi/src/stream_cgribex.h               |     4 +-
 libcdi/src/stream_ext.c                   |   132 +-
 libcdi/src/stream_ext.h                   |     8 +-
 libcdi/src/stream_fcommon.c               |    42 +
 libcdi/src/stream_fcommon.h               |    23 +
 libcdi/src/stream_grb.c                   |   366 +-
 libcdi/src/stream_grb.h                   |    10 +-
 libcdi/src/stream_gribapi.c               |   548 +-
 libcdi/src/stream_gribapi.h               |     2 +-
 libcdi/src/stream_ieg.c                   |   115 +-
 libcdi/src/stream_ieg.h                   |     8 +-
 libcdi/src/stream_record.c                |   338 +-
 libcdi/src/stream_srv.c                   |   136 +-
 libcdi/src/stream_srv.h                   |     8 +-
 libcdi/src/swap.c                         |    55 +-
 libcdi/src/table.c                        |   319 +-
 libcdi/src/table.h                        |  2398 +--
 libcdi/src/tablepar.h                     |    15 +-
 libcdi/src/taxis.c                        |   357 +-
 libcdi/src/taxis.h                        |     3 +
 libcdi/src/timebase.c                     |     4 +-
 libcdi/src/tsteps.c                       |    17 +-
 libcdi/src/varscan.c                      |   148 +-
 libcdi/src/varscan.h                      |     3 +-
 libcdi/src/version.c                      |     6 +-
 libcdi/src/vlist.c                        |   753 +-
 libcdi/src/vlist.h                        |    42 +-
 libcdi/src/vlist_att.c                    |    75 +-
 libcdi/src/vlist_var.c                    |  1017 +-
 libcdi/src/zaxis.c                        |   297 +-
 libcdi/tables/gen_tableheaderfile.in      |   108 +
 libcdi/tests/Makefile.am                  |     3 +-
 libcdi/tests/Makefile.in                  |    10 +-
 libcdi/tests/cksum_read.c                 |    10 +-
 libcdi/tests/cksum_write.c                |    43 +-
 libcdi/tests/deco2d_model.c               |    32 +-
 libcdi/tests/ensure_array_size.c          |     4 +
 libcdi/tests/simple_model.c               |    36 +-
 libcdi/tests/simple_model_helper.c        |     2 +-
 libcdi/tests/stream_cksum.c               |    16 +-
 libcdi/tests/test_f2003.in                |    69 +
 libcdi/tests/test_grib.c                  |    53 +-
 libcdi/tests/test_resource_copy.c         |     9 +-
 m4/._ax_pthread.m4                        |   Bin 0 -> 197 bytes
 m4/acx_options.m4                         |     6 +-
 m4/ax_pthread.m4                          |   155 +-
 src/Cat.c                                 |    25 +-
 src/{Gather.c => Collgrid.c}              |   289 +-
 src/Consecstat.c                          |     3 +-
 src/Detrend.c                             |    13 +-
 src/{Scatter.c => Distgrid.c}             |     2 +-
 src/Ensstat.c                             |    15 +-
 src/Ensstat3.c                            |    22 +-
 src/Ensval.c                              |     2 +-
 src/Eof3d.c                               |    17 +-
 src/Filedes.c                             |     6 +-
 src/Filter.c                              |   233 +-
 src/Fldstat2.c                            |    12 +-
 src/Fourier.c                             |    13 +-
 src/Gradsdes.c                            |  1308 +-
 src/Gridboxstat.c                         |    27 +-
 src/Gridcell.c                            |    15 +-
 src/Gridsearch.c                          |    42 +
 src/Intlevel3d.c                          |    46 +-
 src/Makefile.am                           |     6 +-
 src/Makefile.in                           |   448 +-
 src/Merstat.c                             |    21 +-
 src/Outputgmt.c                           |    11 +-
 src/Remap.c                               |    97 +-
 src/Runpctl.c                             |     1 -
 src/Selbox.c                              |     8 +
 src/Select.c                              |    10 +-
 src/Selvar.c                              |     2 +-
 src/Setgrid.c                             |     4 +-
 src/Sinfo.c                               |    24 +-
 src/Sort.c                                |    27 +-
 src/Split.c                               |     2 +
 src/Splitrec.c                            |     2 +
 src/Splitsel.c                            |     2 +
 src/Splittime.c                           |     5 +
 src/Splityear.c                           |     2 +
 src/Timsort.c                             |    14 +-
 src/Tstepcount.c                          |    14 +-
 src/Ydrunstat.c                           |    34 +-
 src/cdo.h                                 |     4 +
 src/cdo_int.h                             |     2 +
 src/cdo_vlist.c                           |    33 +-
 src/clipping/area.c                       |     2 +-
 src/clipping/clipping.c                   |   280 +-
 src/clipping/clipping.h                   |    41 +-
 src/clipping/geometry.h                   |    69 +-
 src/clipping/grid.h                       |     3 +-
 src/clipping/grid_cell.c                  |     8 +-
 src/clipping/intersection.c               |   349 +-
 src/clipping/utils.h                      |    64 +-
 src/config.h.in                           |     6 +-
 src/exception.c                           |     3 +-
 src/functs.h                              |     2 +-
 src/gradsdeslib.c                         |     5 +-
 src/grid.c                                |    24 +-
 src/grid_area.c                           |   133 +-
 src/griddes.c                             |    36 +-
 src/hetaeta.c                             |     7 +-
 src/interpol.c                            |    13 +-
 src/modules.c                             |    30 +-
 src/operator_help.h                       |   127 +-
 src/pragma_omp_atomic_update.h            |     7 +
 src/process.c                             |    84 +-
 src/pstream.c                             |    85 +-
 src/pstream.h                             |     9 +-
 src/pthread_debug.c                       |    26 +-
 src/remap.h                               |     4 -
 src/remap_bicubic_scrip.c                 |    14 +-
 src/remap_bilinear_scrip.c                |    13 +-
 src/remap_conserv.c                       |   349 +-
 src/remap_conserv_scrip.c                 |   438 +-
 src/remap_distwgt_scrip.c                 |    49 +-
 src/remap_store_link.c                    |     3 +-
 src/remaplib.c                            |    44 +-
 src/remapsort.c                           |     4 +
 src/userlog.c                             |     5 +-
 src/util.c                                |    16 +
 test/Genweights.test.in                   |     2 +-
 test/Makefile.am                          |     2 +-
 test/Makefile.in                          |    13 +-
 test/Read_netcdf.test.in                  |    48 +
 test/data/._netcdf_testfile01.nc          |   Bin 0 -> 197 bytes
 test/data/Makefile.am                     |     6 +-
 test/data/Makefile.in                     |     7 +-
 test/data/netcdf_testfile01.nc            |   Bin 0 -> 63192 bytes
 test/data/netcdf_testfile01_infon_ref     |    13 +
 test/data/netcdf_testfile01_sinfon_ref    |    14 +
 219 files changed, 38866 insertions(+), 30039 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 06f3637..8416843 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,121 @@
-2014-06-26  Uwe Schulzweida
+2015-02-19  Uwe Schulzweida
+
+	* using CDI library version 1.7.0
+	* Version 1.7.0 released
+
+2014-10-30  Uwe Schulzweida
+
+	* remapcon: reactivate normalize option destarea
+
+2014-10-29  Uwe Schulzweida
+
+	* remapcon: deactivate call to remap_normalize() (bug fix)
+
+2014-10-26  Uwe Schulzweida
+
+	* replace >#pragma omp atomic update< by >#include "pragma_omp_atomic_update.h"<
+
+2014-10-23  Uwe Schulzweida
+
+	* using CDI library version 1.6.5
+	* Version 1.6.5 released
+
+2014-10-21  Uwe Schulzweida
+
+	* sortlevel: added optional parameter -1 to reverse the sorting
+
+2014-10-16  Uwe Schulzweida
+
+	* Ydrunstat: set the year of all output timesteps to the lowest year of the output timesteps
+
+2014-10-15  Uwe Schulzweida
+
+	* cdoAbort: close all open CDI streams
+
+2014-10-06  Uwe Schulzweida
+
+	* gather: renamed to collgrid
+	* scatter: renamed to distgrid
+
+2014-09-23  Uwe Schulzweida
+
+	* cat: added support for option -O (overwrite existing output file)
+
+2014-09-19  Uwe Schulzweida
+
+	* --with-fftw3: changed default to no
+	* expand gridfile name parameter [Bug #5196]
+
+2014-09-18  Uwe Schulzweida
+
+	* gradsdes: added support for option 365_day_calendar
+
+2014-09-16  Uwe Schulzweida
+
+	* remapnn::grid_search_nbr: removed wrong omp simd pragma (bug fix)
+
+2014-09-04  Uwe Schulzweida
+
+	* vlistCompare: check flag CMP_CODE only if nvars > 1
+
+2014-08-20  Uwe Schulzweida
+
+	* remapycon: added support for concave grid cells
+
+2014-08-19  Uwe Schulzweida
+
+	* remaplaf: changed weight calculation from SCRIP to YAC
+
+2014-08-16  Uwe Schulzweida
+
+	* import_binary: option 365_day_calendar does not work (big fix)
+
+2014-08-13  Uwe Schulzweida
+
+	* lock call to vlistCopyFlag() [Support #5079]
+
+2014-08-11  Uwe Schulzweida
+
+	* select: print progress status
+
+2014-08-10  Uwe Schulzweida
+
+	* gridarea: added support for concave grid cells
+
+2014-08-06  Uwe Schulzweida
+
+	* setpartab: not callable by this name (bug fix)
+
+2014-07-28  Uwe Schulzweida
+
+	* remap_weights_conserv: changed great_circle_type[8] to great_circle_type[32] (bug fix) 
+	* remap_define_grid: bug fix for unstructured grids (ndims[1])
+
+2014-07-17  Yvonne K�stermann
+
+	* Filter: OpenMP version
+
+2014-07-12  Uwe Schulzweida
+
+	* sellonlatbox: skip variables with only one grid point
+
+2014-07-12  Uwe Schulzweida
+
+	* select: wrong result when select only one timestep (bug fix)
+
+2014-07-07  Uwe Schulzweida
+
+	* cat: added progress status
+
+2014-06-30  Uwe Schulzweida
 
 	* using CDI library version 1.6.4
 	* Version 1.6.4 released
 
+2014-06-30  Uwe Schulzweida
+
+	* Selbox: angle of rotated grid missing (bug fix)
+
 2014-06-19  Uwe Schulzweida
 
 	* Filter: disable zero-padding
diff --git a/NEWS b/NEWS
index a890c12..dea4643 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,20 @@
 CDO NEWS
 --------
 
+Version 1.6.5 (23 October 2014):
+
+   New operators:
+     * distgrid: distribute horizonal grid
+     * collgrid: collect horizontal grid
+   Changed operators:
+     * cat: added support for option -O (overwrite existing output file)
+     * remaplaf: changed calculation of weights from SCRIP to YAC
+   Fixed bugs:
+     * gridarea: added support for concave grid cells
+     * gradsdes: added support for option 365_day_calendar
+     * import_binary: option 365_day_calendar does not work
+     * select: wrong result when select only one timestep
+
 Version 1.6.4 (26 June 2014):
 
    New features:
@@ -11,14 +25,14 @@ Version 1.6.4 (26 June 2014):
      * setpartabp: set parameter table by parameter ID
      * sealevelpressure: sea level pressure
    Changed operators:
+     * Sinfo: changed format of grid and zaxis section
      * Filter: disable zero-padding
      * diff: print number of different values
      * Ymonstat: sorts output by month of year
    Fixed bugs:
-     * Filter:
      * eof3d: set sum of weights to 1
-     * eofcoeff: remove scaling with grib cell area weights
-     * eofcoeff3d: remove scaling with grib cell area weights
+     * eofcoeff: remove scaling with grid cell area weights
+     * eofcoeff3d: remove scaling with grid cell area weights
 
 Version 1.6.3 (18 February 2014):
 
diff --git a/OPERATORS b/OPERATORS
index caac095..5bb990c 100644
--- a/OPERATORS
+++ b/OPERATORS
@@ -58,6 +58,8 @@ Operator catalog:
    Splittime     splityear       Split years
    Splittime     splitmon        Split months
    Splitsel      splitsel        Split time selection
+   Distgrid      distgrid        Distribute horizontal grid
+   Collgrid      collgrid        Collect horizontal grid
 -------------------------------------------------------------
    Selection
 -------------------------------------------------------------
diff --git a/cdo.spec b/cdo.spec
index 50a95b4..cbfdb98 100644
--- a/cdo.spec
+++ b/cdo.spec
@@ -4,7 +4,7 @@
 
 Name:           cdo
 #BuildRequires:  
-Version:        1.6.4
+Version:        1.6.5.1
 Release:        1
 Summary:        Climate Data Operators
 License:        GNU GENERAL PUBLIC LICENSE Version 2, June 1991
diff --git a/config/default b/config/default
index 981638f..8dc1427 100755
--- a/config/default
+++ b/config/default
@@ -5,87 +5,115 @@
 #
 CONFPATH=`echo $0 | cut -c 1-6`
 if [ "$CONFPATH" != "../../" ] ; then
-CONFPATH='./'
+  CONFPATH='./'
 fi
 #
-if test -z "$1" ; then
-  HOSTNAME=`hostname`
-else
-  HOSTNAME=$1
-fi
+COMP=""
+HOSTNAME=`hostname`
+#
+while test $# != 0
+do
+  case $1 in
+      CC=?*)
+          COMP=`expr "X$1" : 'X[^=]*=\(.*\)'`
+          ;;
+      *)
+          HOSTNAME=$1
+          ;;
+  esac
+  shift
+done
 #
 set -x
 #
 case "${HOSTNAME}" in
-    icc)
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --enable-maintainer-mode \
-                    --with-jasper=$HOME/local \
-                    --with-grib_api=$HOME/local/gribapi-1.10.4 \
-                    --with-netcdf=$HOME/local \
-                    --with-hdf5=$HOME/local \
-                    --with-szlib=$HOME/local \
-                    --with-udunits2=$HOME/local/udunits-2.1.24 \
-                    --with-proj=/opt/local \
-                    --with-curl=/opt/local \
-	            CC=icc CFLAGS="-g -Wall -O3 -vec-report2 -march=native -openmp -fp-model source -fast-transcendentals" \
-                    LIBS="-L/opt/local/lib -lopenjpeg"
-	;;
 # i386-apple-darwin10
-    bailung*)
-	${CONFPATH}configure --prefix=$HOME/local \
+    bailung*|d133*|d134*)
+        CDOLIBS="--with-fftw3 \
+                 --with-jasper=$HOME/local \
+                 --with-grib_api=$HOME/local/gribapi-1.12.3 \
+                 --with-netcdf=$HOME/local \
+                 --with-hdf5=$HOME/local \
+                 --with-szlib=$HOME/local \
+                 --with-udunits2=$HOME/local/udunits-2.1.24 \
+                 --with-proj=/opt/local \
+                 --with-curl=/opt/local"
+
+        if  test "$COMP" = icc ; then
+	  ${CONFPATH}configure  \
+                    $CDOLIBS \
+                    LIBS="-L/opt/local/lib -lopenjpeg" \
+	            CC=icc CFLAGS="-g -Wall -O3 -vec-report2 -march=native -fp-model source -fast-transcendentals"
+        elif  test "$COMP" = clang ; then
+	  ${CONFPATH}configure  \
+                    $CDOLIBS \
+                    LIBS="-L/opt/local/lib -lopenjpeg" \
+	            CC=clang CFLAGS="-g -Wall -O3"
+        else
+	  ${CONFPATH}configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
-                    --with-jasper=$HOME/local \
-                    --with-grib_api=$HOME/local/gribapi-1.10.4 \
-                    --with-netcdf=$HOME/local \
-                    --with-hdf5=$HOME/local \
-                    --with-szlib=$HOME/local \
-                    --with-udunits2=$HOME/local/udunits-2.1.24 \
-                    --with-proj=/opt/local \
-                    --with-curl=/opt/local \
-	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -W -Wfloat-equal -std=c99 -pedantic -O3 -march=native" \
-                    LIBS="-L/opt/local/lib -lopenjpeg"
+                    $CDOLIBS \
+                    LIBS="-L/opt/local/lib -lopenjpeg" \
+	            CC=gcc CFLAGS="-g -pipe -Wall -W -Wfloat-equal -pedantic -O3 -march=native -fstack-protector"
 #                    --with-libxml2=/usr 
-#                    --with-magics=/Users/m214003/local/magics-2.14.9 
+#                    --with-magics=/Users/m214003/local/magics-2.14.9
+        fi
 	;;
     hama*)
-	${CONFPATH}configure --prefix=$HOME/local \
+        CDOLIBS="--with-fftw3 \
+                 --with-jasper=/opt/local \
+                 --with-grib_api=$HOME/local/gribapi-1.9.16 \
+                 --with-netcdf=/opt/local \
+                 --with-hdf5=/opt/local \
+                 --with-szlib=$HOME/local \
+                 --with-proj=/opt/local \
+                 --with-curl=/opt/local"
+
+        if  test "$COMP" = icc ; then
+	  ${CONFPATH}configure --prefix=$HOME/local \
+                    $CDOLIBS \
+	            CC=icc CFLAGS="-g -Wall -O3 -vec-report2 -march=native -openmp -fp-model source -fast-transcendentals"
+        elif  test "$COMP" = clang ; then
+	  ${CONFPATH}configure  \
+                    $CDOLIBS \
+	            CC=clang CFLAGS="-g -Wall -O3"
+        else
+	  ${CONFPATH}configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
-                    --with-jasper=/opt/local \
-                    --with-grib_api=$HOME/local/gribapi-1.9.16 \
-                    --with-netcdf=/opt/local \
-                    --with-hdf5=/opt/local \
-                    --with-szlib=$HOME/local \
-                    --with-proj=/opt/local \
-                    --with-curl=/opt/local \
-	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -W -Wfloat-equal -pedantic -O3 -march=native"
+                    $CDOLIBS \
+	            CC=gcc CFLAGS="-g -pipe -Wall -W -Wfloat-equal -pedantic -O3 -march=native -fstack-protector"
 #                    --with-libxml2=/usr \
 #                    --with-magics=/Users/m214003/local/Magics-2.18.14nio \
-	;;
-# ia64-xxx-linux
-    ds*)
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --with-netcdf=/pool/ia64/netcdf/netcdf-3.6.0-p1 \
-                    --with-szlib=$HOME/local \
-                    CC=icc CFLAGS="-g -O2 -Wall -fno-alias -DMIN_BUF_SIZE=4194304"
-	;;
-    wasser*)
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --with-netcdf=/home/dkrz/m214089/local/ia64 \
-                    CC=icc CFLAGS="-g -O2 -Wall -fno-alias"
+        fi
 	;;
 # x86_64-squeeze-x64-linux
     thunder*)
-        ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
-                    --enable-all-static \
-                    --with-jasper=/sw/squeeze-x64/jasper-1.900.1-static \
+        CDOLIBS="--with-jasper=/sw/squeeze-x64/jasper-1.900.1-static \
                     --with-grib_api=/sw/squeeze-x64/grib_api-1.9.9-static \
                     --with-netcdf=/sw/squeeze-x64/netcdf-4.2-static \
                     --with-hdf5=/sw/squeeze-x64/hdf5-1.8.8-static \
                     --with-szlib=/sw/squeeze-x64/szip-2.1 \
                     --with-udunits2=/sw/squeeze-x64/udunits-2.1.19 \
-                    --with-proj=/sw/squeeze-x64/proj-4.7.0 \
-                    CC=gcc CFLAGS='-g -Wall -O3 -march=native'
+                    --with-proj=/sw/squeeze-x64/proj-4.7.0"
+
+        if  test "$COMP" = icc ; then
+          ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+                    --enable-all-static \
+                    --with-fftw3 \
+                    $CDOLIBS \
+	            CC=icc CFLAGS="-g -Wall -O3 -vec-report2 -march=native -fp-model source -fast-transcendentals"
+        elif  test "$COMP" = pgcc ; then
+          ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+                    --enable-all-static \
+                    $CDOLIBS \
+	            CC=pgcc CFLAGS="-g -fast"
+	else
+          ${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+                    --enable-all-static \
+                    --with-fftw3 \
+                    $CDOLIBS \
+                    CC=gcc CFLAGS='-g -Wall -O3 -mavx'
+	fi
 	;;
 # x86_64-lenny-linux-gnu
     squall*)
@@ -100,6 +128,18 @@ case "${HOSTNAME}" in
                     --with-proj=/sw/squeeze-x64/proj-4.7.0 \
                     CC=gcc CFLAGS='-g -Wall -O3'
 	;;
+# ia64-xxx-linux
+    ds*)
+	${CONFPATH}configure --prefix=$HOME/local \
+                    --with-netcdf=/pool/ia64/netcdf/netcdf-3.6.0-p1 \
+                    --with-szlib=$HOME/local \
+                    CC=icc CFLAGS="-g -O2 -Wall -fno-alias -DMIN_BUF_SIZE=4194304"
+	;;
+    wasser*)
+	${CONFPATH}configure --prefix=$HOME/local \
+                    --with-netcdf=/home/dkrz/m214089/local/ia64 \
+                    CC=icc CFLAGS="-g -O2 -Wall -fno-alias"
+	;;
 # x86_64-archlinux
     thingol*)
  	${CONFPATH}configure --prefix=$HOME/local \
@@ -170,23 +210,15 @@ case "${HOSTNAME}" in
         LDFLAGS="-lpng"
         export LDFLAGS
 	${CONFPATH}configure --prefix=$HOME/local/centos58-x64 \
+                    --with-proj=/sw/centos58-x64/proj-4.7.0 \
+                    --with-hdf5=/sw/centos58-x64/hdf5-1.8.10-patch1 \
+                    --with-udunits2=/sw/centos58-x64/udunits-2.1.19 \
                     --with-jasper=/sw/centos58-x64/jasper-1.900.1 \
                     --with-grib_api=/sw/centos58-x64/grib_api-1.9.0-static \
                     --with-netcdf=/sw/centos58-x64/netcdf-4.2.1.1 \
                     --with-szlib=/sw/centos58-x64/szip-2.1 \
                     --with-zlib=/usr \
-	            CC=gcc44 CFLAGS="-g -Wall -O3"
-	;;
-# powerpc-ibm-aix5.2.0.0
-    ecga*)
-
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --with-jasper=/usr/local/lib/metaps/lib/grib_api/jasper_64 \
-                    --with-grib_api=$HOME/gribapi/1.9.8 \
-                    --with-netcdf=/usr/local/apps/netCDF/3.6.2/LP64 \
-                    --with-szlib=$HOME/local \
-                    AR="ar -X 64"  LDFLAGS="-brtl" \
-	            CC=xlc_r CFLAGS="-g -O3 -q64 -qhot -qstrict -qarch=auto -qtune=auto -qsmp=omp -DHAVE_MMAP -qthreaded"
+	            CC=gcc CFLAGS="-g -Wall -O3"
 	;;
 # powerpc-ibm-aix5.3.0.0
     blizzard*)
@@ -202,13 +234,6 @@ case "${HOSTNAME}" in
                     AR="ar -X 64"  LDFLAGS="-brtl -R/sw/aix61/openssl-1.0.0d/lib:/sw/aix61/zlib-1.2.6/lib" \
  	            CC=xlc_r CFLAGS="-g -O3 -q64 -qhot -qstrict -qarch=auto -qtune=auto -qsmp=omp -DHAVE_MMAP -qthreaded"
 	;;
-    vip*)
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --with-netcdf=$HOME/local \
-                    --with-szlib=$HOME/local \
-                    AR="ar -X 64"  LDFLAGS="-brtl" \
-	            CC=xlc_r CFLAGS="-g -O3 -q64 -qhot -qstrict -qarch=auto -qtune=auto -qsmp=omp -DHAVE_MMAP -qthreaded"
-	;;
 # powerpc-ibm-aix6.0.0.0
     c1a*)
 	${CONFPATH}configure --prefix=$HOME/local \
@@ -218,14 +243,15 @@ case "${HOSTNAME}" in
                     AR="ar -X 64"  LDFLAGS="-brtl" \
 	            CC=xlc_r CFLAGS="-g -O3 -q64 -qhot -qstrict -qarch=auto -qtune=auto -qsmp=omp -DHAVE_MMAP -qthreaded"
 	;;
-# powerpc-ibm-aix6.0.0.0
-    dwd | p???et01)
-	${CONFPATH}configure --prefix=$HOME/local \
-                    --with-netcdf=/uhome/mpischul/local \
-                    AR="ar -X 64"  LDFLAGS="-brtl" \
-	            CC=xlc_r CFLAGS="-g -O3 -q64 -qhot -qstrict -qarch=auto -qtune=auto -qsmp=omp -DHAVE_MMAP -qthreaded"
-	;;
     *)
 	echo "configuration for hostname $HOSTNAME not found!"
 	;;
+# x86_64-unknown-linux-gnu (cray)
+    brisi*)
+        ${CONFPATH}configure  \
+                    --with-netcdf=/opt/cray/netcdf/4.3.2/INTEL/140 \
+                    --with-hdf5=/opt/cray/hdf5/1.8.13/INTEL/140 \
+                    --with-fftw3 \
+                    CC=gcc CFLAGS='-g -Wall -O3'
+	;;
 esac
diff --git a/configure b/configure
index 6aa21b8..919a2ff 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 cdo 1.6.4.
+# Generated by GNU Autoconf 2.68 for cdo 1.6.5.1.
 #
 # Report bugs to <http://code.zmaw.de/projects/cdo>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdo'
 PACKAGE_TARNAME='cdo'
-PACKAGE_VERSION='1.6.4'
-PACKAGE_STRING='cdo 1.6.4'
+PACKAGE_VERSION='1.6.5.1'
+PACKAGE_STRING='cdo 1.6.5.1'
 PACKAGE_BUGREPORT='http://code.zmaw.de/projects/cdo'
 PACKAGE_URL=''
 
@@ -621,6 +621,12 @@ AM_CPPFLAGS
 CLIBS
 CLDFLAGS
 FCFLAGS
+BUILD_AVX2_TESTS_FALSE
+BUILD_AVX2_TESTS_TRUE
+BUILD_AVX_TESTS_FALSE
+BUILD_AVX_TESTS_TRUE
+BUILD_SSE42_TESTS_FALSE
+BUILD_SSE42_TESTS_TRUE
 ENABLE_ALL_STATIC_FALSE
 ENABLE_ALL_STATIC_TRUE
 subdirs
@@ -1385,7 +1391,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 cdo 1.6.4 to adapt to many kinds of systems.
+\`configure' configures cdo 1.6.5.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1455,7 +1461,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdo 1.6.4:";;
+     short | recursive ) echo "Configuration of cdo 1.6.5.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1518,7 +1524,7 @@ Optional Packages:
                           library for grib2 compression; if a directory is
                           given, it will be used as a value for
                           --with-jasper-root
-  --without-fftw3         disable support for fftw3
+  --with-fftw3            enable support for fftw3
   --with-proj=<directory> Specify location of PROJ library for cartographic
                           projections.
   --with-curl=<directory> Specify location of CURL library.
@@ -1609,7 +1615,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdo configure 1.6.4
+cdo configure 1.6.5.1
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2202,7 +2208,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 cdo $as_me 1.6.4, which was
+It was created by cdo $as_me 1.6.5.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3145,7 +3151,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdo'
- VERSION='1.6.4'
+ VERSION='1.6.5.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -17329,7 +17335,7 @@ _ACEOF
 fi
 
 #  ----------------------------------------------------------------------
-#  Enable GRIB support
+#  Enable DATA support
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DATA support" >&5
 $as_echo_n "checking for DATA support... " >&6; }
 # Check whether --enable-data was given.
@@ -17351,6 +17357,7 @@ fi
 $as_echo "$enable_data" >&6; }
 ENABLE_DATA=$enable_data
 
+
 #  ----------------------------------------------------------------------
 CFLAGS="$CFLAGS ${OPENMP_CFLAGS}"
 #  ----------------------------------------------------------------------
@@ -17380,7 +17387,6 @@ $as_echo "suppressed" >&6; } ;; #(
   yes) :
 
 
-
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -17468,8 +17474,8 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
 # --thread-safe: KAI C++
 # pthread-config: use pthread-config program (for GNU Pth library)
 
-case "${host_cpu}-${host_os}" in
-        *solaris*)
+case ${host_os} in
+        solaris*)
 
         # On Solaris (at least, for some versions), libc contains stubbed
         # (non-functional) versions of the pthreads routines, so link-based
@@ -17482,11 +17488,42 @@ case "${host_cpu}-${host_os}" in
         ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
         ;;
 
-	*-darwin*)
-	ax_pthread_flags="-pthread $ax_pthread_flags"
-	;;
+        darwin*)
+        ax_pthread_flags="-pthread $ax_pthread_flags"
+        ;;
 esac
 
+# Clang doesn't consider unrecognized options an error unless we specify
+# -Werror. We throw in some extra Clang-specific options to ensure that
+# this doesn't happen for GCC, which also accepts -Werror.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler needs -Werror to reject unknown flags" >&5
+$as_echo_n "checking if compiler needs -Werror to reject unknown flags... " >&6; }
+save_CFLAGS="$CFLAGS"
+ax_pthread_extra_flags="-Werror"
+CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void);
+int
+main ()
+{
+foo()
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  ax_pthread_extra_flags=
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS="$save_CFLAGS"
+
 if test x"$ax_pthread_ok" = xno; then
 for flag in $ax_pthread_flags; do
 
@@ -17502,8 +17539,8 @@ $as_echo_n "checking whether pthreads work with $flag... " >&6; }
                 PTHREAD_CFLAGS="$flag"
                 ;;
 
-		pthread-config)
-		# Extract the first word of "pthread-config", so it can be a program name with args.
+                pthread-config)
+                # Extract the first word of "pthread-config", so it can be a program name with args.
 set dummy pthread-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
@@ -17541,10 +17578,10 @@ $as_echo "no" >&6; }
 fi
 
 
-		if test x"$ax_pthread_config" = xno; then continue; fi
-		PTHREAD_CFLAGS="`pthread-config --cflags`"
-		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-		;;
+                if test x"$ax_pthread_config" = xno; then continue; fi
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
 
                 *)
                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5
@@ -17556,7 +17593,7 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; }
         save_LIBS="$LIBS"
         save_CFLAGS="$CFLAGS"
         LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
 
         # Check for various functions.  We must include pthread.h,
         # since some functions may be macros.  (On the Sequent, we
@@ -17570,17 +17607,17 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; }
         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <pthread.h>
-		     static void routine(void* a) {a=0;}
-		     static void* start_routine(void* a) {return a;}
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }
 int
 main ()
 {
 pthread_t th; pthread_attr_t attr;
-                     pthread_create(&th,0,start_routine,0);
-                     pthread_join(th, 0);
-                     pthread_attr_init(&attr);
-                     pthread_cleanup_push(routine, 0);
-                     pthread_cleanup_pop(0);
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */
   ;
   return 0;
 }
@@ -17613,17 +17650,17 @@ if test "x$ax_pthread_ok" = xyes; then
         CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
 
         # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
 $as_echo_n "checking for joinable pthread attribute... " >&6; }
-	attr_name=unknown
-	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+        attr_name=unknown
+        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <pthread.h>
 int
 main ()
 {
-int attr=$attr; return attr;
+int attr = $attr; return attr /* ; */
   ;
   return 0;
 }
@@ -17633,7 +17670,7 @@ if ac_fn_c_try_link "$LINENO"; then :
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-	done
+        done
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5
 $as_echo "$attr_name" >&6; }
         if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
@@ -17647,22 +17684,75 @@ _ACEOF
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5
 $as_echo_n "checking if more special flags are required for pthreads... " >&6; }
         flag=no
-        case "${host_cpu}-${host_os}" in
-            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        case ${host_os} in
+            aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+            osf* | hpux*) flag="-D_REENTRANT";;
+            solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                # TODO: What about Clang on Solaris?
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
-$as_echo "${flag}" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag" >&5
+$as_echo "$flag" >&6; }
         if test "x$flag" != xno; then
             PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
         fi
 
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
+$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; }
+if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+int i = PTHREAD_PRIO_INHERIT;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ax_cv_PTHREAD_PRIO_INHERIT=yes
+else
+  ax_cv_PTHREAD_PRIO_INHERIT=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
+$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
+        if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then :
+
+$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
+
+fi
+
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        # More AIX lossage: must compile with xlc_r or cc_r
-	if test x"$GCC" != xyes -a \( x"$CC" = xxlc -o x"$CC" = cc \) ; then
-          for ac_prog in xlc_r cc_r
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != xyes; then
+            case $host_os in
+                aix*)
+                case "x/$CC" in #(
+  x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
+    #handle absolute path differently from PATH based program lookup
+                   case "x$CC" in #(
+  x/*) :
+    if { test -f ${CC}_r && $as_test_x ${CC}_r; }; then :
+  PTHREAD_CC="${CC}_r"
+fi ;; #(
+  *) :
+    for ac_prog in ${CC}_r
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -17703,15 +17793,19 @@ fi
 
   test -n "$PTHREAD_CC" && break
 done
-test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
-
-        else
-          PTHREAD_CC=$CC
-	fi
-else
-        PTHREAD_CC="$CC"
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+ ;;
+esac ;; #(
+  *) :
+     ;;
+esac
+                ;;
+            esac
+        fi
 fi
 
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
 
 
 
@@ -19352,7 +19446,7 @@ $as_echo_n "checking for FFTW3 support... " >&6; }
 if test "${with_fftw3+set}" = set; then :
   withval=$with_fftw3;
 else
-  with_fftw3=yes
+  with_fftw3=no
 fi
 
 
@@ -20457,6 +20551,159 @@ else
 fi
 
 
+
+#  ----------------------------------------------------------------------
+
+# configure code from valgrind
+
+# does the x86/amd64 assembler understand SSE 4.2 instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_SSE42_TESTS), used in test Makefile.am's
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if x86/amd64 assembler speaks SSE4.2" >&5
+$as_echo_n "checking if x86/amd64 assembler speaks SSE4.2... " >&6; }
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  do { long long int x;
+   __asm__ __volatile__(
+      "crc32q %%r15,%%r15" : : : "r15" );
+   __asm__ __volatile__(
+      "pblendvb (%%rcx), %%xmm11" : : : "memory", "xmm11");
+   __asm__ __volatile__(
+      "aesdec %%xmm2, %%xmm1" : : : "xmm2", "xmm1"); }
+  while (0)
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ac_have_as_sse42=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ac_have_as_sse42=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test x$ac_have_as_sse42 = xyes; then
+  BUILD_SSE42_TESTS_TRUE=
+  BUILD_SSE42_TESTS_FALSE='#'
+else
+  BUILD_SSE42_TESTS_TRUE='#'
+  BUILD_SSE42_TESTS_FALSE=
+fi
+
+
+
+# does the x86/amd64 assembler understand AVX instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_AVX_TESTS), used in test Makefile.am's
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if x86/amd64 assembler speaks AVX" >&5
+$as_echo_n "checking if x86/amd64 assembler speaks AVX... " >&6; }
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  do { long long int x;
+   __asm__ __volatile__(
+      "vmovupd (%%rsp), %%ymm7" : : : "xmm7" );
+   __asm__ __volatile__(
+      "vaddpd %%ymm6,%%ymm7,%%ymm8" : : : "xmm6","xmm7","xmm8"); }
+  while (0)
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ac_have_as_avx=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ac_have_as_avx=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test x$ac_have_as_avx = xyes; then
+  BUILD_AVX_TESTS_TRUE=
+  BUILD_AVX_TESTS_FALSE='#'
+else
+  BUILD_AVX_TESTS_TRUE='#'
+  BUILD_AVX_TESTS_FALSE=
+fi
+
+
+
+# does the x86/amd64 assembler understand AVX2 instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_AVX2_TESTS), used in test Makefile.am's
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if x86/amd64 assembler speaks AVX2" >&5
+$as_echo_n "checking if x86/amd64 assembler speaks AVX2... " >&6; }
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  do { long long int x;
+   __asm__ __volatile__(
+      "vpsravd (%%rsp), %%ymm8, %%ymm7" : : : "xmm7", "xmm8" );
+   __asm__ __volatile__(
+      "vpaddb %%ymm6,%%ymm7,%%ymm8" : : : "xmm6","xmm7","xmm8"); }
+  while (0)
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ac_have_as_avx2=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ac_have_as_avx2=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ if test x$ac_have_as_avx2 = xyes; then
+  BUILD_AVX2_TESTS_TRUE=
+  BUILD_AVX2_TESTS_FALSE='#'
+else
+  BUILD_AVX2_TESTS_TRUE='#'
+  BUILD_AVX2_TESTS_FALSE=
+fi
+
+
 #  ----------------------------------------------------------------------
 
 
@@ -20518,7 +20765,7 @@ fi
 done
 
 
-ac_config_files="$ac_config_files test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test"
+ac_config_files="$ac_config_files test/Read_netcdf.test test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test"
 
 ac_config_files="$ac_config_files test/Select.test test/Spectral.test test/Timstat.test test/Vertint.test"
 
@@ -20679,6 +20926,18 @@ if test -z "${ENABLE_ALL_STATIC_TRUE}" && test -z "${ENABLE_ALL_STATIC_FALSE}";
   as_fn_error $? "conditional \"ENABLE_ALL_STATIC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${BUILD_SSE42_TESTS_TRUE}" && test -z "${BUILD_SSE42_TESTS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_SSE42_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_AVX_TESTS_TRUE}" && test -z "${BUILD_AVX_TESTS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_AVX_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_AVX2_TESTS_TRUE}" && test -z "${BUILD_AVX2_TESTS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_AVX2_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -21088,7 +21347,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 cdo $as_me 1.6.4, which was
+This file was extended by cdo $as_me 1.6.5.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21154,7 +21413,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="\\
-cdo config.status 1.6.4
+cdo config.status 1.6.5.1
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -21661,6 +21920,7 @@ do
     "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
     "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "test/Read_netcdf.test") CONFIG_FILES="$CONFIG_FILES test/Read_netcdf.test" ;;
     "test/Cat.test") CONFIG_FILES="$CONFIG_FILES test/Cat.test" ;;
     "test/Gridarea.test") CONFIG_FILES="$CONFIG_FILES test/Gridarea.test" ;;
     "test/Genweights.test") CONFIG_FILES="$CONFIG_FILES test/Genweights.test" ;;
@@ -23162,6 +23422,7 @@ compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
 _LT_EOF
 
  ;;
+    "test/Read_netcdf.test":F) chmod a+x "$ac_file" ;;
     "test/Cat.test":F) chmod a+x "$ac_file" ;;
     "test/Gridarea.test":F) chmod a+x "$ac_file" ;;
     "test/Genweights.test":F) chmod a+x "$ac_file" ;;
diff --git a/configure.ac b/configure.ac
index 5509a95..c2ddf3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdo], [1.6.4], [http://code.zmaw.de/projects/cdo])
+AC_INIT([cdo], [1.6.5.1], [http://code.zmaw.de/projects/cdo])
 
 CONFIG_ABORT=yes
 AC_CONFIG_AUX_DIR(config)
@@ -13,7 +13,7 @@ AC_CANONICAL_HOST
 AC_CANONICAL_BUILD
 
 # AM_INIT_AUTOMAKE([foreign -Wall -Werror])
-AM_INIT_AUTOMAKE([foreign -Wall])
+AM_INIT_AUTOMAKE([subdir-objects foreign -Wall])
 AC_CONFIG_HEADERS([src/config.h])
 AM_MAINTAINER_MODE([disable])
 
@@ -105,7 +105,7 @@ AC_SUBST([SYSTEM_TYPE],["$ac_cv_build"])
 #  Check for math library
 AC_CHECK_LIB([m],[floor])
 #  ----------------------------------------------------------------------
-#  Enable GRIB support
+#  Enable DATA support
 AC_MSG_CHECKING([for DATA support])
 AC_ARG_ENABLE([data],
               [AS_HELP_STRING([--enable-data],[DATA support [default=yes]])],
@@ -116,12 +116,88 @@ AC_ARG_ENABLE([data],
                enable_data=yes])
 AC_MSG_RESULT([$enable_data])
 AC_SUBST([ENABLE_DATA],[$enable_data])
+
 #  ----------------------------------------------------------------------
 CFLAGS="$CFLAGS ${OPENMP_CFLAGS}"
 #  ----------------------------------------------------------------------
 
 # Add configure options
 ACX_OPTIONS
+
+#  ----------------------------------------------------------------------
+
+# configure code from valgrind
+
+# does the x86/amd64 assembler understand SSE 4.2 instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_SSE42_TESTS), used in test Makefile.am's
+AC_MSG_CHECKING([if x86/amd64 assembler speaks SSE4.2])
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+  do { long long int x; 
+   __asm__ __volatile__(
+      "crc32q %%r15,%%r15" : : : "r15" );
+   __asm__ __volatile__(
+      "pblendvb (%%rcx), %%xmm11" : : : "memory", "xmm11"); 
+   __asm__ __volatile__(
+      "aesdec %%xmm2, %%xmm1" : : : "xmm2", "xmm1"); }
+  while (0)
+]])], [
+ac_have_as_sse42=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_as_sse42=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(BUILD_SSE42_TESTS, test x$ac_have_as_sse42 = xyes)
+
+
+# does the x86/amd64 assembler understand AVX instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_AVX_TESTS), used in test Makefile.am's
+AC_MSG_CHECKING([if x86/amd64 assembler speaks AVX])
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+  do { long long int x; 
+   __asm__ __volatile__(
+      "vmovupd (%%rsp), %%ymm7" : : : "xmm7" );
+   __asm__ __volatile__(
+      "vaddpd %%ymm6,%%ymm7,%%ymm8" : : : "xmm6","xmm7","xmm8"); }
+  while (0)
+]])], [
+ac_have_as_avx=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_as_avx=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(BUILD_AVX_TESTS, test x$ac_have_as_avx = xyes)
+
+
+# does the x86/amd64 assembler understand AVX2 instructions?
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_AVX2_TESTS), used in test Makefile.am's
+AC_MSG_CHECKING([if x86/amd64 assembler speaks AVX2])
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+  do { long long int x; 
+   __asm__ __volatile__(
+      "vpsravd (%%rsp), %%ymm8, %%ymm7" : : : "xmm7", "xmm8" );
+   __asm__ __volatile__(
+      "vpaddb %%ymm6,%%ymm7,%%ymm8" : : : "xmm6","xmm7","xmm8"); }
+  while (0)
+]])], [
+ac_have_as_avx2=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_as_avx2=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(BUILD_AVX2_TESTS, test x$ac_have_as_avx2 = xyes)
+
 #  ----------------------------------------------------------------------
 AC_SUBST([CPPFLAGS])
 AC_SUBST([FCFLAGS])
@@ -138,7 +214,7 @@ AC_DEFINE_UNQUOTED(COMPILER, ["$COMPILER"], [Compiler])
 AC_REQUIRE_AUX_FILE([tap-driver.sh])
 AC_PROG_AWK
 
-AC_CONFIG_FILES([test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Read_netcdf.test test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/Select.test test/Spectral.test test/Timstat.test test/Vertint.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/Detrend.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([Makefile src/Makefile contrib/Makefile test/Makefile test/data/Makefile cdo.spec cdo.settings])
diff --git a/contrib/cdoCompletion.bash b/contrib/cdoCompletion.bash
index 9d788bb..55b8f2b 100644
--- a/contrib/cdoCompletion.bash
+++ b/contrib/cdoCompletion.bash
@@ -56,6 +56,7 @@ chunit -chunit \
 chvar -chvar \
 cloudlayer -cloudlayer \
 cmd -cmd \
+collgrid -collgrid \
 com -com \
 command -command \
 complextorect -complextorect \
@@ -95,6 +96,7 @@ diffc -diffc \
 diffn -diffn \
 diffp -diffp \
 diffv -diffv \
+distgrid -distgrid \
 div -div \
 divc -divc \
 divcoslat -divcoslat \
@@ -609,7 +611,9 @@ template1 -template1 \
 template2 -template2 \
 test -test \
 test2 -test2 \
+testcellsearch -testcellsearch \
 testdata -testdata \
+testpointsearch -testpointsearch \
 thinout -thinout \
 timavg -timavg \
 timcor -timcor \
diff --git a/contrib/cdoCompletion.tcsh b/contrib/cdoCompletion.tcsh
index 42b4570..296225b 100644
--- a/contrib/cdoCompletion.tcsh
+++ b/contrib/cdoCompletion.tcsh
@@ -56,6 +56,7 @@ chunit \
 chvar \
 cloudlayer \
 cmd \
+collgrid \
 com \
 command \
 complextorect \
@@ -95,6 +96,7 @@ diffc \
 diffn \
 diffp \
 diffv \
+distgrid \
 div \
 divc \
 divcoslat \
@@ -609,7 +611,9 @@ template1 \
 template2 \
 test \
 test2 \
+testcellsearch \
 testdata \
+testpointsearch \
 thinout \
 timavg \
 timcor \
diff --git a/contrib/cdoCompletion.zsh b/contrib/cdoCompletion.zsh
index a134b83..f7c551c 100644
--- a/contrib/cdoCompletion.zsh
+++ b/contrib/cdoCompletion.zsh
@@ -56,6 +56,7 @@ chunit -chunit \
 chvar -chvar \
 cloudlayer -cloudlayer \
 cmd -cmd \
+collgrid -collgrid \
 com -com \
 command -command \
 complextorect -complextorect \
@@ -95,6 +96,7 @@ diffc -diffc \
 diffn -diffn \
 diffp -diffp \
 diffv -diffv \
+distgrid -distgrid \
 div -div \
 divc -divc \
 divcoslat -divcoslat \
@@ -609,7 +611,9 @@ template1 -template1 \
 template2 -template2 \
 test -test \
 test2 -test2 \
+testcellsearch -testcellsearch \
 testdata -testdata \
+testpointsearch -testpointsearch \
 thinout -thinout \
 timavg -timavg \
 timcor -timcor \
diff --git a/doc/cdo.pdf b/doc/cdo.pdf
index b97cf4a..abe6e3b 100644
Binary files a/doc/cdo.pdf and b/doc/cdo.pdf differ
diff --git a/doc/cdo_refcard.pdf b/doc/cdo_refcard.pdf
index 0d8488f..d161726 100644
Binary files a/doc/cdo_refcard.pdf and b/doc/cdo_refcard.pdf differ
diff --git a/libcdi/ChangeLog b/libcdi/ChangeLog
index 9fe4841..f063a7b 100644
--- a/libcdi/ChangeLog
+++ b/libcdi/ChangeLog
@@ -1,3 +1,103 @@
+2014-10-31  Uwe Schulzweida
+
+	* Version 1.6.5.1 released
+
+2014-10-31  Uwe Schulzweida
+
+	* netCDF: call set_validrangeDP() in cdfReadVar() (bug fix)
+	* netCDF: call cdfDoInputDataTransformation() if have missvals (bug fix)
+
+2014-10-24  Uwe Schulzweida
+
+        * gridCompare: change limit of difference from 0.001 to 0.0015
+
+2014-10-23  Nathanael Huebbe
+
+	* resource_handle: optimize error messages
+
+2014-10-23  Uwe Schulzweida
+
+	* Version 1.6.5 released
+	* using CGRIBEX library version 1.6.5
+
+2014-10-21  Uwe Schulzweida
+
+	* vlistDefVarXXXKey: check validity of vlist object [Feature #4720]
+	* lock CDI internal vlist objects
+
+2014-10-13  Uwe Schulzweida
+
+	* added support for grib_api key typeOfSecondFixedSurface
+
+2014-10-10  Uwe Schulzweida
+
+	* netCDF: added support 1D level variables
+
+2014-10-07  Uwe Schulzweida
+
+	* read netCDF: cache time variable
+
+2014-08-21  Uwe Schulzweida
+
+	* reshGetElem: call show_stackframe() to print a backtrace 
+
+2014-08-20  Uwe Schulzweida
+
+	* added CDI function gribapiLibraryVersion(major_version, minor_version, revision_version) [Feature #5043]
+
+2014-08-15  Uwe Schulzweida
+
+	* gridCompare: check position parameter of unstructured grids only if gridnumber > 0
+
+2014-08-13  Uwe Schulzweida
+
+	* cgribex: use timerange indicator to identify different variables
+	* gribapi: use timerange indicator to identify different variables
+
+2014-08-12  Daniel Reinert
+
+	* listDestroy(): set resHListSize=0 [Bug #5058]
+	* NetCDF: Reading uuidOfVGrid [Bug #5046]
+
+2014-08-04  Nathanael Huebbe
+
+	* NetCDF single precision input
+
+2014-07-31  Uwe Schulzweida
+
+	* netCDF4: added support for xtype NC_STRING
+
+2014-07-25  Uwe Schulzweida
+
+	* vlistInqAtt: return -1 if attnum is out of range
+	* vlistInqAttXXX: return -1 if attname not found
+
+2014-07-24  Uwe Schulzweida
+
+	* gribapiEncode: update additional keys defined with vlistDefVarXXXKey() [Feature #4720]
+
+2014-07-22  Uwe Schulzweida
+
+	* added vlistDefVarProductDefinitionTemplate() to define GRIB2 Product Definition Template Number [Feature #4694]
+
+2014-07-21  Uwe Schulzweida
+
+	* gribapiDefSteptype: changed proDefTempNum to 1/11 for typeOfGeneratingProcess=4
+	* file write: set default to NONBLOCK if available
+
+2014-07-18  Uwe Schulzweida
+
+	* added function streamReadVarF() and streamReadVarSliceF()
+	* streamWriteVarF, streamWriteVarSliceF: added support for GRIB1 (cgribex)
+
+2014-07-17  Uwe Schulzweida
+
+	* grib2: activate jpeg support in combination with masks (missing values)
+
+2014-07-01  Uwe Schulzweida
+
+	* netCDF: skip coordinate variables with more than 2 dimension
+
 2014-06-26  Uwe Schulzweida
 
 	* Version 1.6.4 released
diff --git a/libcdi/Makefile.in b/libcdi/Makefile.in
index 3b06290..8d3d571 100644
--- a/libcdi/Makefile.in
+++ b/libcdi/Makefile.in
@@ -81,6 +81,7 @@ subdir = .
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/configure $(am__configure_deps) \
 	$(top_srcdir)/config/mkinstalldirs \
+	$(top_srcdir)/tables/gen_tableheaderfile.in \
 	$(top_srcdir)/util/serialrun.in $(srcdir)/cdi.settings.in \
 	$(top_srcdir)/src/pkgconfig/cdi.pc.in \
 	$(top_srcdir)/src/pkgconfig/cdipio.pc.in AUTHORS COPYING \
@@ -95,6 +96,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
@@ -111,8 +113,8 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/src/config.h
-CONFIG_CLEAN_FILES = util/serialrun cdi.settings src/pkgconfig/cdi.pc \
-	src/pkgconfig/cdipio.pc
+CONFIG_CLEAN_FILES = tables/gen_tableheaderfile util/serialrun \
+	cdi.settings src/pkgconfig/cdi.pc src/pkgconfig/cdipio.pc
 CONFIG_CLEAN_VPATH_FILES =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -452,6 +454,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
 	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
 $(am__aclocal_m4_deps):
+tables/gen_tableheaderfile: $(top_builddir)/config.status $(top_srcdir)/tables/gen_tableheaderfile.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
 util/serialrun: $(top_builddir)/config.status $(top_srcdir)/util/serialrun.in
 	cd $(top_builddir) && $(SHELL) ./config.status $@
 cdi.settings: $(top_builddir)/config.status $(srcdir)/cdi.settings.in
diff --git a/libcdi/NEWS b/libcdi/NEWS
index 9bfc827..2d77819 100644
--- a/libcdi/NEWS
+++ b/libcdi/NEWS
@@ -1,12 +1,31 @@
 CDI NEWS
 --------
 
+Version 1.6.5 (23 October 2014):
+
+   New features:
+     * NetCDF: single precision input
+     * netCDF4: added support for xtype NC_STRING
+     * added CDI function gribapiLibraryVersion(major_version, minor_version, revision_version) [Feature #5043]
+     * gribapiEncode: update additional keys defined with vlistDefVarXXXKey() [Feature #4720]
+     * added vlistDefVarProductDefinitionTemplate() to define GRIB2 Product Definition Template Number [Feature #4694]
+     * streamWriteVarF, streamWriteVarSliceF: added support for GRIB1 (cgribex)
+     * grib2: activate jpeg support in combination with masks (missing values)
+   Fixed bugs:
+     * listDestroy(): set resHListSize=0 [Bug #5058]
+     * NetCDF: Reading uuidOfVGrid [Bug #5046]
+
+
 Version 1.6.4 (26 June 2014):
 
    New features:
      * Added support for SPECS forecast time axis
+     * Added support for GRIB_API key cfName
    Fixed bugs:
      * netCDF4 classic: existing files are converted to netCDF4 - classic flag is lost
+     * netCDF: added support for opendap files by https:
+     * gribapiDefDateTimeRel: set vdate to rdate for time invariant fields [Bug #4641]
+     * Loss of coordinates attribute when merging files [Bug #4880]
 
 Version 1.6.3 (14 February 2014):
 
diff --git a/libcdi/aclocal.m4 b/libcdi/aclocal.m4
index 39e5639..a8d0bc4 100644
--- a/libcdi/aclocal.m4
+++ b/libcdi/aclocal.m4
@@ -1184,6 +1184,7 @@ AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
 m4_include([m4/acx_assert_lang_is_fortran_variant.m4])
+m4_include([m4/acx_check_strptr_convert.m4])
 m4_include([m4/acx_lang_other_suffix_conftest.m4])
 m4_include([m4/acx_options.m4])
 m4_include([m4/acx_sl_fc_mod_path_flag.m4])
diff --git a/libcdi/app/Makefile.in b/libcdi/app/Makefile.in
index 7073720..34c4624 100644
--- a/libcdi/app/Makefile.in
+++ b/libcdi/app/Makefile.in
@@ -89,6 +89,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
diff --git a/libcdi/app/cdi.c b/libcdi/app/cdi.c
index d6561e6..c14cf03 100644
--- a/libcdi/app/cdi.c
+++ b/libcdi/app/cdi.c
@@ -272,16 +272,18 @@ void printInfo(int gridtype, int vdate, int vtime, char *varname, double level,
 
 const char * tunit2str(int tunits)
 {
-  if      ( tunits == TUNIT_YEAR )    return ("years");
-  else if ( tunits == TUNIT_MONTH )   return ("months");
-  else if ( tunits == TUNIT_DAY )     return ("days");
-  else if ( tunits == TUNIT_12HOURS ) return ("12hours");
-  else if ( tunits == TUNIT_6HOURS )  return ("6hours");
-  else if ( tunits == TUNIT_3HOURS )  return ("3hours");
-  else if ( tunits == TUNIT_HOUR )    return ("hours");
-  else if ( tunits == TUNIT_MINUTE )  return ("minutes");
-  else if ( tunits == TUNIT_SECOND )  return ("seconds");
-  else                                return ("unknown");
+  if      ( tunits == TUNIT_YEAR )       return ("years");
+  else if ( tunits == TUNIT_MONTH )      return ("months");
+  else if ( tunits == TUNIT_DAY )        return ("days");
+  else if ( tunits == TUNIT_12HOURS )    return ("12hours");
+  else if ( tunits == TUNIT_6HOURS )     return ("6hours");
+  else if ( tunits == TUNIT_3HOURS )     return ("3hours");
+  else if ( tunits == TUNIT_HOUR )       return ("hours");
+  else if ( tunits == TUNIT_30MINUTES )  return ("30minutes");
+  else if ( tunits == TUNIT_QUARTER )    return ("15minutes");
+  else if ( tunits == TUNIT_MINUTE )     return ("minutes");
+  else if ( tunits == TUNIT_SECOND )     return ("seconds");
+  else                                   return ("unknown");
 }
 
 
@@ -373,6 +375,8 @@ void printShortinfo(int streamID, int vlistID, int vardis)
 	  else if ( tsteptype == TSTEP_MIN      ) fprintf(stdout, "%-8s ", "min");
 	  else if ( tsteptype == TSTEP_MAX      ) fprintf(stdout, "%-8s ", "max");
 	  else if ( tsteptype == TSTEP_ACCUM    ) fprintf(stdout, "%-8s ", "accum");
+	  else if ( tsteptype == TSTEP_RANGE    ) fprintf(stdout, "%-8s ", "range");
+	  else if ( tsteptype == TSTEP_DIFF     ) fprintf(stdout, "%-8s ", "diff");
 	  else                                    fprintf(stdout, "%-8s ", "unknown");
 
 	  /* layer info */
@@ -710,7 +714,7 @@ int main(int argc, char *argv[])
   int Move = 0;
   int Record = 0;
   int Debug = 0;
-  int Quiet  = 0;
+  /* int Quiet  = 0; */
   int Vardis = 0;
   int Version = 0;
   int Longinfo = 0;
@@ -751,7 +755,7 @@ int main(int argc, char *argv[])
 	  Move = 1;
 	  break;
 	case 'q':
-	  Quiet = 1;
+	  /* Quiet = 1; */
 	  break;
 	case 'R':
 	  cdiDefGlobal("REGULARGRID", 1);
@@ -895,7 +899,7 @@ int main(int argc, char *argv[])
 	}
 
       if ( vlistNumber(vlistID1) != CDI_REAL ) datasize *= 2;
-      data = (double *) malloc(datasize*sizeof(double));
+      data = (double *) malloc((size_t)datasize * sizeof (double));
 
       /*
 	nts = cdiInqTimeSize(streamID1);
diff --git a/libcdi/app/createtable.c b/libcdi/app/createtable.c
index e3a829c..d97dd6a 100644
--- a/libcdi/app/createtable.c
+++ b/libcdi/app/createtable.c
@@ -4,8 +4,10 @@
 #include <string.h>
 
 #include "cdi.h"
+#include "error.h"
 
-char *Progname;
+static char *Progname;
+extern int CDI_Debug;
 
 void version(void)
 {
@@ -24,7 +26,7 @@ void usage(void)
 
 int main(int argc, char *argv[])
 {
-  int c, len;
+  int c;
   char  *cstring;
   char *ifile = NULL, *ofile = NULL;
   int debug = 0;
@@ -37,7 +39,7 @@ int main(int argc, char *argv[])
     {
       c = *++argv[0];
       cstring = argv[0];
-      len = strlen(cstring);
+      size_t len = strlen(cstring);
       switch (c)
 	{
         case 'd':
@@ -48,22 +50,22 @@ int main(int argc, char *argv[])
 	  break;
         case 'h':
 	  if ( !strncmp(cstring, "help", len) )
-	    { 
+	    {
 	      usage( );
-	      return( 0 );
+	      return EXIT_SUCCESS;
             }
 	  break;
         case 'v':
 	  if ( !strncmp(cstring, "version", len) )
 	    {
 	      version();
-	      return (0);
+	      return EXIT_SUCCESS;
             }
 	  break;
         default:
 	  usage();
 	  fprintf(stderr, "illegal option %s\n", cstring);
-	  return (-1);
+	  return EXIT_FAILURE;
 	  break;
         }
     }
@@ -83,7 +85,7 @@ int main(int argc, char *argv[])
     {
       usage();
       fprintf(stderr, "missing filenames\n");
-      return (-1);
+      return EXIT_FAILURE;
     }
 
   if ( debug )
@@ -98,10 +100,13 @@ int main(int argc, char *argv[])
   if ( debug ) cdiDebug(debug);
   */
   tableID = tableRead(ifile);
+  if ( CDI_Debug )
+    Message("write parameter table %d to %s", tableID, ofile);
+  FILE *ptfp = (ofile[0] == '-' && ofile[1] == '\0')?stdout:fopen(ofile, "w");
   if ( tableID != CDI_UNDEFID )
-    tableWriteC(ofile, tableID);
+    tableFWriteC(ptfp, tableID);
 
-  return (0);
+  return EXIT_SUCCESS;
 }
 /*
  * Local Variables:
diff --git a/libcdi/app/printinfo.h b/libcdi/app/printinfo.h
index 991531c..46a03d0 100644
--- a/libcdi/app/printinfo.h
+++ b/libcdi/app/printinfo.h
@@ -303,8 +303,8 @@ void printGridInfo(int vlistID)
 	      int i;
 	      double *xvals, *yvals;
 	      double xfirst, xlast, yfirst, ylast;
-	      xvals = (double*) malloc(gridsize*sizeof(double));
-	      yvals = (double*) malloc(gridsize*sizeof(double));
+	      xvals = (double *)malloc((size_t)gridsize * sizeof (double));
+	      yvals = (double *)malloc((size_t)gridsize * sizeof (double));
 
 	      gridInqXvals(gridID, xvals);
 	      gridInqYvals(gridID, yvals);
diff --git a/libcdi/config/default b/libcdi/config/default
index 46efe45..1a63f9c 100755
--- a/libcdi/config/default
+++ b/libcdi/config/default
@@ -19,19 +19,19 @@ case "${HOSTNAME}" in
                     --enable-swig \
                     --enable-python \
                     --with-jasper=/opt/local \
-                    --with-grib_api=$HOME/local/gribapi-1.10.4 \
+                    --with-grib_api=$HOME/local/gribapi-1.12.3 \
                     --with-netcdf=$HOME/local \
                     --with-szlib=$HOME/local \
 	            CC=icc CFLAGS="-g -D_REENTRANT -Wall -O3 -march=native -Df2cFortran -fp-model source"
 	;;
-    bailung*)
+    bailung*|d133*|d134*)
 	./configure --prefix=$HOME/local \
                     --enable-maintainer-mode \
                     --enable-iso-c-interface \
                     --enable-swig \
                     --enable-python \
                     --with-jasper=/opt/local \
-                    --with-grib_api=$HOME/local/gribapi-1.10.4 \
+                    --with-grib_api=$HOME/local/gribapi-1.12.3 \
                     --with-netcdf=$HOME/local \
                     --with-szlib=$HOME/local \
 	            CC=gcc CFLAGS="-g -pipe -D_REENTRANT -Wall -W -Wfloat-equal -pedantic -O3 -march=native -Df2cFortran"
diff --git a/libcdi/configure b/libcdi/configure
index ffea8d6..65181f2 100755
--- a/libcdi/configure
+++ b/libcdi/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.6.4.
+# Generated by GNU Autoconf 2.68 for cdi 1.6.5.1.
 #
 # Report bugs to <http://code.zmaw.de/projects/cdi>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdi'
 PACKAGE_TARNAME='cdi'
-PACKAGE_VERSION='1.6.4'
-PACKAGE_STRING='cdi 1.6.4'
+PACKAGE_VERSION='1.6.5.1'
+PACKAGE_STRING='cdi 1.6.5.1'
 PACKAGE_BUGREPORT='http://code.zmaw.de/projects/cdi'
 PACKAGE_URL=''
 
@@ -620,6 +620,7 @@ BUILD_F77
 BUILD_FC
 BUILD_CXX
 BUILD_CC
+BUILD_LIBS
 BUILD_LDFLAGS
 BUILD_FCFLAGS
 BUILD_CFLAGS
@@ -642,6 +643,7 @@ FCMODCASE
 FCMODEXT
 CDI_F90_INTERFACE_FCFLAGS
 FC_MOD_FLAG
+ENABLE_F2003_ISOC
 CREATE_ISOC_FALSE
 CREATE_ISOC_TRUE
 USE_MPI
@@ -896,6 +898,7 @@ FCMODEXT
 BUILD_CFLAGS
 BUILD_FCFLAGS
 BUILD_LDFLAGS
+BUILD_LIBS
 BUILD_CC
 BUILD_CXX
 BUILD_FC
@@ -1442,7 +1445,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.6.4 to adapt to many kinds of systems.
+\`configure' configures cdi 1.6.5.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1512,7 +1515,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdi 1.6.4:";;
+     short | recursive ) echo "Configuration of cdi 1.6.5.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1546,7 +1549,6 @@ Optional Features:
   --enable-iso-c-interface
                           Create Fortran Interface via iso_c_bindings facility
                           of F2003 [default=no].
-
   --enable-swig           use swig to create extra bindings [default=no]
                           (EXPERIMENTAL)
   --enable-ruby           ruby language bindings [default=no] (EXPERIMENTAL)
@@ -1624,6 +1626,7 @@ Some influential environment variables:
               append to FCFLAGS during build but not in configure phase
   BUILD_LDFLAGS
               append to LDFLAGS during build but not in configure phase
+  BUILD_LIBS  append to LIBS during build but not in configure phase
   BUILD_CC    replace CC with expansion of $BUILD_CC during build but not in
               configure phase
   BUILD_CXX   replace CXX with expansion of $BUILD_CXX during build but not in
@@ -1699,7 +1702,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdi configure 1.6.4
+cdi configure 1.6.5.1
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2460,7 +2463,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.6.4, which was
+It was created by cdi $as_me 1.6.5.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3405,7 +3408,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdi'
- VERSION='1.6.4'
+ VERSION='1.6.5.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -15594,6 +15597,8 @@ fi
            "$FC $FCFLAGS -F" "$FC $FCFLAGS -E" "$FC $FCFLAGS -E" \
            "$FC $FCFLAGS -E -cpp" "$FC $FCFLAGS -x f95-cpp-input -E -P" \
            "${F77-f77} -F" "${F77-f77} -E" 'fpp' \
+           "$CPP -std=c89" "$CPP -x c -std=c89" 'cpp -std=c89' '/lib/cpp - std=c89' \
+           '/usr/ccs/lib/cpp -std=c89' 'g77 -E -std=c89' '${CC-cc} -E -std=c89' \
            "$CPP" "$CPP -x c" 'cpp' '/lib/cpp' \
            '/usr/ccs/lib/cpp' 'g77 -E' '${CC-cc} -E'
          do
@@ -24334,6 +24339,18 @@ fi
 
 done
 
+for ac_header in execinfo.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_execinfo_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_EXECINFO_H 1
+_ACEOF
+
+fi
+
+done
+
 #  ----------------------------------------------------------------------
 # Checks for the availability of functions
 for ac_func in mallinfo
@@ -24514,7 +24531,6 @@ $as_echo "suppressed" >&6; } ;; #(
   yes) :
 
 
-
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -24602,8 +24618,8 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
 # --thread-safe: KAI C++
 # pthread-config: use pthread-config program (for GNU Pth library)
 
-case "${host_cpu}-${host_os}" in
-        *solaris*)
+case ${host_os} in
+        solaris*)
 
         # On Solaris (at least, for some versions), libc contains stubbed
         # (non-functional) versions of the pthreads routines, so link-based
@@ -24616,11 +24632,42 @@ case "${host_cpu}-${host_os}" in
         ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
         ;;
 
-	*-darwin*)
-	ax_pthread_flags="-pthread $ax_pthread_flags"
-	;;
+        darwin*)
+        ax_pthread_flags="-pthread $ax_pthread_flags"
+        ;;
 esac
 
+# Clang doesn't consider unrecognized options an error unless we specify
+# -Werror. We throw in some extra Clang-specific options to ensure that
+# this doesn't happen for GCC, which also accepts -Werror.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler needs -Werror to reject unknown flags" >&5
+$as_echo_n "checking if compiler needs -Werror to reject unknown flags... " >&6; }
+save_CFLAGS="$CFLAGS"
+ax_pthread_extra_flags="-Werror"
+CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void);
+int
+main ()
+{
+foo()
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  ax_pthread_extra_flags=
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS="$save_CFLAGS"
+
 if test x"$ax_pthread_ok" = xno; then
 for flag in $ax_pthread_flags; do
 
@@ -24636,8 +24683,8 @@ $as_echo_n "checking whether pthreads work with $flag... " >&6; }
                 PTHREAD_CFLAGS="$flag"
                 ;;
 
-		pthread-config)
-		# Extract the first word of "pthread-config", so it can be a program name with args.
+                pthread-config)
+                # Extract the first word of "pthread-config", so it can be a program name with args.
 set dummy pthread-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
@@ -24675,10 +24722,10 @@ $as_echo "no" >&6; }
 fi
 
 
-		if test x"$ax_pthread_config" = xno; then continue; fi
-		PTHREAD_CFLAGS="`pthread-config --cflags`"
-		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-		;;
+                if test x"$ax_pthread_config" = xno; then continue; fi
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
 
                 *)
                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5
@@ -24690,7 +24737,7 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; }
         save_LIBS="$LIBS"
         save_CFLAGS="$CFLAGS"
         LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
 
         # Check for various functions.  We must include pthread.h,
         # since some functions may be macros.  (On the Sequent, we
@@ -24704,17 +24751,17 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; }
         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <pthread.h>
-		     static void routine(void* a) {a=0;}
-		     static void* start_routine(void* a) {return a;}
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }
 int
 main ()
 {
 pthread_t th; pthread_attr_t attr;
-                     pthread_create(&th,0,start_routine,0);
-                     pthread_join(th, 0);
-                     pthread_attr_init(&attr);
-                     pthread_cleanup_push(routine, 0);
-                     pthread_cleanup_pop(0);
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */
   ;
   return 0;
 }
@@ -24747,17 +24794,17 @@ if test "x$ax_pthread_ok" = xyes; then
         CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
 
         # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
 $as_echo_n "checking for joinable pthread attribute... " >&6; }
-	attr_name=unknown
-	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+        attr_name=unknown
+        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <pthread.h>
 int
 main ()
 {
-int attr=$attr; return attr;
+int attr = $attr; return attr /* ; */
   ;
   return 0;
 }
@@ -24767,7 +24814,7 @@ if ac_fn_c_try_link "$LINENO"; then :
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-	done
+        done
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5
 $as_echo "$attr_name" >&6; }
         if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
@@ -24781,22 +24828,75 @@ _ACEOF
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5
 $as_echo_n "checking if more special flags are required for pthreads... " >&6; }
         flag=no
-        case "${host_cpu}-${host_os}" in
-            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        case ${host_os} in
+            aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+            osf* | hpux*) flag="-D_REENTRANT";;
+            solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                # TODO: What about Clang on Solaris?
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
-$as_echo "${flag}" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag" >&5
+$as_echo "$flag" >&6; }
         if test "x$flag" != xno; then
             PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
         fi
 
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
+$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; }
+if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+int i = PTHREAD_PRIO_INHERIT;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ax_cv_PTHREAD_PRIO_INHERIT=yes
+else
+  ax_cv_PTHREAD_PRIO_INHERIT=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
+$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
+        if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then :
+
+$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
+
+fi
+
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        # More AIX lossage: must compile with xlc_r or cc_r
-	if test x"$GCC" != xyes -a \( x"$CC" = xxlc -o x"$CC" = cc \) ; then
-          for ac_prog in xlc_r cc_r
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != xyes; then
+            case $host_os in
+                aix*)
+                case "x/$CC" in #(
+  x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
+    #handle absolute path differently from PATH based program lookup
+                   case "x$CC" in #(
+  x/*) :
+    if { test -f ${CC}_r && $as_test_x ${CC}_r; }; then :
+  PTHREAD_CC="${CC}_r"
+fi ;; #(
+  *) :
+    for ac_prog in ${CC}_r
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -24837,15 +24937,19 @@ fi
 
   test -n "$PTHREAD_CC" && break
 done
-test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
-
-        else
-          PTHREAD_CC=$CC
-	fi
-else
-        PTHREAD_CC="$CC"
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+ ;;
+esac ;; #(
+  *) :
+     ;;
+esac
+                ;;
+            esac
+        fi
 fi
 
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
 
 
 
@@ -27348,6 +27452,79 @@ else
   enable_isoc=no
 fi
 
+if test x"$enable_isoc" = xyes; then :
+  ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran compiler can handle complex CHARACTER interoperability" >&5
+$as_echo_n "checking if Fortran compiler can handle complex CHARACTER interoperability... " >&6; }
+   cat > conftest.$ac_ext <<_ACEOF
+module conftest_mod
+  use iso_c_binding
+  implicit none
+  private
+  public :: errstr
+contains
+  function errstr(errno)
+    integer, intent(in) :: errno
+    interface
+      function strerror(errno) bind(c, name='strerror')
+        import :: c_int, c_ptr
+        integer(c_int), value, intent(in) :: errno
+        type(c_ptr) :: strerror
+      end function strerror
+      function strlen(s) bind(c, name='strlen')
+        import :: c_ptr, c_size_t
+        type(c_ptr), value, intent(in) :: s
+        integer(c_size_t) :: strlen
+      end function strlen
+    end interface
+    type(c_ptr) :: cptr
+    character(len=:, kind=c_char), pointer :: errstr
+
+    cptr = strerror(int(errno, c_int))
+    errstr => c2f_string(cptr, int(strlen(cptr)))
+  end function errstr
+
+  function c2f_string(s, slen)
+    type(c_ptr), intent(in) :: s
+    integer, intent(in) :: slen
+    CHARACTER(len=slen, kind=c_char), POINTER :: c2f_string
+    c2f_string => NULL()
+    call c_f_pointer(s, c2f_string)
+  end function c2f_string
+end module conftest_mod
+
+program conftest
+  use iso_c_binding
+  use conftest_mod, only: errstr
+  implicit none
+  character(kind=c_char, len=:), pointer :: msg
+  msg => errstr(42)
+  write (0, '(a)') msg
+end program conftest
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+  enable_isoc=no
+fi
  if test $enable_isoc = 'yes'; then
   CREATE_ISOC_TRUE=
   CREATE_ISOC_FALSE='#'
@@ -27356,6 +27533,9 @@ else
   CREATE_ISOC_FALSE=
 fi
 
+ENABLE_F2003_ISOC=$enable_isoc
+
+
 # in case the Fortran interface uses the more modern F90-style interface,
 # the FCFLAGS for users of the library have to include a switch to use the
 # .mod file
@@ -27814,7 +27994,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-ac_config_files="$ac_config_files tests/test_cksum_grib tests/test_cksum_nc tests/test_cksum_nc2 tests/test_cksum_nc4 tests/test_cksum_extra tests/test_cksum_service tests/test_cksum_ieg tests/test_chunk_cksum tests/pio_write_run tests/pio_write_deco2d_run tests/pio_cksum_mpinonb tests/pio_cksum_fpguard tests/pio_cksum_asynch tests/pio_cksum_writer tests/pio_cksum_cdf tests/test_resource_copy_mpi_run util/serialrun"
+ac_config_files="$ac_config_files tests/test_cksum_grib tests/test_cksum_nc tests/test_cksum_nc2 tests/test_cksum_nc4 tests/test_cksum_extra tests/test_cksum_service tests/test_cksum_ieg tests/test_chunk_cksum tests/test_f2003 tests/pio_write_run tests/pio_write_deco2d_run tests/pio_cksum_mpinonb tests/pio_cksum_fpguard tests/pio_cksum_asynch tests/pio_cksum_writer tests/pio_cksum_cdf tests/test_resource_copy_mpi_run tables/gen_tableheaderfile util/serialrun"
 
 
 ac_config_files="$ac_config_files Makefile src/Makefile interfaces/Makefile app/Makefile tests/Makefile examples/Makefile cdi.settings examples/pio/Makefile src/pkgconfig/cdi.pc src/pkgconfig/cdipio.pc"
@@ -28004,6 +28184,7 @@ fi
 CFLAGS="$CFLAGS${BUILD_CFLAGS+ $BUILD_CFLAGS}"
 FCFLAGS="$FCFLAGS${BUILD_FCFLAGS+ $BUILD_FCFLAGS}"
 LDFLAGS="$LDFLAGS${BUILD_LDFLAGS+ $BUILD_LDFLAGS}"
+LIBS="$LIBS${BUILD_LIBS+ $BUILD_LIBS}"
 CC="${BUILD_CC-$CC}"
 CXX="${BUILD_CXX-$CXX}"
 FC="${BUILD_FC-$FC}"
@@ -28417,7 +28598,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.6.4, which was
+This file was extended by cdi $as_me 1.6.5.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -28483,7 +28664,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.6.4
+cdi config.status 1.6.5.1
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -29170,6 +29351,7 @@ do
     "tests/test_cksum_service") CONFIG_FILES="$CONFIG_FILES tests/test_cksum_service" ;;
     "tests/test_cksum_ieg") CONFIG_FILES="$CONFIG_FILES tests/test_cksum_ieg" ;;
     "tests/test_chunk_cksum") CONFIG_FILES="$CONFIG_FILES tests/test_chunk_cksum" ;;
+    "tests/test_f2003") CONFIG_FILES="$CONFIG_FILES tests/test_f2003" ;;
     "tests/pio_write_run") CONFIG_FILES="$CONFIG_FILES tests/pio_write_run" ;;
     "tests/pio_write_deco2d_run") CONFIG_FILES="$CONFIG_FILES tests/pio_write_deco2d_run" ;;
     "tests/pio_cksum_mpinonb") CONFIG_FILES="$CONFIG_FILES tests/pio_cksum_mpinonb" ;;
@@ -29178,6 +29360,7 @@ do
     "tests/pio_cksum_writer") CONFIG_FILES="$CONFIG_FILES tests/pio_cksum_writer" ;;
     "tests/pio_cksum_cdf") CONFIG_FILES="$CONFIG_FILES tests/pio_cksum_cdf" ;;
     "tests/test_resource_copy_mpi_run") CONFIG_FILES="$CONFIG_FILES tests/test_resource_copy_mpi_run" ;;
+    "tables/gen_tableheaderfile") CONFIG_FILES="$CONFIG_FILES tables/gen_tableheaderfile" ;;
     "util/serialrun") CONFIG_FILES="$CONFIG_FILES util/serialrun" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
@@ -30988,6 +31171,7 @@ _LT_EOF
     "tests/test_cksum_service":F) chmod a+x "$ac_file" ;;
     "tests/test_cksum_ieg":F) chmod a+x "$ac_file" ;;
     "tests/test_chunk_cksum":F) chmod a+x "$ac_file" ;;
+    "tests/test_f2003":F) chmod a+x "$ac_file" ;;
     "tests/pio_write_run":F) chmod a+x "$ac_file" ;;
     "tests/pio_write_deco2d_run":F) chmod a+x "$ac_file" ;;
     "tests/pio_cksum_mpinonb":F) chmod a+x "$ac_file" ;;
@@ -30996,6 +31180,7 @@ _LT_EOF
     "tests/pio_cksum_writer":F) chmod a+x "$ac_file" ;;
     "tests/pio_cksum_cdf":F) chmod a+x "$ac_file" ;;
     "tests/test_resource_copy_mpi_run":F) chmod a+x "$ac_file" ;;
+    "tables/gen_tableheaderfile":F) chmod a+x "$ac_file" ;;
     "util/serialrun":F) chmod a+x "$ac_file" ;;
 
   esac
diff --git a/libcdi/configure.ac b/libcdi/configure.ac
index 86b5c9c..8d8bfc5 100644
--- a/libcdi/configure.ac
+++ b/libcdi/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdi], [1.6.4], [http://code.zmaw.de/projects/cdi])
+AC_INIT([cdi], [1.6.5.1], [http://code.zmaw.de/projects/cdi])
 
 echo "configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}"
 
@@ -65,6 +65,7 @@ AC_CHECK_MEMBERS([struct stat.st_blksize])
 #  ----------------------------------------------------------------------
 # Checks for header files
 AC_CHECK_HEADERS(malloc.h)
+AC_CHECK_HEADERS(execinfo.h)
 #  ----------------------------------------------------------------------
 # Checks for the availability of functions
 AC_CHECK_FUNCS([mallinfo])
@@ -208,11 +209,15 @@ AM_CONDITIONAL([USE_PPM_CORE],[test $enable_ppm = yes])
 AC_SUBST([USE_MPI])
 #  ----------------------------------------------------------------------
 #  Create the Fortran Interface via iso_c_binding module (Fortran 2003 Standard)
-AC_ARG_ENABLE(iso-c-interface,
-              AS_HELP_STRING([--enable-iso-c-interface],
-                             [Create Fortran Interface via iso_c_bindings facility of F2003 [default=no]]).
-              ,enable_isoc=${enableval},enable_isoc=no)
+AC_ARG_ENABLE([iso-c-interface],
+              [AS_HELP_STRING([--enable-iso-c-interface],
+                 [Create Fortran Interface via iso_c_bindings facility of F2003 [default=no].])],
+              [enable_isoc=${enableval}],[enable_isoc=no])
+AS_IF([test x"$enable_isoc" = xyes],
+  [ACX_FC_CHECK_STRPTR_CONVERT],[enable_isoc=no])
 AM_CONDITIONAL([CREATE_ISOC],[test $enable_isoc = 'yes'])
+AC_SUBST([ENABLE_F2003_ISOC],[$enable_isoc])
+AM_SUBST_NOTMAKE([ENABLE_F2003_ISOC])
 # in case the Fortran interface uses the more modern F90-style interface,
 # the FCFLAGS for users of the library have to include a switch to use the
 # .mod file
@@ -303,6 +308,10 @@ AC_ARG_VAR([BUILD_LDFLAGS],
   [append to LDFLAGS during build but not in configure phase])dnl
 AC_CONFIG_COMMANDS_PRE([LDFLAGS="$LDFLAGS${BUILD_LDFLAGS+ $BUILD_LDFLAGS}"])dnl
 AM_SUBST_NOTMAKE([BUILD_LDFLAGS])dnl
+AC_ARG_VAR([BUILD_LIBS],
+  [append to LIBS during build but not in configure phase])dnl
+AC_CONFIG_COMMANDS_PRE([LIBS="$LIBS${BUILD_LIBS+ $BUILD_LIBS}"])dnl
+AM_SUBST_NOTMAKE([BUILD_LIBS])dnl
 AC_ARG_VAR([BUILD_CC],
   [replace CC with expansion of $BUILD_CC during build but not in configure phase])dnl
 AC_CONFIG_COMMANDS_PRE([CC="${BUILD_CC-$CC}"])dnl
@@ -333,6 +342,7 @@ AC_CONFIG_FILES([tests/test_cksum_grib \
                  tests/test_cksum_service \
                  tests/test_cksum_ieg \
                  tests/test_chunk_cksum \
+                 tests/test_f2003 \
                  tests/pio_write_run \
                  tests/pio_write_deco2d_run \
                  tests/pio_cksum_mpinonb \
@@ -341,6 +351,7 @@ AC_CONFIG_FILES([tests/test_cksum_grib \
                  tests/pio_cksum_writer \
                  tests/pio_cksum_cdf \
                  tests/test_resource_copy_mpi_run \
+                 tables/gen_tableheaderfile \
                  util/serialrun],[chmod a+x "$ac_file"])
 
 AC_OUTPUT([Makefile src/Makefile interfaces/Makefile app/Makefile \
diff --git a/libcdi/doc/cdi_cman.pdf b/libcdi/doc/cdi_cman.pdf
index 6751a48..75b630c 100644
Binary files a/libcdi/doc/cdi_cman.pdf and b/libcdi/doc/cdi_cman.pdf differ
diff --git a/libcdi/doc/cdi_fman.pdf b/libcdi/doc/cdi_fman.pdf
index dba4acc..1e69024 100644
Binary files a/libcdi/doc/cdi_fman.pdf and b/libcdi/doc/cdi_fman.pdf differ
diff --git a/libcdi/examples/Makefile.am b/libcdi/examples/Makefile.am
index e0a0d84..bb96dc7 100644
--- a/libcdi/examples/Makefile.am
+++ b/libcdi/examples/Makefile.am
@@ -27,9 +27,12 @@ cdi_copy_LDADD           = $(top_builddir)/src/libcdi.la
 #
 cdi_read_f2003_SOURCES   = cdi_read_f2003.f90
 cdi_read_f2003_LDADD     = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.o
+cdi_read_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
 #
 cdi_write_f2003_SOURCES  = cdi_write_f2003.f90
-cdi_write_f2003_LDADD    = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.o
+cdi_write_f2003_LDADD    = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.$(OBJEXT)
+cdi_write_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
+
 #
 if ENABLE_ALL_STATIC
 cdi_write_LDFLAGS        = -all-static
diff --git a/libcdi/examples/Makefile.in b/libcdi/examples/Makefile.in
index cf2109b..e66719a 100644
--- a/libcdi/examples/Makefile.in
+++ b/libcdi/examples/Makefile.in
@@ -85,10 +85,11 @@ noinst_PROGRAMS = cdi_write$(EXEEXT) cdi_write_ens$(EXEEXT) \
 subdir = examples
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/config/mkinstalldirs \
-	$(top_srcdir)/config/depcomp
+	$(top_srcdir)/config/depcomp README
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
@@ -144,7 +145,7 @@ cdi_write_ens_DEPENDENCIES = $(top_builddir)/src/libcdi.la
 am_cdi_write_f2003_OBJECTS = cdi_write_f2003.$(OBJEXT)
 cdi_write_f2003_OBJECTS = $(am_cdi_write_f2003_OBJECTS)
 cdi_write_f2003_DEPENDENCIES = $(top_builddir)/src/libcdi.la \
-	$(top_builddir)/src/mo_cdi.o
+	$(top_builddir)/src/mo_cdi.$(OBJEXT)
 cdi_write_f2003_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FCLD) \
 	$(AM_FCFLAGS) $(FCFLAGS) $(cdi_write_f2003_LDFLAGS) $(LDFLAGS) \
@@ -446,7 +447,8 @@ cdi_read_f2003_SOURCES = cdi_read_f2003.f90
 cdi_read_f2003_LDADD = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.o
 #
 cdi_write_f2003_SOURCES = cdi_write_f2003.f90
-cdi_write_f2003_LDADD = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.o
+cdi_write_f2003_LDADD = $(top_builddir)/src/libcdi.la $(top_builddir)/src/mo_cdi.$(OBJEXT)
+
 #
 @ENABLE_ALL_STATIC_TRUE at cdi_write_LDFLAGS = -all-static
 @ENABLE_ALL_STATIC_TRUE at cdi_read_LDFLAGS = -all-static
@@ -776,6 +778,8 @@ uninstall-am:
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
 	tags tags-am uninstall uninstall-am
 
+cdi_read_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
+cdi_write_f2003.$(OBJEXT): $(top_builddir)/src/mo_cdi.$(FCMODEXT)
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libcdi/examples/README b/libcdi/examples/README
new file mode 100644
index 0000000..701881e
--- /dev/null
+++ b/libcdi/examples/README
@@ -0,0 +1,9 @@
+The following C Source files
+
+cdi_read.c
+cdi_write.c
+cdi_copy.c
+
+are directly used in the documentation.
+
+!!! Please do not change these files !!!
diff --git a/libcdi/examples/cdi_copy.c b/libcdi/examples/cdi_copy.c
index 0e4b3b5..a5729cb 100644
--- a/libcdi/examples/cdi_copy.c
+++ b/libcdi/examples/cdi_copy.c
@@ -9,7 +9,7 @@ int nts  =  3; // Number of time steps
 int main(void)
 {
   int taxisID, vlistID1, vlistID2, varID1, varID2, streamID1, streamID2, tsID;
-  int nmiss, vdate, vtime;
+  int nmiss;
   double var1[nlon*nlat];
   double var2[nlon*nlat*nlev];
 
@@ -50,10 +50,6 @@ int main(void)
       // Inquire the input time step
       streamInqTimestep(streamID1, tsID);
 
-      // Get the verification date and time
-      vdate = taxisInqVdate(taxisID);
-      vtime = taxisInqVtime(taxisID);
-
       // Define the output time step
       streamDefTimestep(streamID2, tsID);
 
diff --git a/libcdi/examples/cdi_read.c b/libcdi/examples/cdi_read.c
index f619f37..cc89486 100644
--- a/libcdi/examples/cdi_read.c
+++ b/libcdi/examples/cdi_read.c
@@ -41,6 +41,7 @@ int main(void)
       // Get the verification date and time 
       vdate = taxisInqVdate(taxisID);
       vtime = taxisInqVtime(taxisID);
+      printf("read timestep %d:  date=%d  time=%d\n", tsID+1, vdate, vtime);
 
       // Read var1 and var2 
       streamReadVar(streamID, varID1, var1, &nmiss);
diff --git a/libcdi/examples/cdi_read_f2003.f90 b/libcdi/examples/cdi_read_f2003.f90
index 045499a..9128712 100644
--- a/libcdi/examples/cdi_read_f2003.f90
+++ b/libcdi/examples/cdi_read_f2003.f90
@@ -9,14 +9,22 @@ PROGRAM CDIREADF2003
   INTEGER :: streamID, varID, gridID, zaxisID
   INTEGER :: tsID, vlistID, taxisID
   DOUBLE PRECISION, ALLOCATABLE :: field(:,:)
-  CHARACTER(kind=c_char,len=256) :: name, longname, units, msg
+  CHARACTER(kind=c_char), POINTER, DIMENSION(:) :: &
+       msg, cdi_version
+  CHARACTER(kind=c_char), DIMENSION(cdi_max_name + 1) :: &
+       name, longname, units
+  INTEGER :: name_c_len, longname_c_len, units_c_len
+
+  cdi_version => cdiLibraryVersion()
+
+  WRITE (0, '(a,132a)') 'cdi version: ', cdi_version
 
   ! Open the dataset
   streamID = streamOpenRead(C_CHAR_"example.nc"//C_NULL_CHAR)
   IF ( streamID < 0 ) THEN
     PRINT *,  'Could not Read the file.'
-    msg = cdiStringError(streamID)
-    WRITE(0,*) msg
+    msg => cdiStringError(streamID)
+    WRITE(0,'(132a)') msg
     STOP 1
   END IF
 
@@ -31,12 +39,16 @@ PROGRAM CDIREADF2003
     CALL vlistInqVarLongname(vlistID, varID, longname)
     CALL vlistInqVarUnits(vlistID, varID, units)
 
-    CALL ctrim(name)
-    CALL ctrim(longname)
-    CALL ctrim(units)
+    ! CALL ctrim(name)
+    ! CALL ctrim(longname)
+    ! CALL ctrim(units)
 
-    WRITE(*,*) 'Parameter: ', varID+1, code,' ',trim(name),' ', &
-                trim(longname),' ',trim(units), ' |'
+    longname_c_len = c_len(longname)
+    name_c_len = c_len(name)
+    units_c_len = c_len(units)
+    PRINT '(a,2(i0,a),132a)', 'Parameter: ', varID+1, ' ', code, ' ', &
+         name(1:name_c_len), ' ', longname(1:longname_c_len), ' ', &
+         units(1:units_c_len), ' |'
 
   END DO
 
@@ -53,7 +65,7 @@ PROGRAM CDIREADF2003
     vdate = taxisInqVdate(taxisID)
     vtime = taxisInqVtime(taxisID)
 
-    WRITE(*,*) 'Timestep: ', tsID+1, vdate, vtime
+    PRINT '(a,i3,i10,i10)', 'Timestep: ', tsID+1, vdate, vtime
 
     ! Read the variables at the current timestep
     DO varID = 0, nvars-1
@@ -64,8 +76,9 @@ PROGRAM CDIREADF2003
       ALLOCATE(field(gsize, nlevel))
       CALL streamReadVar(streamID, varID, field, nmiss)
       DO ilev = 1, nlevel
-        WRITE(*,*) '   var=', varID+1, ' level=', ilev, ':', &
-                  MINVAL(field(:,ilev)), MAXVAL(field(:,ilev))
+        PRINT '(a,i3,a,i3,a,f10.5,1x,f10.5)', '   var=', varID+1, &
+             ' level=', ilev, ':', &
+             MINVAL(field(:,ilev)), MAXVAL(field(:,ilev))
       END DO
       DEALLOCATE(field)
     END DO
diff --git a/libcdi/examples/cdi_write_ens.c b/libcdi/examples/cdi_write_ens.c
index 6406ff4..d05b809 100644
--- a/libcdi/examples/cdi_write_ens.c
+++ b/libcdi/examples/cdi_write_ens.c
@@ -10,29 +10,24 @@ int main(int argc, char *argv[])
   int filetype = FILETYPE_GRB2;
   int nlat = 18, nlon = 2*nlat;
   double *data = NULL;
-  double missval;
   int nlevel;
   int varID;
-  int datasize = 0;
   int streamID1, streamID2;
-  int gridID, zaxisID, code, vdate, vtime;
+  int gridID, zaxisID;
   int nrecs, nvars;
-  int gridtype, gridsize = 0;
   int tsID;
-  int timeID = 0;
-  int level, levelID;
-  int offset;
+  int levelID;
   int vlistID, taxisID;
   int nmiss;
 
   int instID;
   int i1,i2,i3;
 
-  datasize = nlon * nlat;
-  data = (double *) malloc(datasize*sizeof(double));
-  memset(data, 0, datasize*sizeof(double));
+  size_t datasize = (size_t)nlon * (size_t)nlat;
+  data = (double *) malloc(datasize * sizeof (double));
+  memset(data, 0, datasize * sizeof (double));
 
-  gridID = gridCreate(GRID_GAUSSIAN, datasize);
+  gridID = gridCreate(GRID_GAUSSIAN, (int)datasize);
   gridDefXsize(gridID, nlon);
   gridDefYsize(gridID, nlat);
 
@@ -87,11 +82,11 @@ int main(int argc, char *argv[])
 
   for ( varID = 0; varID < nvars; varID++ )
     {
-      gridID   = vlistInqVarGrid(vlistID, varID);
-      zaxisID  = vlistInqVarZaxis(vlistID, varID);
-      gridsize = gridInqSize(gridID);
-      nlevel   = zaxisInqSize(zaxisID);
-      if ( gridsize*nlevel > datasize ) datasize = gridsize*nlevel;
+      int gridID   = vlistInqVarGrid(vlistID, varID);
+      int zaxisID  = vlistInqVarZaxis(vlistID, varID);
+      size_t gridsize = (size_t)gridInqSize(gridID);
+      size_t nlevel = (size_t)zaxisInqSize(zaxisID);
+      if ( gridsize * nlevel > datasize ) datasize = gridsize * nlevel;
     }
 
   data = (double *) malloc(datasize*sizeof(double));
@@ -102,8 +97,8 @@ int main(int argc, char *argv[])
   tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
-      vdate = taxisInqVdate(taxisID);
-      vtime = taxisInqVtime(taxisID);
+      /* int vdate =  */taxisInqVdate(taxisID);
+      /* int vtime =  */taxisInqVtime(taxisID);
 
       streamDefTimestep(streamID2, tsID);
 
@@ -111,18 +106,18 @@ int main(int argc, char *argv[])
 	{
 	  streamReadVar(streamID1, varID, data, &nmiss);
 
-	  code     = vlistInqVarCode(vlistID, varID);
+	  /* int code     =  */vlistInqVarCode(vlistID, varID);
 	  gridID   = vlistInqVarGrid(vlistID, varID);
 	  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-	  gridtype = gridInqType(gridID);
-	  gridsize = gridInqSize(gridID);
+	  /* int gridtype =  */gridInqType(gridID);
+	  /* int gridsize =  */gridInqSize(gridID);
 	  nlevel   = zaxisInqSize(zaxisID);
-	  missval  = vlistInqVarMissval(vlistID, varID);
+	  /* double missval =  */vlistInqVarMissval(vlistID, varID);
 
 	  for ( levelID = 0; levelID < nlevel; levelID++ )
 	    {
-	      level  = (int) zaxisInqLevel(zaxisID, levelID);
-	      offset = gridsize*levelID;
+	      /* int level  = (int)  */zaxisInqLevel(zaxisID, levelID);
+	      /* int offset = gridsize*levelID; */
 	    }
 
 	  streamWriteVar(streamID2, varID, data, nmiss);
diff --git a/libcdi/examples/cdi_write_f2003.f90 b/libcdi/examples/cdi_write_f2003.f90
index a642150..890f157 100644
--- a/libcdi/examples/cdi_write_f2003.f90
+++ b/libcdi/examples/cdi_write_f2003.f90
@@ -16,8 +16,8 @@
       INTEGER i, nmiss, status
       DOUBLE PRECISION lons(nlon), lats(nlat), levs(nlev)
       DOUBLE PRECISION var1(nlon*nlat), var2(nlon*nlat*nlev)
-      CHARACTER(len=256) :: varname
-      CHARACTER(kind=c_char,len=256) :: msg
+      CHARACTER(len=256, kind=c_char) :: varname
+      CHARACTER(kind=c_char,len=1), POINTER :: msg(:)
 
       DATA lons /0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330/
       DATA lats /-75, -45, -15, 15, 45, 75/
@@ -47,8 +47,8 @@
       varID2 = vlistDefVar(vlistID, gridID, zaxisID2, TIME_VARIABLE)
 
 !     Define the variable names
-      varname = "varname1"
-      CALL vlistDefVarName(vlistID, varID1, TRIM(varname)//C_NULL_CHAR)
+      varname = "varname1" // c_null_char
+      CALL vlistDefVarName(vlistID, varID1, varname)
       CALL vlistDefVarName(vlistID, varID2, C_CHAR_"varname2"//C_NULL_CHAR)
 
 !     Create a Time axis
@@ -60,8 +60,8 @@
 !     Create a dataset in netCDF format
       streamID = streamOpenWrite(C_CHAR_"example.nc"//C_NULL_CHAR, FILETYPE_NC)
       IF ( streamID < 0 ) THEN
-         msg = cdiStringError(streamID)
-         WRITE(0,*) msg
+         msg => cdiStringError(streamID)
+         WRITE(0,'(132a)') msg
          STOP 1
       END IF
 
diff --git a/libcdi/examples/pio/Makefile.in b/libcdi/examples/pio/Makefile.in
index 3185123..7c5c04a 100644
--- a/libcdi/examples/pio/Makefile.in
+++ b/libcdi/examples/pio/Makefile.in
@@ -90,6 +90,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
diff --git a/libcdi/examples/pio/collectData.c b/libcdi/examples/pio/collectData.c
index bd0905d..677934f 100644
--- a/libcdi/examples/pio/collectData.c
+++ b/libcdi/examples/pio/collectData.c
@@ -69,7 +69,7 @@ static void modelRun(MPI_Comm commModel)
     {
       zaxisID[i] = zaxisCreate ( ZAXIS_PRESSURE, nlev[i] );
       zaxisDefLevels ( zaxisID[i], levs );
-      varSize[i] = nlon * nlat * nlev[i];
+      varSize[i] = nlon * nlat * (size_t)nlev[i];
     }
   vlistID = vlistCreate ();
 
@@ -130,7 +130,7 @@ static void modelRun(MPI_Comm commModel)
 #ifdef USE_MPI
               int chunk = varDeco[i].chunkSize;
 #else
-              int chunk = varSize[i];
+              int chunk = (int)varSize[i];
 #endif
 	      for (j = 0; j < chunk; ++j) var[j] = 2.2;
 #ifdef USE_MPI
diff --git a/libcdi/examples/pio/collectDataNStreams.c b/libcdi/examples/pio/collectDataNStreams.c
index c4b0cf9..2257f0c 100644
--- a/libcdi/examples/pio/collectDataNStreams.c
+++ b/libcdi/examples/pio/collectDataNStreams.c
@@ -105,7 +105,7 @@ static void modelRun(MPI_Comm commModel)
       {
         varID[i][j] = vlistDefVar(vlistID[i], gridID, zaxisID[i][j],
                                   TIME_VARIABLE );
-        varSize[i][j] = nlon * nlat * nlev[i][j];
+        varSize[i][j] = nlon * nlat * (size_t)nlev[i][j];
 #ifdef USE_MPI
         {
           int start = uniform_partition_start((int [2]){ 0, varSize[i][j] - 1 },
@@ -127,10 +127,10 @@ static void modelRun(MPI_Comm commModel)
         }
 #else
         if (maxChunkSize < varSize[i][j])
-          maxChunkSize = varSize[i][j];
+          maxChunkSize = (int)varSize[i][j];
 #endif
       }
-    var = (double*) malloc(maxChunkSize * sizeof (var[0]));
+    var = (double *)malloc((size_t)maxChunkSize * sizeof (var[0]));
   }
   taxisID = taxisCreate ( TAXIS_ABSOLUTE );
   for ( i = 0; i < nStreams; i++ )
@@ -182,7 +182,7 @@ static void modelRun(MPI_Comm commModel)
                   int start = varDeco[i][j].start;
                   int chunk = varDeco[i][j].chunkSize;
 #else
-                  int start = 0, chunk = varSize[i][j];
+                  int start = 0, chunk = (int)varSize[i][j];
 #endif
                   for(int k = 0; k < chunk; k++)
                     var[k] = 3.3 * (double)(k + start);
diff --git a/libcdi/interfaces/Makefile.am b/libcdi/interfaces/Makefile.am
index 9d491bf..473f945 100644
--- a/libcdi/interfaces/Makefile.am
+++ b/libcdi/interfaces/Makefile.am
@@ -3,9 +3,21 @@
 SWIGCDILIB = cdilib.i
 SWIGCDIOBJ = cdiobj.i
 BINDINGS   =
-EXTRA_DIST = $(SWIGCDIOBJ) $(SWIGCDILIB)
-EXTRA_DIST += ruby/cdilib_wrap.c ruby/cdiobj_wrap.cpp ruby/testLib.rb ruby/testObj.rb
-EXTRA_DIST += python/cdilib_wrap.c python/cdiobj_wrap.cpp python/testLib.py python/testObj.py python/setupObj.py python/setupLib.py python/setup.py python/table.py python/CdiLib.py python/CdiObj.py
+
+EXTRA_DIST = $(SWIGCDIOBJ) $(SWIGCDILIB) \
+	\
+	ruby/cdilib_wrap.c ruby/cdiobj_wrap.cpp ruby/testLib.rb \
+	ruby/testObj.rb \
+	\
+	python/cdilib_wrap.c python/cdiobj_wrap.cpp python/testLib.py \
+	python/testObj.py python/setupObj.py python/setupLib.py \
+	python/setup.py python/table.py python/CdiLib.py \
+	python/CdiObj.py \
+	\
+	CdiInfo.cpp \
+	\
+	f2003/bindGen.rb
+
 if CREATE_INTERFACES
 BINDINGS += help
 endif
diff --git a/libcdi/interfaces/Makefile.in b/libcdi/interfaces/Makefile.in
index a8f81b0..7d159d6 100644
--- a/libcdi/interfaces/Makefile.in
+++ b/libcdi/interfaces/Makefile.in
@@ -96,6 +96,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
@@ -403,12 +404,20 @@ top_srcdir = @top_srcdir@
 SWIGCDILIB = cdilib.i
 SWIGCDIOBJ = cdiobj.i
 BINDINGS = $(am__append_1) $(am__append_4) $(am__append_5)
-EXTRA_DIST = $(SWIGCDIOBJ) $(SWIGCDILIB) ruby/cdilib_wrap.c \
-	ruby/cdiobj_wrap.cpp ruby/testLib.rb ruby/testObj.rb \
+EXTRA_DIST = $(SWIGCDIOBJ) $(SWIGCDILIB) \
+	\
+	ruby/cdilib_wrap.c ruby/cdiobj_wrap.cpp ruby/testLib.rb \
+	ruby/testObj.rb \
+	\
 	python/cdilib_wrap.c python/cdiobj_wrap.cpp python/testLib.py \
 	python/testObj.py python/setupObj.py python/setupLib.py \
 	python/setup.py python/table.py python/CdiLib.py \
-	python/CdiObj.py
+	python/CdiObj.py \
+	\
+	CdiInfo.cpp \
+	\
+	f2003/bindGen.rb
+
 noinst_LTLIBRARIES = $(am__append_3)
 #
 locallibs = $(top_builddir)/src/.libs/libcdi.so @LTLIBOBJS@ @NETCDF_LIBS@ @HDF5_LIBS@ @SZLIB_LIBS@ @ZLIB_LIBS@
diff --git a/libcdi/interfaces/f2003/bindGen.rb b/libcdi/interfaces/f2003/bindGen.rb
new file mode 100755
index 0000000..9e99357
--- /dev/null
+++ b/libcdi/interfaces/f2003/bindGen.rb
@@ -0,0 +1,499 @@
+#!/usr/bin/env ruby
+require 'optparse'
+################################################################
+# CONFIGURATION:
+CFTypeInfo             = {
+  'int'                  => {:namedConst       => 'c_int'                , :ftype => 'integer'},
+  'short int'            => {:namedConst       => 'c_short'              , :ftype => 'integer'},
+  'long int'             => {:namedConst       => 'c_long'               , :ftype => 'integer'},
+  'long long int'        => {:namedConst       => 'c_long_long'          , :ftype => 'integer'},
+  'signed char'          => {:namedConst       => 'c_signed_char'        , :ftype => 'integer'},
+  'unsigned char'        => {:namedConst       => 'c_signed_char'        , :ftype => 'integer'},
+  'size_t'               => {:namedConst       => 'c_size_t'             , :ftype => 'integer'},
+  'int8_t'               => {:namedConst       => 'c_int8_t'             , :ftype => 'integer'},
+  'int16_t'              => {:namedConst       => 'c_int16_t'            , :ftype => 'integer'},
+  'int32_t'              => {:namedConst       => 'c_int32_t'            , :ftype => 'integer'},
+  'int64_t'              => {:namedConst       => 'c_int64_t'            , :ftype => 'integer'},
+  'int_fast8_t'          => {:namedConst       => 'c_int_fast8_t'        , :ftype => 'integer'},
+  'int_fast16_t'         => {:namedConst       => 'c_int_fast16_t'       , :ftype => 'integer'},
+  'int_fast32_t'         => {:namedConst       => 'c_int_fast32_t'       , :ftype => 'integer'},
+  'int_fast64_t'         => {:namedConst       => 'c_int_fast64_t'       , :ftype => 'integer'},
+  'int_least8_t'         => {:namedConst       => 'c_int_least8_t'       , :ftype => 'integer'},
+  'int_least16_t'        => {:namedConst       => 'c_int_least16_t'      , :ftype => 'integer'},
+  'int_least32_t'        => {:namedConst       => 'c_int_least32_t'      , :ftype => 'integer'},
+  'int_least64_t'        => {:namedConst       => 'c_int_least64_t'      , :ftype => 'integer'},
+  'intmax_t'             => {:namedConst       => 'c_intmax_t'           , :ftype => 'integer'},
+  'intptr_t'             => {:namedConst       => 'c_intptr_t'           , :ftype => 'integer'},
+
+  'float'                => {:namedConst       => 'c_float'              , :ftype => 'real'},
+  'double'               => {:namedConst       => 'c_double'             , :ftype => 'real'},
+  'long double'          => {:namedConst       => 'c_long_double'        , :ftype => 'real'},
+
+  'float _Complex'       => {:namedConst       => 'c_float_complex'      , :ftype => 'complex'},
+  'double _Complex'      => {:namedConst       => 'c_double_complex'     , :ftype => 'complex'},
+  'long double _Complex' => {:namedConst       => 'c_long_double_complex', :ftype => 'complex'},
+  '_Bool'                => {:namedConst       => 'c_bool'               , :ftype => 'logical'},
+  'char'                 => {:namedConst       => 'c_char'               , :ftype => 'character'}
+}
+# how the module should be invoked from fortran
+ModuleName    = 'mo_cdi'
+# which conversion is to use generating the fortran routine names, this could
+# be any ruby String method.
+FNameMethod   = :noop
+# FNameMethod = :downcase
+# FNameMethod = :noop
+# FNameMethod = :upcase
+class String;def noop;self;end;end
+# fortran subroutines are not allowed to have a parameters with the same name,
+# so in case of a match, these parameters have to get an new name
+FParamExtension = 'v'
+# Naming convention from above: 
+# all non scalar variables should have the postfix '_vec' in there name
+Vectors = /_vec$/i
+################################################################################
+FortranMaxLineLength = 132
+# read the c header file and grep out name, return type and paramterlist of
+# each function
+def getFuncInfo(filename)
+  typelist = %w[char int float double void]
+  cppflags = ENV['CPPFLAGS'].nil? ? '' : ENV['CPPFLAGS']
+  funclist = IO.popen("cpp #{cppflags} #{filename} | cpp -fpreprocessed").readlines.delete_if {|line| line.include?('#')}.collect {|line| line.chomp}
+  # delete everything, that do not look like a function prototype
+  typeRegexp = /^.*(#{typelist.join('|')}) \**\w+\s*\(.*\)/
+  funclist.delete_if {|line|
+    not typeRegexp.match(line.lstrip)
+  }
+  funclist.collect! {|line|
+    md = /(\w+)+ +(\**)(\w+)\s*\((.*)\)/.match(line)
+    returnType, returnPointer, funcName, paramList = md[1,4]
+    paramList = paramList.split(',').collect {|p| p.split(' ').each {|_p| _p.strip}}
+    [funcName, returnType, returnPointer, paramList]
+  }
+  funclist
+end
+
+# grep the #define C-Constants, which should be available within the fortran CDI API
+def getDefines(filename)
+  defines = File.open(filename,'r').readlines.grep(/^#define/).collect {|line|
+    md = / +(\w+) +(-*\d+)/.match(line)
+  }.select {|item| not item.nil?}.collect {|match| match[1..2]}
+end
+
+# create continuation for lines longer that 132 sign, which would create an
+# error with some fortran compilers
+def genContinuation(iline)
+  # leave the input untouched
+  line = iline
+  # try to create readable line breaks, i.e. do not split name, labels or keywords
+  regexp = /,[^,]*$/
+
+  matchIndex = line[0,FortranMaxLineLength] =~ regexp
+
+  if matchIndex.nil?
+    line[FortranMaxLineLength-2] = "&\n"+line[FortranMaxLineLength-2,1]+"&"
+  else
+    line[matchIndex] = ",&\n" + ' '*7
+  end
+  line
+end
+
+
+# create fortran module variables
+def genModParams(vars)
+  vars.collect {|var, value|
+    "      integer, parameter :: #{var} = #{value}"
+  }.join("\n")
+end
+
+# return the fortran version of the c parameters (name, named constant within
+# iso-c-bindig, fortran type)
+def fortranParamsWithTypes(paramList)
+  paramList.collect {|paramInfo|
+    ctype, param = paramInfo[-2,2]
+    ftype, nc    = CFTypeInfo[ctype][:ftype], CFTypeInfo[ctype][:namedConst]
+    # fortran parameters can be configured out of the c parameters
+    [param.send(FNameMethod),nc,ftype, paramInfo.include?('const')]
+  }
+end
+def startMod(name)
+  "
+module #{name}
+      use, intrinsic :: iso_c_binding
+
+      implicit none
+
+      private
+  "
+end
+def endMod(name)
+  "\nend module #{name}\n"
+end
+def isBadFunction(returnType, returnPointer, paramList)
+  return true if (
+    # external return type
+    (returnType != 'void' and not CFTypeInfo.keys.include?(returnType)) or
+    # pointer2pointer return type
+    returnPointer.length > 1
+  )
+  paramList.each {|paramInfo|
+    next if paramInfo == ['void']
+    next if paramInfo[0] == 'void' and /^\*\w+$/.match(paramInfo[1])
+    ctype, param = paramInfo[-2,2]
+    # TJ: unnamed arguments shouldn't be matched at all but because
+    # pointer * is parsed as part of the name those need to be rejected here
+    return true if (
+      CFTypeInfo[ctype].nil? or                        # derived data type
+      param == '*' or                                  # unnamed pointer
+      param[0,2] == '**' or                            # pointer2pointer
+      (param[0,1] == '*' and /\w\[\d*\]/.match(param)) # array of pointers
+    )
+  }
+  return false
+end
+
+def hasDimension(paramName, paramFType)
+  return true if paramFType == 'character'
+  return true if ( %w[integer real].include?(paramFType) and Vectors.match(paramName) )
+  return false
+end
+
+# collect further information about the original c type of the params and
+# in case of a match between param name and function name, the parameter name
+# is changed
+def setFortranParams(paramswithtypes,fFuncname)
+  # special treatment of empty parameter list
+  return [[],[]] if paramswithtypes == [[]]
+
+  originalParameters = paramswithtypes.transpose[0]
+  paramswithtypes.collect {|param, paramCType, fType, isConstant|
+    # test for pointers/arrays
+    isPointer, isArray, arraySize = false, false, nil
+    if param[0,1] == '*'
+      isPointer = true
+      # remove '*' from funcnames and paramnames
+      param.sub!('*','')
+    end
+    if ( md = /\w\[(\d*)\]/.match(param); not md.nil? )
+      isArray   = true
+      arraySize = md[1] == '' ? '*' : md[1]
+      param.tr!("[#{md[1]}]",'')
+    end
+
+    # change param name if it equals the funcname
+    if param == fFuncname or param.downcase == fFuncname.downcase
+      param += FParamExtension
+      # but maybe the result is the name of another parameter. -> play it again sam...
+      param += FParamExtension while ( originalParameters.include?(param) )
+    end
+    if param[0,1] == '_'
+      param = 'p' + param
+    end
+
+    [param,paramCType,fType,isPointer,isArray,arraySize,isConstant]
+  }
+end
+
+def printParams(fParams, indent)
+  out = ''
+  fParams.each {|param,paramType,ftype,ispointer,isarray,arraysize,isconstant|
+    dimension     = isarray ? "dimension(#{arraysize})" : ( (ispointer and hasDimension(param, ftype) ) ? 'dimension(*)' : nil)
+    intent, value = nil, nil
+    if (ispointer or isarray)
+      if not isconstant
+        intent = 'intent(out)'
+      else
+        intent = 'intent(in)'
+      end unless paramType == 'c_char'
+    else
+      #intent = 'intent(in)'
+      value  = 'value'
+    end
+
+    typeinfo = [value,intent,dimension].select {|s| ! s.nil?}.join(',')
+    out << "  #{indent}#{ftype}"
+    out << (paramType == 'c_ptr' ? '' : "(kind=#{paramType})")
+    out << ", #{typeinfo} :: #{param}\n"
+  }
+  return out
+end
+
+# creates the actual binding within the module for the given c function
+# unsupported types of function a ignored, see RESTRICTIONS (top) for details
+def genInterface(cFuncname, returnType, returnPointer, paramList)
+
+  # do not create interfaces for unsuppoerted function
+  if isBadFunction( returnType, returnPointer, paramList)
+    warn "parameterlist of '#{cFuncname}' is not supported -> function ignored."
+    return ['','']
+  end
+  return ['', ''] if (cFuncname[0,1] == '_')
+  # the void argument type can be left out: if 'void' occures in the
+  # parameterlist (which is only the case, if it is the only parameter
+  # information), it is simply removed and a empty paramter list is left.
+  paramList = [[],[]] if paramList.flatten == [ 'void' ] or paramList.flatten.empty?
+
+  out = ''
+  isWrapper = false
+
+  # create new names for the fortran routines, see CONFIGURATION (top)
+  fFuncname = cFuncname.send(FNameMethod)
+
+  paramsWithTypes = []
+  # divide between empty and non empty parameter lists
+  if paramList == [[],[]]
+    fParams, fParams4Import, fTypes4Import = [], [],[]
+  else
+    # collect information for setting the correct fortran type for each parameter
+    paramsWithTypes = paramList.collect {|paramInfo|
+      ctype, param = paramInfo[-2,2]
+      ptr_match = /^\*(\w+)$/.match(param)
+      if (/^(:?const)? *void$/.match(ctype) and ptr_match)
+        param = ptr_match[1]
+        ftype = 'type(c_ptr)'
+        nc = 'c_ptr'
+      else
+        ftype, nc    = CFTypeInfo[ctype][:ftype], CFTypeInfo[ctype][:namedConst]
+      end
+      # fortran parameters can be configured out of the c parameters
+      [param.send(FNameMethod),nc,ftype, paramInfo.include?('const')]
+    }
+
+    # get deeper information about parameterlists and filter out functions with
+    # non supported parameters
+    fParams = setFortranParams(paramsWithTypes,fFuncname)
+    fParams4Import, fTypes4Import, = fParams.transpose
+  end
+
+  fReturnInfo                    = CFTypeInfo[returnType]
+  indent = '      '
+  if not fReturnInfo.nil?
+    fReturnString = "function"
+    fEnd    = ["#{fReturnInfo[:ftype]}(kind=#{fReturnInfo[:namedConst]}) :: #{fFuncname}\n", "end function" ]
+    fTypes4Import << fReturnInfo[:namedConst]
+  elsif returnType == 'void'
+    fReturnString = "subroutine"
+    fEnd    = ["end subroutine"]
+  end
+  fFuncname_suffix = ''
+
+  if (returnType == 'char' and returnPointer == '*')
+    out << "#{indent}function #{fFuncname}(#{fParams4Import.join(',')})\n"
+    out << printParams(fParams, indent)
+    fTypes4Import.unshift('c_ptr') unless fTypes4Import.include?('c_ptr')
+    isWrapper = true
+    fwEnd = [ "end function" ]
+    fFuncname_suffix = '_c'
+    indent = '        '
+    fEnd = [ "type(c_ptr) :: #{fFuncname}#{fFuncname_suffix}\n",
+             "end function" ]
+  end
+  out << "#{indent}interface
+#{indent}  #{fReturnString} #{fFuncname}#{fFuncname_suffix}(#{fParams4Import.join(',')}) bind(c,name='#{cFuncname}')\n"
+  out << "#{indent}    import :: #{fTypes4Import.uniq.join(',')}\n" unless fTypes4Import.empty?
+
+  out << printParams(fParams, indent + '  ')
+
+  fEnd.each_with_index do |line, i|
+    extra_indent = '    '
+    if i == fEnd.length - 1
+      extra_indent = '  '
+    end
+    out << indent + extra_indent + line
+  end
+  out << " #{fFuncname}#{fFuncname_suffix}\n#{indent}end interface\n"
+  if (returnType == 'char' and returnPointer == '*')
+    indent = '      '
+    out << "#{indent}  character(len=1, kind=c_char), pointer :: #{fFuncname}(:)
+#{indent}  type(c_ptr) :: cptr
+#{indent}  integer :: slen(1)
+
+#{indent}  cptr = #{fFuncname}#{fFuncname_suffix}("
+    out << fParams4Import.join(",&
+#{indent}    ") << ")\n"
+    out << "#{indent}  #{fFuncname} => null()\n"
+    out << "#{indent}  slen(1) = int(strlen(cptr))\n"
+    out << "#{indent}  call c_f_pointer(cptr, #{fFuncname}, slen)\n"
+    fwEnd.each_with_index do |line,i|
+      extra_indent = '  '
+      if i == fwEnd.length - 1
+        extra_indent = ''
+      end
+      out << indent + extra_indent + line
+    end
+    out << " #{fFuncname}\n"
+  end
+  [out, makePublic(fFuncname), isWrapper]
+end
+def makePublic(*fFuncnameList)
+  fFuncnameList.collect {|fname| 
+    "      public :: #{fname.tr('*','')}"
+  }.join("\n") << "\n"
+end
+def ctrim
+  "
+    subroutine ctrim(str)
+    character(kind=c_char), intent(inout) :: str(:)
+    character(kind=c_char) :: c
+    integer :: i
+
+    do i=1,size(str)
+      c = str(i)
+      if (c == c_null_char) then
+        str(i:size(str)) = ' '
+        exit
+      end if
+    end do
+
+    end subroutine ctrim\n"
+end
+
+def clen
+  "
+    function c_len(s) result(i)
+      character(kind=c_char), intent(in) :: s(:)
+      integer :: i
+      do i = 1, size(s)
+        if (s(i) == c_null_char) then
+          exit
+        end if
+      end do
+      i = i - 1
+    end function\n"
+end
+
+################################################################################
+if __FILE__ == $0
+require 'optparse'
+require 'pp'
+
+debug = false
+OptionParser.new do |opts|
+  opts.on("-d","--debug") {debug = true}
+  opts.on_tail("--help","-h","-H","Display this help message.") do
+    puts <<-'END'
+#== Synopsis
+# Create Fortran iso-c-bindings form a given c header file
+# 
+#== Usage
+#   binGen.rb <headerFile> <fortranLibraryFile> [<modName>] [--help|--debug]  
+#
+# headerFile:
+#   A general c header file: function prototypes and '#defines' with numerical
+#   value will be taken for the fortran module construction. Furthermore there
+#   are some restrictions to what is provided in fortran: Currently internal
+#   datatypes and (arrays|pointers) to internal datatypes are supported, i.e.
+#   no arrays of pointers, no pointer to pointers, no typedefs
+#
+# fortranLibraryFile:
+#   file name for generated bindings
+#
+# modName:
+#   This will be the name of the Fortran module, so it has to obey the fortran 
+#   restriction for module names. default: mo_cdi
+#  
+#== Author
+# Ralf Mueller, ralf.mueller at zmaw.de
+#
+#== RESTRICTIONS:
+# ONLY SUPPORT FOR INTERNAL DATATYPES AND (ARRAYS|POINTERS) TO INTERNAL
+# DATATYPES, I.E. NO ARRAYS OF POINTERS, NO POINTER TO POINTERS, NO TYPEDEFS
+#
+#=== Special: naming convention
+# Pointers can have different sizes, which cannot be detetermined by parsing a
+# function prototype. Therefor a convention according the parameter names can
+# be used to take this decision precisely:
+# * Pointers to numbers are expected to be scalars unless the name of the
+#   parameter end with '_vec'
+# * Pointers to char are allways referenced as vectors
+#
+#== LICENSE: 
+# BSD License
+#
+#  Copyright (c) 2009-2012, Ralf Mueller (ralf.mueller at zmaw.de)
+#  All rights reserved.
+#  
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are met:
+#  
+#      * Redistributions of source code must retain the above copyright notice,
+#        this list of conditions and the following disclaimer.
+#  
+#      * Redistributions in binary form must reproduce the above copyright
+#        notice, this list of conditions and the following disclaimer in the
+#        documentation and/or other materials provided with the distribution.
+#  
+#      * The names of its contributors may not be used to endorse or promote
+#        products derived from this software without specific prior written
+#        permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+END
+  exit
+  end
+end.parse!
+
+  if ARGV[1] == nil
+    warn 'no outputile given'
+    exit
+  end
+
+  outputString      = ''
+  modname           = ARGV[2].nil? ? ModuleName : ARGV[2]
+
+  cDefines          = getDefines(ARGV[0])
+  pp cDefines if debug
+  unless cDefines.empty?
+    makeModVarsPublic = makePublic(*cDefines.transpose[0]) 
+    moduleVariables   = genModParams(cDefines)
+  end
+
+  interfaces, makepublics, subroutines = '', '', "contains\n"
+  indent = '    '
+
+  funcdecls = [ [ 'strlen', 'size_t', '', [ [ 'void', '*s' ] ] ] ]
+  funcdecls.concat(getFuncInfo(ARGV[0]))
+
+  funcdecls.each {| funcName, returnType, returnPointer, paramList|
+    pp [funcName, returnType, returnPointer, paramList] if debug
+    interface, makepublic, isWrapper = genInterface(funcName,returnType, returnPointer, paramList)
+    if isWrapper
+      subroutines << interface
+    else
+      interfaces  << interface
+    end
+    makepublics << makepublic
+  }
+
+  # add a specialized trim for wierd c strings
+  makepublics << makePublic('ctrim') << makePublic('c_len')
+  subroutines << ctrim << clen
+
+  File.open(ARGV[1],"w") {|f|
+    [ startMod(modname),
+      moduleVariables ||= '',
+      interfaces,
+      makepublics,
+      makeModVarsPublic ||= '',
+      subroutines,
+      endMod(modname)
+    ].join("\n").split("\n").each {|line| 
+      # check the length of each line before writing to file
+      if line.length > FortranMaxLineLength
+        f << genContinuation(line) << "\n"
+      else
+        f << line << "\n"
+      end
+    }
+  }
+
+end
diff --git a/libcdi/m4/acx_check_strptr_convert.m4 b/libcdi/m4/acx_check_strptr_convert.m4
new file mode 100644
index 0000000..26f95f4
--- /dev/null
+++ b/libcdi/m4/acx_check_strptr_convert.m4
@@ -0,0 +1,103 @@
+dnl acx_fc_check_strprt_convert.m4 --- unset a shell variable
+dnl
+dnl Copyright  (C)  2010  Thomas Jahns <jahns at dkrz.de>
+dnl
+dnl Version: 1.0
+dnl Keywords:
+dnl Author: Thomas Jahns <jahns at dkrz.de>
+dnl Maintainer: Thomas Jahns <jahns at dkrz.de>
+dnl URL: https://www.dkrz.de/redmine/projects/show/scales-ppm
+dnl
+dnl Redistribution and use in source and binary forms, with or without
+dnl modification, are  permitted provided that the following conditions are
+dnl met:
+dnl
+dnl Redistributions of source code must retain the above copyright notice,
+dnl this list of conditions and the following disclaimer.
+dnl
+dnl Redistributions in binary form must reproduce the above copyright
+dnl notice, this list of conditions and the following disclaimer in the
+dnl documentation and/or other materials provided with the distribution.
+dnl
+dnl Neither the name of the DKRZ GmbH nor the names of its contributors
+dnl may be used to endorse or promote products derived from this software
+dnl without specific prior written permission.
+dnl
+dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+dnl IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+dnl TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+dnl PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+dnl OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+dnl EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+dnl PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+dnl PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+dnl LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+dnl NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+dnl
+dnl Commentary:
+dnl
+dnl FIXME: this is currently only a placeholder that expects unset to
+dnl be present although it's not universally available
+dnl
+dnl
+dnl Code:
+dnl
+AC_DEFUN([ACX_FC_CHECK_STRPTR_CONVERT],
+  [AC_LANG_PUSH([Fortran])
+   AC_MSG_CHECKING([if Fortran compiler can handle complex CHARACTER interoperability])
+   AC_COMPILE_IFELSE([AC_LANG_SOURCE([module conftest_mod
+  use iso_c_binding
+  implicit none
+  private
+  public :: errstr
+contains
+  function errstr(errno)
+    integer, intent(in) :: errno
+    interface
+      function strerror(errno) bind(c, name='strerror')
+        import :: c_int, c_ptr
+        integer(c_int), value, intent(in) :: errno
+        type(c_ptr) :: strerror
+      end function strerror
+      function strlen(s) bind(c, name='strlen')
+        import :: c_ptr, c_size_t
+        type(c_ptr), value, intent(in) :: s
+        integer(c_size_t) :: strlen
+      end function strlen
+    end interface
+    type(c_ptr) :: cptr
+    character(len=:, kind=c_char), pointer :: errstr
+
+    cptr = strerror(int(errno, c_int))
+    errstr => c2f_string(cptr, int(strlen(cptr)))
+  end function errstr
+
+  function c2f_string(s, slen)
+    type(c_ptr), intent(in) :: s
+    integer, intent(in) :: slen
+    CHARACTER(len=slen, kind=c_char), POINTER :: c2f_string
+    c2f_string => NULL()
+    call c_f_pointer(s, c2f_string)
+  end function c2f_string
+end module conftest_mod
+
+program conftest
+  use iso_c_binding
+  use conftest_mod, only: errstr
+  implicit none
+  character(kind=c_char, len=:), pointer :: msg
+  msg => errstr(42)
+  write (0, '(a)') msg
+end program conftest])],
+     [AC_MSG_RESULT([yes])
+m4_ifval([$1],[$1])],
+     [AC_MSG_RESULT([no])
+m4_ifval([$2],[$2])])
+   AC_LANG_POP([Fortran])])
+
+dnl
+dnl Local Variables:
+dnl mode: autoconf
+dnl End:
+dnl
diff --git a/libcdi/m4/ax_pthread.m4 b/libcdi/m4/ax_pthread.m4
index 4ecd9c6..d383ad5 100644
--- a/libcdi/m4/ax_pthread.m4
+++ b/libcdi/m4/ax_pthread.m4
@@ -33,6 +33,10 @@
 #   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
 #   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
 #
+#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+#   PTHREAD_CFLAGS.
+#
 #   ACTION-IF-FOUND is a list of shell commands to run if a threads library
 #   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
 #   is not found. If ACTION-IF-FOUND is not specified, the default action
@@ -45,9 +49,12 @@
 #   Alejandro Forero Cuervo to the autoconf macro repository. We are also
 #   grateful for the helpful feedback of numerous users.
 #
+#   Updated for Autoconf 2.68 by Daniel Richard G.
+#
 # LICENSE
 #
 #   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2011 Daniel Richard G. <skunk at iSKUNK.ORG>
 #
 #   This program is free software: you can redistribute it and/or modify it
 #   under the terms of the GNU General Public License as published by the
@@ -75,13 +82,12 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 11
+#serial 21
 
 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
 AC_DEFUN([AX_PTHREAD], [
 AC_REQUIRE([AC_CANONICAL_HOST])
-AC_LANG_SAVE
-AC_LANG_C
+AC_LANG_PUSH([C])
 ax_pthread_ok=no
 
 # We used to check for pthread.h first, but this fails if pthread.h
@@ -97,8 +103,8 @@ if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
         save_LIBS="$LIBS"
         LIBS="$PTHREAD_LIBS $LIBS"
         AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
-        AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
-        AC_MSG_RESULT($ax_pthread_ok)
+        AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
+        AC_MSG_RESULT([$ax_pthread_ok])
         if test x"$ax_pthread_ok" = xno; then
                 PTHREAD_LIBS=""
                 PTHREAD_CFLAGS=""
@@ -139,8 +145,8 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
 # --thread-safe: KAI C++
 # pthread-config: use pthread-config program (for GNU Pth library)
 
-case "${host_cpu}-${host_os}" in
-        *solaris*)
+case ${host_os} in
+        solaris*)
 
         # On Solaris (at least, for some versions), libc contains stubbed
         # (non-functional) versions of the pthreads routines, so link-based
@@ -153,11 +159,25 @@ case "${host_cpu}-${host_os}" in
         ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
         ;;
 
-	*-darwin*)
-	ax_pthread_flags="-pthread $ax_pthread_flags"
-	;;
+        darwin*)
+        ax_pthread_flags="-pthread $ax_pthread_flags"
+        ;;
 esac
 
+# Clang doesn't consider unrecognized options an error unless we specify
+# -Werror. We throw in some extra Clang-specific options to ensure that
+# this doesn't happen for GCC, which also accepts -Werror.
+
+AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
+save_CFLAGS="$CFLAGS"
+ax_pthread_extra_flags="-Werror"
+CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
+                  [AC_MSG_RESULT([yes])],
+                  [ax_pthread_extra_flags=
+                   AC_MSG_RESULT([no])])
+CFLAGS="$save_CFLAGS"
+
 if test x"$ax_pthread_ok" = xno; then
 for flag in $ax_pthread_flags; do
 
@@ -171,12 +191,12 @@ for flag in $ax_pthread_flags; do
                 PTHREAD_CFLAGS="$flag"
                 ;;
 
-		pthread-config)
-		AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
-		if test x"$ax_pthread_config" = xno; then continue; fi
-		PTHREAD_CFLAGS="`pthread-config --cflags`"
-		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-		;;
+                pthread-config)
+                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+                if test x"$ax_pthread_config" = xno; then continue; fi
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
 
                 *)
                 AC_MSG_CHECKING([for the pthreads library -l$flag])
@@ -187,7 +207,7 @@ for flag in $ax_pthread_flags; do
         save_LIBS="$LIBS"
         save_CFLAGS="$CFLAGS"
         LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
 
         # Check for various functions.  We must include pthread.h,
         # since some functions may be macros.  (On the Sequent, we
@@ -198,21 +218,22 @@ for flag in $ax_pthread_flags; do
         # pthread_cleanup_push because it is one of the few pthread
         # functions on Solaris that doesn't have a non-functional libc stub.
         # We try pthread_create on general principles.
-        AC_TRY_LINK([#include <pthread.h>
-		     static void routine(void* a) {a=0;}
-		     static void* start_routine(void* a) {return a;}],
-                    [pthread_t th; pthread_attr_t attr;
-                     pthread_create(&th,0,start_routine,0);
-                     pthread_join(th, 0);
-                     pthread_attr_init(&attr);
-                     pthread_cleanup_push(routine, 0);
-                     pthread_cleanup_pop(0); ],
-                    [ax_pthread_ok=yes])
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+                [ax_pthread_ok=yes],
+                [])
 
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        AC_MSG_RESULT($ax_pthread_ok)
+        AC_MSG_RESULT([$ax_pthread_ok])
         if test "x$ax_pthread_ok" = xyes; then
                 break;
         fi
@@ -230,54 +251,82 @@ if test "x$ax_pthread_ok" = xyes; then
         CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
 
         # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-	AC_MSG_CHECKING([for joinable pthread attribute])
-	attr_name=unknown
-	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
-                        [attr_name=$attr; break])
-	done
-        AC_MSG_RESULT($attr_name)
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        attr_name=unknown
+        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+            AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                           [int attr = $attr; return attr /* ; */])],
+                [attr_name=$attr; break],
+                [])
+        done
+        AC_MSG_RESULT([$attr_name])
         if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
-            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+            AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
                                [Define to necessary symbol if this constant
                                 uses a non-standard name on your system.])
         fi
 
         AC_MSG_CHECKING([if more special flags are required for pthreads])
         flag=no
-        case "${host_cpu}-${host_os}" in
-            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        case ${host_os} in
+            aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+            osf* | hpux*) flag="-D_REENTRANT";;
+            solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                # TODO: What about Clang on Solaris?
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
-        AC_MSG_RESULT(${flag})
+        AC_MSG_RESULT([$flag])
         if test "x$flag" != xno; then
             PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
         fi
 
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            [ax_cv_PTHREAD_PRIO_INHERIT], [
+                AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+                                                [[int i = PTHREAD_PRIO_INHERIT;]])],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+            [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
+
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        # More AIX lossage: must compile with xlc_r or cc_r
-	if test x"$GCC" != xyes -a \( x"$CC" = xxlc -o x"$CC" = cc \) ; then
-          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
-        else
-          PTHREAD_CC=$CC
-	fi
-else
-        PTHREAD_CC="$CC"
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != xyes; then
+            case $host_os in
+                aix*)
+                AS_CASE(["x/$CC"],
+                  [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+                  [#handle absolute path differently from PATH based program lookup
+                   AS_CASE(["x$CC"],
+                     [x/*],
+                     [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+                     [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+                ;;
+            esac
+        fi
 fi
 
-AC_SUBST(PTHREAD_LIBS)
-AC_SUBST(PTHREAD_CFLAGS)
-AC_SUBST(PTHREAD_CC)
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
 
 # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
 if test x"$ax_pthread_ok" = xyes; then
-        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
         :
 else
         ax_pthread_ok=no
         $2
 fi
-AC_LANG_RESTORE
+AC_LANG_POP
 ])dnl AX_PTHREAD
diff --git a/libcdi/m4/starlink_fpp.m4 b/libcdi/m4/starlink_fpp.m4
index 7fb29d2..49c9e41 100644
--- a/libcdi/m4/starlink_fpp.m4
+++ b/libcdi/m4/starlink_fpp.m4
@@ -317,6 +317,8 @@ AC_DEFUN([_ACX_SL_PROG_FPP],dnl
            "$FC $FCFLAGS -F" "$FC $FCFLAGS -E" "$FC $FCFLAGS -E" \
            "$FC $FCFLAGS -E -cpp" "$FC $FCFLAGS -x f95-cpp-input -E -P" \
            "${F77-f77} -F" "${F77-f77} -E" 'fpp' \
+           "$CPP -std=c89" "$CPP -x c -std=c89" 'cpp -std=c89' '/lib/cpp - std=c89' \
+           '/usr/ccs/lib/cpp -std=c89' 'g77 -E -std=c89' '${CC-cc} -E -std=c89' \
            "$CPP" "$CPP -x c" 'cpp' '/lib/cpp' \
            '/usr/ccs/lib/cpp' 'g77 -E' '${CC-cc} -E'
          do
diff --git a/libcdi/src/Makefile.am b/libcdi/src/Makefile.am
index 2e66f53..4e83286 100644
--- a/libcdi/src/Makefile.am
+++ b/libcdi/src/Makefile.am
@@ -77,6 +77,8 @@ 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  \
@@ -189,7 +191,7 @@ all-local: $(LOCALTARGETS)
 CLEANFILES  = `ls *~`
 #CLEANFILES += cdilib.c
 if CREATE_ISOC
-CLEANFILES += $(top_builddir)/src/mo_cdi.$(FCMODEXT) $(top_builddir)/src/mo_cdi.$(OBJEXT)
+CLEANFILES += mo_cdi.$(FCMODEXT) mo_cdi.$(OBJEXT) mo_cdi.f90
 endif
 
 if ENABLE_CDI_LIB
diff --git a/libcdi/src/Makefile.in b/libcdi/src/Makefile.in
index 3e7517a..43d1c37 100644
--- a/libcdi/src/Makefile.in
+++ b/libcdi/src/Makefile.in
@@ -86,7 +86,7 @@ host_triplet = @host@
 @ENABLE_CDI_LIB_TRUE@@USE_MPI_TRUE at am__append_5 = pkgconfig/cdipio.pc
 @CREATE_ISOC_TRUE at am__append_6 = mo_cdi.$(OBJEXT)
 #CLEANFILES += cdilib.c
- at CREATE_ISOC_TRUE@am__append_7 = $(top_builddir)/src/mo_cdi.$(FCMODEXT) $(top_builddir)/src/mo_cdi.$(OBJEXT)
+ at CREATE_ISOC_TRUE@am__append_7 = mo_cdi.$(FCMODEXT) mo_cdi.$(OBJEXT) mo_cdi.f90
 @ENABLE_CDI_LIB_TRUE at am__append_8 = pkgconfig/cdi.pc
 @ENABLE_CDI_LIB_TRUE@@USE_MPI_TRUE at am__append_9 = pkgconfig/cdipio.pc
 @ENABLE_CDI_LIB_TRUE@@USE_MPI_TRUE at am__append_10 = pkgconfig/cdipio.pc
@@ -97,6 +97,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
@@ -150,10 +151,11 @@ am_libcdi_la_OBJECTS = basetime.lo binary.lo calendar.lo cdf.lo \
 	institution.lo model.lo namespace.lo serialize.lo \
 	resource_handle.lo servicelib.lo stream_cdf.lo \
 	stream_cgribex.lo stream_ext.lo stream_grb.lo \
-	stream_gribapi.lo stream_history.lo stream_ieg.lo cdi_int.lo \
-	stream_record.lo stream_srv.lo stream_var.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 swap.lo
+	stream_gribapi.lo stream_history.lo stream_ieg.lo \
+	stream_fcommon.lo cdi_int.lo stream_record.lo stream_srv.lo \
+	stream_var.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 swap.lo
 libcdi_la_OBJECTS = $(am_libcdi_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -497,6 +499,8 @@ 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  \
@@ -730,6 +734,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_cdf.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_cgribex.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_ext.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_fcommon.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_grb.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_gribapi.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_history.Plo at am__quote@
diff --git a/libcdi/src/basetime.c b/libcdi/src/basetime.c
index f42d2f9..3d4d5e3 100644
--- a/libcdi/src/basetime.c
+++ b/libcdi/src/basetime.c
@@ -16,11 +16,12 @@ void basetimeInit(basetime_t *basetime)
   if ( basetime == NULL )
     Error("Internal problem! Basetime not allocated.");
 
-  (*basetime).ncvarid       = UNDEFID;
-  (*basetime).ncdimid       = UNDEFID;
-  (*basetime).ncvarboundsid = UNDEFID;
-  (*basetime).leadtimeid    = UNDEFID;
-  (*basetime).lwrf          = 0;
+  basetime->ncvarid       = UNDEFID;
+  basetime->ncdimid       = UNDEFID;
+  basetime->ncvarboundsid = UNDEFID;
+  basetime->leadtimeid    = UNDEFID;
+  basetime->lwrf          = 0;
+  basetime->timevar_cache = NULL;
 }
 /*
  * Local Variables:
diff --git a/libcdi/src/basetime.h b/libcdi/src/basetime.h
index 1bdc997..8a56f5a 100644
--- a/libcdi/src/basetime.h
+++ b/libcdi/src/basetime.h
@@ -1,6 +1,16 @@
 #ifndef _BASETIME_H
 #define _BASETIME_H
 
+//#define USE_TIMECACHE 1
+#define MAX_TIMECACHE_SIZE 1024
+
+typedef struct {
+  int size;
+  int startid;
+  int maxvals;
+  double cache[MAX_TIMECACHE_SIZE];
+}
+timecache_t;
 
 typedef struct {
   int   ncvarid;
@@ -8,6 +18,7 @@ typedef struct {
   int   ncvarboundsid;
   int   leadtimeid;
   int   lwrf;     /* TRUE for time axis in WRF format */
+  timecache_t *timevar_cache;
 }
 basetime_t;
 
diff --git a/libcdi/src/calendar.c b/libcdi/src/calendar.c
index fdb5fc0..b3b8ad7 100644
--- a/libcdi/src/calendar.c
+++ b/libcdi/src/calendar.c
@@ -1,6 +1,8 @@
+#include <limits.h>
 #include <stdio.h>
 
 #include "cdi.h"  		/* CALENDAR_ */
+#include "error.h"
 #include "timebase.h"
 
 
@@ -112,17 +114,17 @@ static int encode_day(int dpy, int year, int month, int day)
 {
   int i;
   int *dpm = NULL;
-  double rval;
-
-  rval = dpy * year + day;
+  long rval = (long)dpy * year + day;
 
   if      ( dpy == 360 ) dpm = month_360;
   else if ( dpy == 365 ) dpm = month_365;
   else if ( dpy == 366 ) dpm = month_366;
-  
+
   if ( dpm ) for ( i = 0; i < month-1; i++ ) rval += dpm[i];
+  if (rval > INT_MAX || rval < INT_MIN)
+    Error("Unhandled date: %ld", rval);
 
-  return (rval);
+  return (int)rval;
 }
 
 
diff --git a/libcdi/src/cdf.c b/libcdi/src/cdf.c
index 3c9bc95..29e32c9 100644
--- a/libcdi/src/cdf.c
+++ b/libcdi/src/cdf.c
@@ -67,19 +67,18 @@ void cdfComment(int ncid)
 {
   static char comment[256] = "Climate Data Interface version ";
   static int init = 0;
-  char *blank;
-  int size = 0;
 
   if ( ! init )
     {
       init = 1;
-      blank = strchr(cdiLibraryVersion(), ' ');
-      if ( blank ) size = blank - cdiLibraryVersion();
+      const char *libvers = cdiLibraryVersion();
+      const char *blank = strchr(libvers, ' ');
+      size_t size = blank ? (size_t)(blank - libvers) : 0;
 
-      if ( size == 0 || ! isdigit((int) *cdiLibraryVersion()) )
+      if ( size == 0 || ! isdigit((int) *libvers) )
 	strcat(comment, "??");
       else
-	strncat(comment, cdiLibraryVersion(), size);
+	strncat(comment, libvers, size);
       strcat(comment, " (http://code.zmaw.de/projects/cdi)");
     }
 
diff --git a/libcdi/src/cdf_int.c b/libcdi/src/cdf_int.c
index 3f42f13..742ad27 100644
--- a/libcdi/src/cdf_int.c
+++ b/libcdi/src/cdf_int.c
@@ -56,7 +56,8 @@ void cdf_create(const char *path, int cmode, int *ncidp)
   chunksizehint = 16777216; /* 16 MB */
 #endif
 
-  if ( cdiNcChunksizehint != CDI_UNDEFID ) chunksizehint = cdiNcChunksizehint;
+  if ( cdiNcChunksizehint != CDI_UNDEFID )
+    chunksizehint = (size_t)cdiNcChunksizehint;
 
   cdi_nc__create_funcp my_nc__create =
     (cdi_nc__create_funcp)namespaceSwitchGet(NSSWITCH_NC__CREATE).func;
@@ -101,7 +102,8 @@ int cdf_open(const char *path, int omode, int *ncidp)
       /*
       if ( chunksizehint < ChunkSizeMin ) chunksizehint = ChunkSizeMin;
       */
-      if ( cdiNcChunksizehint != CDI_UNDEFID ) chunksizehint = cdiNcChunksizehint;
+      if ( cdiNcChunksizehint != CDI_UNDEFID )
+        chunksizehint = (size_t)cdiNcChunksizehint;
 
       /* FIXME: parallel part missing */
       status = nc__open(path, omode, &chunksizehint, ncidp);
@@ -536,6 +538,19 @@ void  cdf_get_vara_text(int ncid, int varid, const size_t start[],
 }
 
 
+void  cdf_get_vara_uchar(int ncid, int varid, const size_t start[], const size_t count[], unsigned char *tp)
+{
+  int status;
+
+  status = nc_get_vara_uchar(ncid, varid, start, count, tp);
+
+  if ( CDF_Debug || status != NC_NOERR )
+    Message("ncid = %d varid = %d", ncid, varid);
+
+  if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
+}
+
+
 void cdf_put_var_double(int ncid, int varid, const double *dp)
 {
   int status;
@@ -723,7 +738,7 @@ void cdf_put_att_double(int ncid, int varid, const char *name, nc_type xtype,
 }
 
 
-void cdf_get_att_text(int ncid, int varid, char *name, char *tp)
+void cdf_get_att_text(int ncid, int varid, const char *name, char *tp)
 {
   int status;
 
@@ -735,8 +750,22 @@ void cdf_get_att_text(int ncid, int varid, char *name, char *tp)
   if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
 }
 
+void cdf_get_att_string(int ncid, int varid, const char *name, char **tp)
+{
+#if  defined  (HAVE_NETCDF4)
+  int status;
+
+  status = nc_get_att_string(ncid, varid, name, tp);
+
+  if ( CDF_Debug || status != NC_NOERR )
+    Message("ncid = %d varid = %d name = %s", ncid, varid, name);
+
+  if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
+#endif
+}
+
 
-void cdf_get_att_int(int ncid, int varid, char *name, int *ip)
+void cdf_get_att_int(int ncid, int varid, const char *name, int *ip)
 {
   int status;
 
@@ -749,7 +778,7 @@ void cdf_get_att_int(int ncid, int varid, char *name, int *ip)
 }
 
 
-void cdf_get_att_double(int ncid, int varid, char *name, double *dp)
+void cdf_get_att_double(int ncid, int varid, const char *name, double *dp)
 {
   int status;
 
diff --git a/libcdi/src/cdf_int.h b/libcdi/src/cdf_int.h
index e73166f..59ef922 100644
--- a/libcdi/src/cdf_int.h
+++ b/libcdi/src/cdf_int.h
@@ -22,14 +22,11 @@ void cdf_inq_dimid (int ncid, const char *name, int *dimidp);
 void cdf_inq_dim (int ncid, int dimid, char *name, size_t * lengthp);
 void cdf_inq_dimname (int ncid, int dimid, char *name);
 void cdf_inq_dimlen (int ncid, int dimid, size_t * lengthp);
-void cdf_def_var (int ncid, const char *name, nc_type xtype, int ndims,
-		 const int dimids[], int *varidp);
-void cdf_def_var_serial(int ncid, const char *name, nc_type xtype, int ndims,
-                        const int dimids[], int *varidp);
-void cdf_inq_varid (int ncid, const char *name, int *varidp);
-void cdf_inq_nvars (int ncid, int *nvarsp);
-void cdf_inq_var (int ncid, int varid, char *name, nc_type *xtypep,
-		 int *ndimsp, int dimids[], int *nattsp);
+void cdf_def_var (int ncid, const char *name, nc_type xtype, int ndims, const int dimids[], int *varidp);
+void cdf_def_var_serial(int ncid, const char *name, nc_type xtype, int ndims, const int dimids[], int *varidp);
+void cdf_inq_varid(int ncid, const char *name, int *varidp);
+void cdf_inq_nvars(int ncid, int *nvarsp);
+void cdf_inq_var(int ncid, int varid, char *name, nc_type *xtypep, int *ndimsp, int dimids[], int *nattsp);
 void cdf_inq_varname (int ncid, int varid, char *name);
 void cdf_inq_vartype (int ncid, int varid, nc_type *xtypep);
 void cdf_inq_varndims (int ncid, int varid, int *ndimsp);
@@ -60,36 +57,29 @@ void cdf_get_var1_text(int ncid, int varid, const size_t index[], char *tp);
 void cdf_get_var1_double(int ncid, int varid, const size_t index[], double *dp);
 void cdf_put_var1_double(int ncid, int varid, const size_t index[], const double *dp);
 
-void cdf_get_vara_text(int ncid, int varid, const size_t start[],
-		       const size_t count[], char *tp);
-
-void cdf_get_vara_double(int ncid, int varid, const size_t start[],
-                         const size_t count[], double *dp);
-void cdf_put_vara_double(int ncid, int varid, const size_t start[],
-                         const size_t count[], const double *dp);
-
-void cdf_get_vara_float(int ncid, int varid, const size_t start[],
-                        const size_t count[], float *fp);
-void cdf_put_vara_float(int ncid, int varid, const size_t start[],
-                        const size_t count[], const float *fp);
-
-void cdf_put_att_text (int ncid, int varid, const char *name, size_t len,
-		      const char *tp);
-void cdf_put_att_int (int ncid, int varid, const char *name, nc_type xtype,
-		     size_t len, const int *ip);
-void cdf_put_att_double (int ncid, int varid, const char *name, nc_type xtype,
-			size_t len, const double *dp);
-
-void cdf_get_att_text (int ncid, int varid, char *name, char *tp);
-void cdf_get_att_int (int ncid, int varid, char *name, int *ip);
-void cdf_get_att_double (int ncid, int varid, char *name, double *dp);
-
-void cdf_inq_att (int ncid, int varid, const char *name, nc_type * xtypep,
-		 size_t * lenp);
-void cdf_inq_atttype (int ncid, int varid, const char *name, nc_type *xtypep);
+void cdf_get_vara_uchar(int ncid, int varid, const size_t start[], const size_t count[], unsigned char *tp);
+void cdf_get_vara_text(int ncid, int varid, const size_t start[], const size_t count[], char *tp);
+
+void cdf_get_vara_double(int ncid, int varid, const size_t start[], const size_t count[], double *dp);
+void cdf_put_vara_double(int ncid, int varid, const size_t start[], const size_t count[], const double *dp);
+
+void cdf_get_vara_float(int ncid, int varid, const size_t start[], const size_t count[], float *fp);
+void cdf_put_vara_float(int ncid, int varid, const size_t start[], const size_t count[], const float *fp);
+
+void cdf_put_att_text(int ncid, int varid, const char *name, size_t len, const char *tp);
+void cdf_put_att_int(int ncid, int varid, const char *name, nc_type xtype, size_t len, const int *ip);
+void cdf_put_att_double(int ncid, int varid, const char *name, nc_type xtype, size_t len, const double *dp);
+
+void cdf_get_att_string(int ncid, int varid, const char *name, char **tp);
+void cdf_get_att_text  (int ncid, int varid, const char *name, char *tp);
+void cdf_get_att_int   (int ncid, int varid, const char *name, int *ip);
+void cdf_get_att_double(int ncid, int varid, const char *name, double *dp);
+
+void cdf_inq_att    (int ncid, int varid, const char *name, nc_type * xtypep, size_t * lenp);
+void cdf_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep);
 void cdf_inq_attlen (int ncid, int varid, const char *name, size_t *lenp);
-void cdf_inq_attname (int ncid, int varid, int attnum, char *name);
-void cdf_inq_attid (int ncid, int varid, const char *name, int *attnump);
+void cdf_inq_attname(int ncid, int varid, int attnum, char *name);
+void cdf_inq_attid  (int ncid, int varid, const char *name, int *attnump);
 
 typedef int (*cdi_nc__create_funcp)(const char *path, int cmode,
                                     size_t initialsz, size_t *chunksizehintp,
diff --git a/libcdi/src/cdi.h b/libcdi/src/cdi.h
index 035720b..170a171 100644
--- a/libcdi/src/cdi.h
+++ b/libcdi/src/cdi.h
@@ -7,6 +7,7 @@
 #ifndef  CDI_H_
 #define  CDI_H_
 
+#include <stdio.h>
 #include <sys/types.h>
 /*
 #if defined(__cplusplus)
@@ -40,6 +41,7 @@ extern "C" {
 
 /* File types */
 
+#define  FILETYPE_UNDEF          -1   /* Unknown/not yet defined file type */
 #define  FILETYPE_GRB             1   /* File type GRIB                       */
 #define  FILETYPE_GRB2            2   /* File type GRIB version 2             */
 #define  FILETYPE_NC              3   /* File type netCDF                     */
@@ -197,14 +199,15 @@ extern "C" {
 
 #define  TUNIT_SECOND             1
 #define  TUNIT_MINUTE             2
-#define  TUNIT_HOUR               3
-#define  TUNIT_DAY                4
-#define  TUNIT_MONTH              5
-#define  TUNIT_YEAR               6
-#define  TUNIT_QUARTER            7
-#define  TUNIT_3HOURS             8
-#define  TUNIT_6HOURS             9
-#define  TUNIT_12HOURS           10
+#define  TUNIT_QUARTER            3
+#define  TUNIT_30MINUTES          4
+#define  TUNIT_HOUR               5
+#define  TUNIT_3HOURS             6
+#define  TUNIT_6HOURS             7
+#define  TUNIT_12HOURS            8
+#define  TUNIT_DAY                9
+#define  TUNIT_MONTH             10
+#define  TUNIT_YEAR              11
 
 /* CALENDAR types */
 
@@ -224,7 +227,7 @@ char   *cdiStringError(int cdiErrno);
 
 void    cdiDebug(int debug);
 
-char   *cdiLibraryVersion(void);
+const char *cdiLibraryVersion(void);
 void    cdiPrintVersion(void);
 
 int     cdiHaveFiletype(int filetype);
@@ -326,6 +329,7 @@ void    streamWriteVarF(int streamID, int varID, const float *data_vec, int nmis
 
 /*      streamReadVar: Read a variable */
 void    streamReadVar(int streamID, int varID, double *data_vec, int *nmiss);
+void    streamReadVarF(int streamID, int varID, float *data_vec, int *nmiss);
 
 /*      streamWriteVarSlice: Write a horizontal slice of a variable */
 void    streamWriteVarSlice(int streamID, int varID, int levelID, const double *data_vec, int nmiss);
@@ -333,6 +337,7 @@ void    streamWriteVarSliceF(int streamID, int varID, int levelID, const float *
 
 /*      streamReadVarSlice: Read a horizontal slice of a variable */
 void    streamReadVarSlice(int streamID, int varID, int levelID, double *data_vec, int *nmiss);
+void    streamReadVarSliceF(int streamID, int varID, int levelID, float *data_vec, int *nmiss);
 
 void    streamWriteVarChunk(int streamID, int varID, const int rect[][2],
                             const double *data_vec, int nmiss);
@@ -347,7 +352,7 @@ void    streamWriteRecordF(int streamID, const float *data_vec, int nmiss);
 void    streamReadRecord(int streamID, double *data_vec, int *nmiss);
 void    streamCopyRecord(int streamIDdest, int streamIDsrc);
 
-void    streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
+void    streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
 
 /* VLIST routines */
 
@@ -520,6 +525,9 @@ int     vlistInqVarTimaccu(int vlistID, int varID);
 void    vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGeneratingProcess);
 int     vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID);
 
+void    vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDefinitionTemplate);
+int     vlistInqVarProductDefinitionTemplate(int vlistID, int varID);
+
 int     vlistInqVarSize(int vlistID, int varID);
 
 void    vlistDefIndex(int vlistID, int varID, int levID, int index);
@@ -987,6 +995,7 @@ char   *modelInqNamePtr(int modelID);
 /* Table routines */
 
 void    tableWriteC(const char *filename, int tableID);
+void    tableFWriteC(FILE *ptfp, int tableID);
 void    tableWrite(const char *filename, int tableID);
 int     tableRead(const char *tablefile);
 int     tableDef(int modelID, int tablenum, const char *tablename);
@@ -1007,9 +1016,9 @@ int     tableInqParName(int tableID, int code, char *name);
 int     tableInqParLongname(int tableID, int code, char *longname);
 int     tableInqParUnits(int tableID, int code, char *units);
 
-char   *tableInqParNamePtr(int tableID, int parID);
-char   *tableInqParLongnamePtr(int tableID, int parID);
-char   *tableInqParUnitsPtr(int tableID, int parID);
+const char *tableInqParNamePtr(int tableID, int parID);
+const char *tableInqParLongnamePtr(int tableID, int parID);
+const char *tableInqParUnitsPtr(int tableID, int parID);
 
 /* History routines */
 
@@ -1017,6 +1026,9 @@ void    streamDefHistory(int streamID, int size, const char *history);
 int     streamInqHistorySize(int streamID);
 void    streamInqHistoryString(int streamID, char *history);
 
+
+void gribapiLibraryVersion(int *major_version, int *minor_version, int *revision_version);
+
 /*
 #if defined (__cplusplus)
 }
diff --git a/libcdi/src/cdi.inc b/libcdi/src/cdi.inc
index c6eb0f0..11d9993 100644
--- a/libcdi/src/cdi.inc
+++ b/libcdi/src/cdi.inc
@@ -4,7 +4,7 @@
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   February 2014
+! Uwe Schulzweida, MPI-MET, Hamburg,   September 2014
 !
 
       INTEGER    CDI_MAX_NAME          
@@ -48,6 +48,8 @@
 !
 !  File types
 !
+      INTEGER    FILETYPE_UNDEF        
+      PARAMETER (FILETYPE_UNDEF         = -1)
       INTEGER    FILETYPE_GRB          
       PARAMETER (FILETYPE_GRB           =  1)
       INTEGER    FILETYPE_GRB2         
@@ -334,22 +336,24 @@
       PARAMETER (TUNIT_SECOND           =  1)
       INTEGER    TUNIT_MINUTE          
       PARAMETER (TUNIT_MINUTE           =  2)
-      INTEGER    TUNIT_HOUR            
-      PARAMETER (TUNIT_HOUR             =  3)
-      INTEGER    TUNIT_DAY             
-      PARAMETER (TUNIT_DAY              =  4)
-      INTEGER    TUNIT_MONTH           
-      PARAMETER (TUNIT_MONTH            =  5)
-      INTEGER    TUNIT_YEAR            
-      PARAMETER (TUNIT_YEAR             =  6)
       INTEGER    TUNIT_QUARTER         
-      PARAMETER (TUNIT_QUARTER          =  7)
+      PARAMETER (TUNIT_QUARTER          =  3)
+      INTEGER    TUNIT_30MINUTES       
+      PARAMETER (TUNIT_30MINUTES        =  4)
+      INTEGER    TUNIT_HOUR            
+      PARAMETER (TUNIT_HOUR             =  5)
       INTEGER    TUNIT_3HOURS          
-      PARAMETER (TUNIT_3HOURS           =  8)
+      PARAMETER (TUNIT_3HOURS           =  6)
       INTEGER    TUNIT_6HOURS          
-      PARAMETER (TUNIT_6HOURS           =  9)
+      PARAMETER (TUNIT_6HOURS           =  7)
       INTEGER    TUNIT_12HOURS         
-      PARAMETER (TUNIT_12HOURS          = 10)
+      PARAMETER (TUNIT_12HOURS          =  8)
+      INTEGER    TUNIT_DAY             
+      PARAMETER (TUNIT_DAY              =  9)
+      INTEGER    TUNIT_MONTH           
+      PARAMETER (TUNIT_MONTH            = 10)
+      INTEGER    TUNIT_YEAR            
+      PARAMETER (TUNIT_YEAR             = 11)
 !
 !  CALENDAR types
 !
@@ -502,6 +506,9 @@
 !                                    (INTEGER         streamID)
       EXTERNAL        streamInqVlist
 
+!
+!  PIO:
+!
       INTEGER         streamInqVlistIDorig
 !                                    (INTEGER         streamID)
       EXTERNAL        streamInqVlistIDorig
@@ -524,15 +531,15 @@
 !                                     INTEGER         comptype)
       EXTERNAL        streamDefCompType
 
+      INTEGER         streamInqCompType
+!                                    (INTEGER         streamID)
+      EXTERNAL        streamInqCompType
+
 !                     streamDefCompLevel
 !                                    (INTEGER         streamID,
 !                                     INTEGER         complevel)
       EXTERNAL        streamDefCompLevel
 
-      INTEGER         streamInqCompType
-!                                    (INTEGER         streamID)
-      EXTERNAL        streamInqCompType
-
       INTEGER         streamInqCompLevel
 !                                    (INTEGER         streamID)
       EXTERNAL        streamInqCompLevel
@@ -542,18 +549,15 @@
 !                                     INTEGER         tsID)
       EXTERNAL        streamDefTimestep
 
-!
-!  query currently set timestep id
-!
-      INTEGER         streamInqCurTimestepID
-!                                    (INTEGER         streamID)
-      EXTERNAL        streamInqCurTimestepID
-
       INTEGER         streamInqTimestep
 !                                    (INTEGER         streamID,
 !                                     INTEGER         tsID)
       EXTERNAL        streamInqTimestep
 
+      INTEGER         streamInqCurTimestepID
+!                                    (INTEGER         streamID)
+      EXTERNAL        streamInqCurTimestepID
+
       CHARACTER(80)   streamFilename
 !                                    (INTEGER         streamID)
       EXTERNAL        streamFilename
@@ -573,13 +577,6 @@
 !
 !  STREAM var I/O routines
 !
-!                     streamReadVar
-!                                    (INTEGER         streamID,
-!                                     INTEGER         varID,
-!                                     DOUBLEPRECISION data_vec,
-!                                     INTEGER         nmiss)
-      EXTERNAL        streamReadVar
-
 !                     streamWriteVar
 !                                    (INTEGER         streamID,
 !                                     INTEGER         varID,
@@ -594,13 +591,19 @@
 !                                     INTEGER         nmiss)
       EXTERNAL        streamWriteVarF
 
-!                     streamReadVarSlice
+!                     streamReadVar
 !                                    (INTEGER         streamID,
 !                                     INTEGER         varID,
-!                                     INTEGER         levelID,
 !                                     DOUBLEPRECISION data_vec,
 !                                     INTEGER         nmiss)
-      EXTERNAL        streamReadVarSlice
+      EXTERNAL        streamReadVar
+
+!                     streamReadVarF
+!                                    (INTEGER         streamID,
+!                                     INTEGER         varID,
+!                                     REAL            data_vec,
+!                                     INTEGER         nmiss)
+      EXTERNAL        streamReadVarF
 
 !                     streamWriteVarSlice
 !                                    (INTEGER         streamID,
@@ -618,6 +621,22 @@
 !                                     INTEGER         nmiss)
       EXTERNAL        streamWriteVarSliceF
 
+!                     streamReadVarSlice
+!                                    (INTEGER         streamID,
+!                                     INTEGER         varID,
+!                                     INTEGER         levelID,
+!                                     DOUBLEPRECISION data_vec,
+!                                     INTEGER         nmiss)
+      EXTERNAL        streamReadVarSlice
+
+!                     streamReadVarSliceF
+!                                    (INTEGER         streamID,
+!                                     INTEGER         varID,
+!                                     INTEGER         levelID,
+!                                     REAL            data_vec,
+!                                     INTEGER         nmiss)
+      EXTERNAL        streamReadVarSliceF
+
 !                     streamWriteVarChunk
 !                                    (INTEGER         streamID,
 !                                     INTEGER         varID,
@@ -629,23 +648,17 @@
 !
 !  STREAM record I/O routines
 !
-!                     streamInqRecord
-!                                    (INTEGER         streamID,
-!                                     INTEGER         varID,
-!                                     INTEGER         levelID)
-      EXTERNAL        streamInqRecord
-
 !                     streamDefRecord
 !                                    (INTEGER         streamID,
 !                                     INTEGER         varID,
 !                                     INTEGER         levelID)
       EXTERNAL        streamDefRecord
 
-!                     streamReadRecord
+!                     streamInqRecord
 !                                    (INTEGER         streamID,
-!                                     DOUBLEPRECISION data_vec,
-!                                     INTEGER         nmiss)
-      EXTERNAL        streamReadRecord
+!                                     INTEGER         varID,
+!                                     INTEGER         levelID)
+      EXTERNAL        streamInqRecord
 
 !                     streamWriteRecord
 !                                    (INTEGER         streamID,
@@ -659,6 +672,12 @@
 !                                     INTEGER         nmiss)
       EXTERNAL        streamWriteRecordF
 
+!                     streamReadRecord
+!                                    (INTEGER         streamID,
+!                                     DOUBLEPRECISION data_vec,
+!                                     INTEGER         nmiss)
+      EXTERNAL        streamReadRecord
+
 !                     streamCopyRecord
 !                                    (INTEGER         streamIDdest,
 !                                     INTEGER         streamIDsrc)
@@ -867,17 +886,17 @@
 !                                     INTEGER         code)
       EXTERNAL        vlistInqVarID
 
-      INTEGER         vlistInqVarTsteptype
-!                                    (INTEGER         vlistID,
-!                                     INTEGER         varID)
-      EXTERNAL        vlistInqVarTsteptype
-
 !                     vlistDefVarTsteptype
 !                                    (INTEGER         vlistID,
 !                                     INTEGER         varID,
 !                                     INTEGER         tsteptype)
       EXTERNAL        vlistDefVarTsteptype
 
+      INTEGER         vlistInqVarTsteptype
+!                                    (INTEGER         vlistID,
+!                                     INTEGER         varID)
+      EXTERNAL        vlistInqVarTsteptype
+
 !                     vlistDefVarCompType
 !                                    (INTEGER         vlistID,
 !                                     INTEGER         varID,
@@ -1119,6 +1138,17 @@
 !                                     INTEGER         varID)
       EXTERNAL        vlistInqVarTypeOfGeneratingProcess
 
+!                     vlistDefVarProductDefinitionTemplate
+!                                    (INTEGER         vlistID,
+!                                     INTEGER         varID,
+!                                     INTEGER         productDefinitionTemplate)
+      EXTERNAL        vlistDefVarProductDefinitionTemplate
+
+      INTEGER         vlistInqVarProductDefinitionTemplate
+!                                    (INTEGER         vlistID,
+!                                     INTEGER         varID)
+      EXTERNAL        vlistInqVarProductDefinitionTemplate
+
       INTEGER         vlistInqVarSize
 !                                    (INTEGER         vlistID,
 !                                     INTEGER         varID)
@@ -1418,71 +1448,71 @@
 !                                     CHARACTER*(*)   xname)
       EXTERNAL        gridDefXname
 
+!                     gridInqXname
+!                                    (INTEGER         gridID,
+!                                     CHARACTER*(*)   xname)
+      EXTERNAL        gridInqXname
+
 !                     gridDefXlongname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   xlongname)
       EXTERNAL        gridDefXlongname
 
+!                     gridInqXlongname
+!                                    (INTEGER         gridID,
+!                                     CHARACTER*(*)   xlongname)
+      EXTERNAL        gridInqXlongname
+
 !                     gridDefXunits
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   xunits)
       EXTERNAL        gridDefXunits
 
+!                     gridInqXunits
+!                                    (INTEGER         gridID,
+!                                     CHARACTER*(*)   xunits)
+      EXTERNAL        gridInqXunits
+
 !                     gridDefYname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   yname)
       EXTERNAL        gridDefYname
 
+!                     gridInqYname
+!                                    (INTEGER         gridID,
+!                                     CHARACTER*(*)   yname)
+      EXTERNAL        gridInqYname
+
 !                     gridDefYlongname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   ylongname)
       EXTERNAL        gridDefYlongname
 
+!                     gridInqYlongname
+!                                    (INTEGER         gridID,
+!                                     CHARACTER*(*)   ylongname)
+      EXTERNAL        gridInqYlongname
+
 !                     gridDefYunits
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   yunits)
       EXTERNAL        gridDefYunits
 
-!                     gridInqXname
-!                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   xname)
-      EXTERNAL        gridInqXname
-
-!                     gridInqXlongname
+!                     gridInqYunits
 !                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   xlongname)
-      EXTERNAL        gridInqXlongname
+!                                     CHARACTER*(*)   yunits)
+      EXTERNAL        gridInqYunits
 
 !                     gridInqXstdname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   xstdname)
       EXTERNAL        gridInqXstdname
 
-!                     gridInqXunits
-!                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   xunits)
-      EXTERNAL        gridInqXunits
-
-!                     gridInqYname
-!                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   yname)
-      EXTERNAL        gridInqYname
-
-!                     gridInqYlongname
-!                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   ylongname)
-      EXTERNAL        gridInqYlongname
-
 !                     gridInqYstdname
 !                                    (INTEGER         gridID,
 !                                     CHARACTER*(*)   ystdname)
       EXTERNAL        gridInqYstdname
 
-!                     gridInqYunits
-!                                    (INTEGER         gridID,
-!                                     CHARACTER*(*)   yunits)
-      EXTERNAL        gridInqYunits
-
 !                     gridDefPrec
 !                                    (INTEGER         gridID,
 !                                     INTEGER         prec)
@@ -1518,81 +1548,81 @@
 !                                    (INTEGER         gridID)
       EXTERNAL        gridIsRotated
 
-      DOUBLEPRECISION gridInqXpole
-!                                    (INTEGER         gridID)
-      EXTERNAL        gridInqXpole
-
 !                     gridDefXpole
 !                                    (INTEGER         gridID,
 !                                     DOUBLEPRECISION xpole)
       EXTERNAL        gridDefXpole
 
-      DOUBLEPRECISION gridInqYpole
+      DOUBLEPRECISION gridInqXpole
 !                                    (INTEGER         gridID)
-      EXTERNAL        gridInqYpole
+      EXTERNAL        gridInqXpole
 
 !                     gridDefYpole
 !                                    (INTEGER         gridID,
 !                                     DOUBLEPRECISION ypole)
       EXTERNAL        gridDefYpole
 
-      DOUBLEPRECISION gridInqAngle
+      DOUBLEPRECISION gridInqYpole
 !                                    (INTEGER         gridID)
-      EXTERNAL        gridInqAngle
+      EXTERNAL        gridInqYpole
 
 !                     gridDefAngle
 !                                    (INTEGER         gridID,
 !                                     DOUBLEPRECISION angle)
       EXTERNAL        gridDefAngle
 
-!                     gridDefTrunc
-!                                    (INTEGER         gridID,
-!                                     INTEGER         trunc)
-      EXTERNAL        gridDefTrunc
+      DOUBLEPRECISION gridInqAngle
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqAngle
 
       INTEGER         gridInqTrunc
 !                                    (INTEGER         gridID)
       EXTERNAL        gridInqTrunc
 
+!                     gridDefTrunc
+!                                    (INTEGER         gridID,
+!                                     INTEGER         trunc)
+      EXTERNAL        gridDefTrunc
+
 !
 !  Hexagonal GME grid
 !
-      INTEGER         gridInqGMEnd
-!                                    (INTEGER         gridID)
-      EXTERNAL        gridInqGMEnd
-
 !                     gridDefGMEnd
 !                                    (INTEGER         gridID,
 !                                     INTEGER         nd)
       EXTERNAL        gridDefGMEnd
 
-      INTEGER         gridInqGMEni
+      INTEGER         gridInqGMEnd
 !                                    (INTEGER         gridID)
-      EXTERNAL        gridInqGMEni
+      EXTERNAL        gridInqGMEnd
 
 !                     gridDefGMEni
 !                                    (INTEGER         gridID,
 !                                     INTEGER         ni)
       EXTERNAL        gridDefGMEni
 
-      INTEGER         gridInqGMEni2
+      INTEGER         gridInqGMEni
 !                                    (INTEGER         gridID)
-      EXTERNAL        gridInqGMEni2
+      EXTERNAL        gridInqGMEni
 
 !                     gridDefGMEni2
 !                                    (INTEGER         gridID,
 !                                     INTEGER         ni2)
       EXTERNAL        gridDefGMEni2
 
-      INTEGER         gridInqGMEni3
+      INTEGER         gridInqGMEni2
 !                                    (INTEGER         gridID)
-      EXTERNAL        gridInqGMEni3
+      EXTERNAL        gridInqGMEni2
 
 !                     gridDefGMEni3
 !                                    (INTEGER         gridID,
 !                                     INTEGER         ni3)
       EXTERNAL        gridDefGMEni3
 
+      INTEGER         gridInqGMEni3
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqGMEni3
+
 !
 !  Reference of an unstructured grid
 !
@@ -1861,36 +1891,36 @@
 !                                     CHARACTER*(*)   name)
       EXTERNAL        zaxisDefName
 
-!                     zaxisDefLongname
-!                                    (INTEGER         zaxisID,
-!                                     CHARACTER*(*)   longname)
-      EXTERNAL        zaxisDefLongname
-
-!                     zaxisDefUnits
-!                                    (INTEGER         zaxisID,
-!                                     CHARACTER*(*)   units)
-      EXTERNAL        zaxisDefUnits
-
 !                     zaxisInqName
 !                                    (INTEGER         zaxisID,
 !                                     CHARACTER*(*)   name)
       EXTERNAL        zaxisInqName
 
+!                     zaxisDefLongname
+!                                    (INTEGER         zaxisID,
+!                                     CHARACTER*(*)   longname)
+      EXTERNAL        zaxisDefLongname
+
 !                     zaxisInqLongname
 !                                    (INTEGER         zaxisID,
 !                                     CHARACTER*(*)   longname)
       EXTERNAL        zaxisInqLongname
 
-!                     zaxisInqStdname
+!                     zaxisDefUnits
 !                                    (INTEGER         zaxisID,
-!                                     CHARACTER*(*)   stdname)
-      EXTERNAL        zaxisInqStdname
+!                                     CHARACTER*(*)   units)
+      EXTERNAL        zaxisDefUnits
 
 !                     zaxisInqUnits
 !                                    (INTEGER         zaxisID,
 !                                     CHARACTER*(*)   units)
       EXTERNAL        zaxisInqUnits
 
+!                     zaxisInqStdname
+!                                    (INTEGER         zaxisID,
+!                                     CHARACTER*(*)   stdname)
+      EXTERNAL        zaxisInqStdname
+
 !                     zaxisDefPrec
 !                                    (INTEGER         zaxisID,
 !                                     INTEGER         prec)
@@ -1933,46 +1963,46 @@
 !                                    (INTEGER         zaxisID)
       EXTERNAL        zaxisInqVctSize
 
-      INTEGER         zaxisInqLbounds
+!                     zaxisDefLbounds
 !                                    (INTEGER         zaxisID,
 !                                     DOUBLEPRECISION lbounds_vec)
-      EXTERNAL        zaxisInqLbounds
-
-      INTEGER         zaxisInqUbounds
-!                                    (INTEGER         zaxisID,
-!                                     DOUBLEPRECISION ubounds_vec)
-      EXTERNAL        zaxisInqUbounds
+      EXTERNAL        zaxisDefLbounds
 
-      INTEGER         zaxisInqWeights
+      INTEGER         zaxisInqLbounds
 !                                    (INTEGER         zaxisID,
-!                                     DOUBLEPRECISION weights_vec)
-      EXTERNAL        zaxisInqWeights
+!                                     DOUBLEPRECISION lbounds_vec)
+      EXTERNAL        zaxisInqLbounds
 
       DOUBLEPRECISION zaxisInqLbound
 !                                    (INTEGER         zaxisID,
 !                                     INTEGER         index)
       EXTERNAL        zaxisInqLbound
 
-      DOUBLEPRECISION zaxisInqUbound
+!                     zaxisDefUbounds
 !                                    (INTEGER         zaxisID,
-!                                     INTEGER         index)
-      EXTERNAL        zaxisInqUbound
+!                                     DOUBLEPRECISION ubounds_vec)
+      EXTERNAL        zaxisDefUbounds
 
-!                     zaxisDefLbounds
+      INTEGER         zaxisInqUbounds
 !                                    (INTEGER         zaxisID,
-!                                     DOUBLEPRECISION lbounds_vec)
-      EXTERNAL        zaxisDefLbounds
+!                                     DOUBLEPRECISION ubounds_vec)
+      EXTERNAL        zaxisInqUbounds
 
-!                     zaxisDefUbounds
+      DOUBLEPRECISION zaxisInqUbound
 !                                    (INTEGER         zaxisID,
-!                                     DOUBLEPRECISION ubounds_vec)
-      EXTERNAL        zaxisDefUbounds
+!                                     INTEGER         index)
+      EXTERNAL        zaxisInqUbound
 
 !                     zaxisDefWeights
 !                                    (INTEGER         zaxisID,
 !                                     DOUBLEPRECISION weights_vec)
       EXTERNAL        zaxisDefWeights
 
+      INTEGER         zaxisInqWeights
+!                                    (INTEGER         zaxisID,
+!                                     DOUBLEPRECISION weights_vec)
+      EXTERNAL        zaxisInqWeights
+
 !                     zaxisChangeType
 !                                    (INTEGER         zaxisID,
 !                                     INTEGER         zaxistype)
@@ -2013,6 +2043,14 @@
 !                                     INTEGER         time)
       EXTERNAL        taxisDefVtime
 
+      INTEGER         taxisInqVdate
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqVdate
+
+      INTEGER         taxisInqVtime
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqVtime
+
 !                     taxisDefRdate
 !                                    (INTEGER         taxisID,
 !                                     INTEGER         date)
@@ -2023,6 +2061,14 @@
 !                                     INTEGER         time)
       EXTERNAL        taxisDefRtime
 
+      INTEGER         taxisInqRdate
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqRdate
+
+      INTEGER         taxisInqRtime
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqRtime
+
 !                     taxisDefFdate
 !                                    (INTEGER         taxisID,
 !                                     INTEGER         date)
@@ -2033,6 +2079,14 @@
 !                                     INTEGER         time)
       EXTERNAL        taxisDefFtime
 
+      INTEGER         taxisInqFdate
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqFdate
+
+      INTEGER         taxisInqFtime
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqFtime
+
       INTEGER         taxisHasBounds
 !                                    (INTEGER         taxisID)
       EXTERNAL        taxisHasBounds
@@ -2070,51 +2124,45 @@
 !                                     INTEGER         calendar)
       EXTERNAL        taxisDefCalendar
 
+      INTEGER         taxisInqCalendar
+!                                    (INTEGER         taxisID)
+      EXTERNAL        taxisInqCalendar
+
 !                     taxisDefTunit
 !                                    (INTEGER         taxisID,
 !                                     INTEGER         tunit)
       EXTERNAL        taxisDefTunit
 
-!                     taxisDefNumavg
-!                                    (INTEGER         taxisID,
-!                                     INTEGER         numavg)
-      EXTERNAL        taxisDefNumavg
-
-      INTEGER         taxisInqType
-!                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqType
-
-      INTEGER         taxisInqVdate
+      INTEGER         taxisInqTunit
 !                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqVdate
+      EXTERNAL        taxisInqTunit
 
-      INTEGER         taxisInqVtime
-!                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqVtime
+!                     taxisDefForecastTunit
+!                                    (INTEGER         taxisID,
+!                                     INTEGER         tunit)
+      EXTERNAL        taxisDefForecastTunit
 
-      INTEGER         taxisInqRdate
+      INTEGER         taxisInqForecastTunit
 !                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqRdate
+      EXTERNAL        taxisInqForecastTunit
 
-      INTEGER         taxisInqRtime
-!                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqRtime
-
-      INTEGER         taxisInqFdate
-!                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqFdate
+!                     taxisDefForecastPeriod
+!                                    (INTEGER         taxisID,
+!                                     DOUBLEPRECISION fc_period)
+      EXTERNAL        taxisDefForecastPeriod
 
-      INTEGER         taxisInqFtime
+      DOUBLEPRECISION taxisInqForecastPeriod
 !                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqFtime
+      EXTERNAL        taxisInqForecastPeriod
 
-      INTEGER         taxisInqCalendar
-!                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqCalendar
+!                     taxisDefNumavg
+!                                    (INTEGER         taxisID,
+!                                     INTEGER         numavg)
+      EXTERNAL        taxisDefNumavg
 
-      INTEGER         taxisInqTunit
+      INTEGER         taxisInqType
 !                                    (INTEGER         taxisID)
-      EXTERNAL        taxisInqTunit
+      EXTERNAL        taxisInqType
 
       INTEGER         taxisInqNumavg
 !                                    (INTEGER         taxisID)
@@ -2304,3 +2352,9 @@
 !                                     CHARACTER*(*)   history)
       EXTERNAL        streamInqHistoryString
 
+!                     gribapiLibraryVersion
+!                                    (INTEGER         major_version,
+!                                     INTEGER         minor_version,
+!                                     INTEGER         revision_version)
+      EXTERNAL        gribapiLibraryVersion
+
diff --git a/libcdi/src/cdiFortran.c b/libcdi/src/cdiFortran.c
index b469d10..ad1767a 100644
--- a/libcdi/src/cdiFortran.c
+++ b/libcdi/src/cdiFortran.c
@@ -100,20 +100,20 @@ FCALLSCSUB1 (streamClose, STREAMCLOSE, streamclose, INT)
 FCALLSCSUB1 (streamSync, STREAMSYNC, streamsync, INT)
 FCALLSCSUB2 (streamDefVlist, STREAMDEFVLIST, streamdefvlist, INT, INT)
 FCALLSCFUN1 (INT, streamInqVlist, STREAMINQVLIST, streaminqvlist, INT)
+
+/*  PIO:  */
+
 FCALLSCFUN1 (INT, streamInqVlistIDorig, STREAMINQVLISTIDORIG, streaminqvlistidorig, INT)
 FCALLSCFUN1 (INT, streamInqFiletype, STREAMINQFILETYPE, streaminqfiletype, INT)
 FCALLSCSUB2 (streamDefByteorder, STREAMDEFBYTEORDER, streamdefbyteorder, INT, INT)
 FCALLSCFUN1 (INT, streamInqByteorder, STREAMINQBYTEORDER, streaminqbyteorder, INT)
 FCALLSCSUB2 (streamDefCompType, STREAMDEFCOMPTYPE, streamdefcomptype, INT, INT)
-FCALLSCSUB2 (streamDefCompLevel, STREAMDEFCOMPLEVEL, streamdefcomplevel, INT, INT)
 FCALLSCFUN1 (INT, streamInqCompType, STREAMINQCOMPTYPE, streaminqcomptype, INT)
+FCALLSCSUB2 (streamDefCompLevel, STREAMDEFCOMPLEVEL, streamdefcomplevel, INT, INT)
 FCALLSCFUN1 (INT, streamInqCompLevel, STREAMINQCOMPLEVEL, streaminqcomplevel, INT)
 FCALLSCFUN2 (INT, streamDefTimestep, STREAMDEFTIMESTEP, streamdeftimestep, INT, INT)
-
-/*  query currently set timestep id  */
-
-FCALLSCFUN1 (INT, streamInqCurTimestepID, STREAMINQCURTIMESTEPID, streaminqcurtimestepid, INT)
 FCALLSCFUN2 (INT, streamInqTimestep, STREAMINQTIMESTEP, streaminqtimestep, INT, INT)
+FCALLSCFUN1 (INT, streamInqCurTimestepID, STREAMINQCURTIMESTEPID, streaminqcurtimestepid, INT)
 FCALLSCFUN1 (STRING, streamFilename, STREAMFILENAME, streamfilename, INT)
 FCALLSCFUN1 (STRING, streamFilesuffix, STREAMFILESUFFIX, streamfilesuffix, INT)
 FCALLSCFUN1 (INT, streamNtsteps, STREAMNTSTEPS, streamntsteps, INT)
@@ -121,21 +121,23 @@ FCALLSCFUN1 (INT, streamInqNvars, STREAMINQNVARS, streaminqnvars, INT)
 
 /*  STREAM var I/O routines  */
 
-FCALLSCSUB4 (streamReadVar, STREAMREADVAR, streamreadvar, INT, INT, PDOUBLE, PINT)
 FCALLSCSUB4 (streamWriteVar, STREAMWRITEVAR, streamwritevar, INT, INT, PDOUBLE, INT)
 FCALLSCSUB4 (streamWriteVarF, STREAMWRITEVARF, streamwritevarf, INT, INT, PFLOAT, INT)
-FCALLSCSUB5 (streamReadVarSlice, STREAMREADVARSLICE, streamreadvarslice, INT, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB4 (streamReadVar, STREAMREADVAR, streamreadvar, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB4 (streamReadVarF, STREAMREADVARF, streamreadvarf, INT, INT, PFLOAT, PINT)
 FCALLSCSUB5 (streamWriteVarSlice, STREAMWRITEVARSLICE, streamwritevarslice, INT, INT, INT, PDOUBLE, INT)
 FCALLSCSUB5 (streamWriteVarSliceF, STREAMWRITEVARSLICEF, streamwritevarslicef, INT, INT, INT, PFLOAT, INT)
+FCALLSCSUB5 (streamReadVarSlice, STREAMREADVARSLICE, streamreadvarslice, INT, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB5 (streamReadVarSliceF, STREAMREADVARSLICEF, streamreadvarslicef, INT, INT, INT, PFLOAT, PINT)
 FCALLSCSUB5 (streamWriteVarChunk, STREAMWRITEVARCHUNK, streamwritevarchunk, INT, INT, INTVV, PDOUBLE, INT)
 
 /*  STREAM record I/O routines  */
 
-FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
 FCALLSCSUB3 (streamDefRecord, STREAMDEFRECORD, streamdefrecord, INT, INT, INT)
-FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, PDOUBLE, PINT)
+FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
 FCALLSCSUB3 (streamWriteRecord, STREAMWRITERECORD, streamwriterecord, INT, PDOUBLE, INT)
 FCALLSCSUB3 (streamWriteRecordF, STREAMWRITERECORDF, streamwriterecordf, INT, PFLOAT, INT)
+FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, PDOUBLE, PINT)
 FCALLSCSUB2 (streamCopyRecord, STREAMCOPYRECORD, streamcopyrecord, INT, INT)
 
 /*  VLIST routines  */
@@ -186,8 +188,8 @@ FCALLSCFUN2 (INT, vlistInqVarZaxis, VLISTINQVARZAXIS, vlistinqvarzaxis, INT, INT
 /*  used in MPIOM  */
 
 FCALLSCFUN2 (INT, vlistInqVarID, VLISTINQVARID, vlistinqvarid, INT, INT)
-FCALLSCFUN2 (INT, vlistInqVarTsteptype, VLISTINQVARTSTEPTYPE, vlistinqvartsteptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarTsteptype, VLISTDEFVARTSTEPTYPE, vlistdefvartsteptype, INT, INT, INT)
+FCALLSCFUN2 (INT, vlistInqVarTsteptype, VLISTINQVARTSTEPTYPE, vlistinqvartsteptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarCompType, VLISTDEFVARCOMPTYPE, vlistdefvarcomptype, INT, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarCompType, VLISTINQVARCOMPTYPE, vlistinqvarcomptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarCompLevel, VLISTDEFVARCOMPLEVEL, vlistdefvarcomplevel, INT, INT, INT)
@@ -231,6 +233,8 @@ FCALLSCSUB3 (vlistDefVarTimaccu, VLISTDEFVARTIMACCU, vlistdefvartimaccu, INT, IN
 FCALLSCFUN2 (INT, vlistInqVarTimaccu, VLISTINQVARTIMACCU, vlistinqvartimaccu, INT, INT)
 FCALLSCSUB3 (vlistDefVarTypeOfGeneratingProcess, VLISTDEFVARTYPEOFGENERATINGPROCESS, vlistdefvartypeofgeneratingprocess, INT, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarTypeOfGeneratingProcess, VLISTINQVARTYPEOFGENERATINGPROCESS, vlistinqvartypeofgeneratingprocess, INT, INT)
+FCALLSCSUB3 (vlistDefVarProductDefinitionTemplate, VLISTDEFVARPRODUCTDEFINITIONTEMPLATE, vlistdefvarproductdefinitiontemplate, INT, INT, INT)
+FCALLSCFUN2 (INT, vlistInqVarProductDefinitionTemplate, VLISTINQVARPRODUCTDEFINITIONTEMPLATE, vlistinqvarproductdefinitiontemplate, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarSize, VLISTINQVARSIZE, vlistinqvarsize, INT, INT)
 FCALLSCSUB4 (vlistDefIndex, VLISTDEFINDEX, vlistdefindex, INT, INT, INT, INT)
 FCALLSCFUN3 (INT, vlistInqIndex, VLISTINQINDEX, vlistinqindex, INT, INT, INT)
@@ -291,19 +295,19 @@ FCALLSCFUN2 (INT, gridInqXvals, GRIDINQXVALS, gridinqxvals, INT, PDOUBLE)
 FCALLSCSUB2 (gridDefYvals, GRIDDEFYVALS, griddefyvals, INT, PDOUBLE)
 FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, PDOUBLE)
 FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING)
+FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING)
+FCALLSCSUB2 (gridInqXlongname, GRIDINQXLONGNAME, gridinqxlongname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXunits, GRIDDEFXUNITS, griddefxunits, INT, STRING)
+FCALLSCSUB2 (gridInqXunits, GRIDINQXUNITS, gridinqxunits, INT, PSTRING)
 FCALLSCSUB2 (gridDefYname, GRIDDEFYNAME, griddefyname, INT, STRING)
+FCALLSCSUB2 (gridInqYname, GRIDINQYNAME, gridinqyname, INT, PSTRING)
 FCALLSCSUB2 (gridDefYlongname, GRIDDEFYLONGNAME, griddefylongname, INT, STRING)
+FCALLSCSUB2 (gridInqYlongname, GRIDINQYLONGNAME, gridinqylongname, INT, PSTRING)
 FCALLSCSUB2 (gridDefYunits, GRIDDEFYUNITS, griddefyunits, INT, STRING)
-FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
-FCALLSCSUB2 (gridInqXlongname, GRIDINQXLONGNAME, gridinqxlongname, INT, PSTRING)
+FCALLSCSUB2 (gridInqYunits, GRIDINQYUNITS, gridinqyunits, INT, PSTRING)
 FCALLSCSUB2 (gridInqXstdname, GRIDINQXSTDNAME, gridinqxstdname, INT, PSTRING)
-FCALLSCSUB2 (gridInqXunits, GRIDINQXUNITS, gridinqxunits, INT, PSTRING)
-FCALLSCSUB2 (gridInqYname, GRIDINQYNAME, gridinqyname, INT, PSTRING)
-FCALLSCSUB2 (gridInqYlongname, GRIDINQYLONGNAME, gridinqylongname, INT, PSTRING)
 FCALLSCSUB2 (gridInqYstdname, GRIDINQYSTDNAME, gridinqystdname, INT, PSTRING)
-FCALLSCSUB2 (gridInqYunits, GRIDINQYUNITS, gridinqyunits, INT, PSTRING)
 FCALLSCSUB2 (gridDefPrec, GRIDDEFPREC, griddefprec, INT, INT)
 FCALLSCFUN1 (INT, gridInqPrec, GRIDINQPREC, gridinqprec, INT)
 FCALLSCFUN2 (DOUBLE, gridInqXval, GRIDINQXVAL, gridinqxval, INT, INT)
@@ -312,25 +316,25 @@ FCALLSCFUN1 (DOUBLE, gridInqXinc, GRIDINQXINC, gridinqxinc, INT)
 FCALLSCFUN1 (DOUBLE, gridInqYinc, GRIDINQYINC, gridinqyinc, INT)
 FCALLSCFUN1 (INT, gridIsCircular, GRIDISCIRCULAR, gridiscircular, INT)
 FCALLSCFUN1 (INT, gridIsRotated, GRIDISROTATED, gridisrotated, INT)
-FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT)
 FCALLSCSUB2 (gridDefXpole, GRIDDEFXPOLE, griddefxpole, INT, DOUBLE)
-FCALLSCFUN1 (DOUBLE, gridInqYpole, GRIDINQYPOLE, gridinqypole, INT)
+FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT)
 FCALLSCSUB2 (gridDefYpole, GRIDDEFYPOLE, griddefypole, INT, DOUBLE)
-FCALLSCFUN1 (DOUBLE, gridInqAngle, GRIDINQANGLE, gridinqangle, INT)
+FCALLSCFUN1 (DOUBLE, gridInqYpole, GRIDINQYPOLE, gridinqypole, INT)
 FCALLSCSUB2 (gridDefAngle, GRIDDEFANGLE, griddefangle, INT, DOUBLE)
-FCALLSCSUB2 (gridDefTrunc, GRIDDEFTRUNC, griddeftrunc, INT, INT)
+FCALLSCFUN1 (DOUBLE, gridInqAngle, GRIDINQANGLE, gridinqangle, INT)
 FCALLSCFUN1 (INT, gridInqTrunc, GRIDINQTRUNC, gridinqtrunc, INT)
+FCALLSCSUB2 (gridDefTrunc, GRIDDEFTRUNC, griddeftrunc, INT, INT)
 
 /*  Hexagonal GME grid  */
 
-FCALLSCFUN1 (INT, gridInqGMEnd, GRIDINQGMEND, gridinqgmend, INT)
 FCALLSCSUB2 (gridDefGMEnd, GRIDDEFGMEND, griddefgmend, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni, GRIDINQGMENI, gridinqgmeni, INT)
+FCALLSCFUN1 (INT, gridInqGMEnd, GRIDINQGMEND, gridinqgmend, INT)
 FCALLSCSUB2 (gridDefGMEni, GRIDDEFGMENI, griddefgmeni, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni2, GRIDINQGMENI2, gridinqgmeni2, INT)
+FCALLSCFUN1 (INT, gridInqGMEni, GRIDINQGMENI, gridinqgmeni, INT)
 FCALLSCSUB2 (gridDefGMEni2, GRIDDEFGMENI2, griddefgmeni2, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni3, GRIDINQGMENI3, gridinqgmeni3, INT)
+FCALLSCFUN1 (INT, gridInqGMEni2, GRIDINQGMENI2, gridinqgmeni2, INT)
 FCALLSCSUB2 (gridDefGMEni3, GRIDDEFGMENI3, griddefgmeni3, INT, INT)
+FCALLSCFUN1 (INT, gridInqGMEni3, GRIDINQGMENI3, gridinqgmeni3, INT)
 
 /*  Reference of an unstructured grid  */
 
@@ -393,12 +397,12 @@ FCALLSCFUN1 (INT, zaxisInqNumber, ZAXISINQNUMBER, zaxisinqnumber, INT)
 FCALLSCSUB2 (zaxisDefUUID, ZAXISDEFUUID, zaxisdefuuid, INT, PPSTRING)
 FCALLSCSUB2 (zaxisInqUUID, ZAXISINQUUID, zaxisinquuid, INT, PPSTRING)
 FCALLSCSUB2 (zaxisDefName, ZAXISDEFNAME, zaxisdefname, INT, STRING)
-FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
-FCALLSCSUB2 (zaxisDefUnits, ZAXISDEFUNITS, zaxisdefunits, INT, STRING)
 FCALLSCSUB2 (zaxisInqName, ZAXISINQNAME, zaxisinqname, INT, PSTRING)
+FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
 FCALLSCSUB2 (zaxisInqLongname, ZAXISINQLONGNAME, zaxisinqlongname, INT, PSTRING)
-FCALLSCSUB2 (zaxisInqStdname, ZAXISINQSTDNAME, zaxisinqstdname, INT, PSTRING)
+FCALLSCSUB2 (zaxisDefUnits, ZAXISDEFUNITS, zaxisdefunits, INT, STRING)
 FCALLSCSUB2 (zaxisInqUnits, ZAXISINQUNITS, zaxisinqunits, INT, PSTRING)
+FCALLSCSUB2 (zaxisInqStdname, ZAXISINQSTDNAME, zaxisinqstdname, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefPrec, ZAXISDEFPREC, zaxisdefprec, INT, INT)
 FCALLSCFUN1 (INT, zaxisInqPrec, ZAXISINQPREC, zaxisinqprec, INT)
 FCALLSCSUB2 (zaxisDefPositive, ZAXISDEFPOSITIVE, zaxisdefpositive, INT, INT)
@@ -408,14 +412,14 @@ FCALLSCFUN1 (INT, zaxisInqLtype, ZAXISINQLTYPE, zaxisinqltype, INT)
 FCALLSCSUB3 (zaxisDefVct, ZAXISDEFVCT, zaxisdefvct, INT, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisInqVct, ZAXISINQVCT, zaxisinqvct, INT, PDOUBLE)
 FCALLSCFUN1 (INT, zaxisInqVctSize, ZAXISINQVCTSIZE, zaxisinqvctsize, INT)
+FCALLSCSUB2 (zaxisDefLbounds, ZAXISDEFLBOUNDS, zaxisdeflbounds, INT, PDOUBLE)
 FCALLSCFUN2 (INT, zaxisInqLbounds, ZAXISINQLBOUNDS, zaxisinqlbounds, INT, PDOUBLE)
-FCALLSCFUN2 (INT, zaxisInqUbounds, ZAXISINQUBOUNDS, zaxisinqubounds, INT, PDOUBLE)
-FCALLSCFUN2 (INT, zaxisInqWeights, ZAXISINQWEIGHTS, zaxisinqweights, INT, PDOUBLE)
 FCALLSCFUN2 (DOUBLE, zaxisInqLbound, ZAXISINQLBOUND, zaxisinqlbound, INT, INT)
-FCALLSCFUN2 (DOUBLE, zaxisInqUbound, ZAXISINQUBOUND, zaxisinqubound, INT, INT)
-FCALLSCSUB2 (zaxisDefLbounds, ZAXISDEFLBOUNDS, zaxisdeflbounds, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisDefUbounds, ZAXISDEFUBOUNDS, zaxisdefubounds, INT, PDOUBLE)
+FCALLSCFUN2 (INT, zaxisInqUbounds, ZAXISINQUBOUNDS, zaxisinqubounds, INT, PDOUBLE)
+FCALLSCFUN2 (DOUBLE, zaxisInqUbound, ZAXISINQUBOUND, zaxisinqubound, INT, INT)
 FCALLSCSUB2 (zaxisDefWeights, ZAXISDEFWEIGHTS, zaxisdefweights, INT, PDOUBLE)
+FCALLSCFUN2 (INT, zaxisInqWeights, ZAXISINQWEIGHTS, zaxisinqweights, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisChangeType, ZAXISCHANGETYPE, zaxischangetype, INT, INT)
 
 /*  TAXIS routines  */
@@ -427,10 +431,16 @@ FCALLSCSUB2 (taxisCopyTimestep, TAXISCOPYTIMESTEP, taxiscopytimestep, INT, INT)
 FCALLSCSUB2 (taxisDefType, TAXISDEFTYPE, taxisdeftype, INT, INT)
 FCALLSCSUB2 (taxisDefVdate, TAXISDEFVDATE, taxisdefvdate, INT, INT)
 FCALLSCSUB2 (taxisDefVtime, TAXISDEFVTIME, taxisdefvtime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqVdate, TAXISINQVDATE, taxisinqvdate, INT)
+FCALLSCFUN1 (INT, taxisInqVtime, TAXISINQVTIME, taxisinqvtime, INT)
 FCALLSCSUB2 (taxisDefRdate, TAXISDEFRDATE, taxisdefrdate, INT, INT)
 FCALLSCSUB2 (taxisDefRtime, TAXISDEFRTIME, taxisdefrtime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqRdate, TAXISINQRDATE, taxisinqrdate, INT)
+FCALLSCFUN1 (INT, taxisInqRtime, TAXISINQRTIME, taxisinqrtime, INT)
 FCALLSCSUB2 (taxisDefFdate, TAXISDEFFDATE, taxisdeffdate, INT, INT)
 FCALLSCSUB2 (taxisDefFtime, TAXISDEFFTIME, taxisdefftime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqFdate, TAXISINQFDATE, taxisinqfdate, INT)
+FCALLSCFUN1 (INT, taxisInqFtime, TAXISINQFTIME, taxisinqftime, INT)
 FCALLSCFUN1 (INT, taxisHasBounds, TAXISHASBOUNDS, taxishasbounds, INT)
 FCALLSCSUB1 (taxisDeleteBounds, TAXISDELETEBOUNDS, taxisdeletebounds, INT)
 FCALLSCSUB3 (taxisDefVdateBounds, TAXISDEFVDATEBOUNDS, taxisdefvdatebounds, INT, INT, INT)
@@ -438,17 +448,15 @@ FCALLSCSUB3 (taxisDefVtimeBounds, TAXISDEFVTIMEBOUNDS, taxisdefvtimebounds, INT,
 FCALLSCSUB3 (taxisInqVdateBounds, TAXISINQVDATEBOUNDS, taxisinqvdatebounds, INT, PINT, PINT)
 FCALLSCSUB3 (taxisInqVtimeBounds, TAXISINQVTIMEBOUNDS, taxisinqvtimebounds, INT, PINT, PINT)
 FCALLSCSUB2 (taxisDefCalendar, TAXISDEFCALENDAR, taxisdefcalendar, INT, INT)
+FCALLSCFUN1 (INT, taxisInqCalendar, TAXISINQCALENDAR, taxisinqcalendar, INT)
 FCALLSCSUB2 (taxisDefTunit, TAXISDEFTUNIT, taxisdeftunit, INT, INT)
+FCALLSCFUN1 (INT, taxisInqTunit, TAXISINQTUNIT, taxisinqtunit, INT)
+FCALLSCSUB2 (taxisDefForecastTunit, TAXISDEFFORECASTTUNIT, taxisdefforecasttunit, INT, INT)
+FCALLSCFUN1 (INT, taxisInqForecastTunit, TAXISINQFORECASTTUNIT, taxisinqforecasttunit, INT)
+FCALLSCSUB2 (taxisDefForecastPeriod, TAXISDEFFORECASTPERIOD, taxisdefforecastperiod, INT, DOUBLE)
+FCALLSCFUN1 (DOUBLE, taxisInqForecastPeriod, TAXISINQFORECASTPERIOD, taxisinqforecastperiod, INT)
 FCALLSCSUB2 (taxisDefNumavg, TAXISDEFNUMAVG, taxisdefnumavg, INT, INT)
 FCALLSCFUN1 (INT, taxisInqType, TAXISINQTYPE, taxisinqtype, INT)
-FCALLSCFUN1 (INT, taxisInqVdate, TAXISINQVDATE, taxisinqvdate, INT)
-FCALLSCFUN1 (INT, taxisInqVtime, TAXISINQVTIME, taxisinqvtime, INT)
-FCALLSCFUN1 (INT, taxisInqRdate, TAXISINQRDATE, taxisinqrdate, INT)
-FCALLSCFUN1 (INT, taxisInqRtime, TAXISINQRTIME, taxisinqrtime, INT)
-FCALLSCFUN1 (INT, taxisInqFdate, TAXISINQFDATE, taxisinqfdate, INT)
-FCALLSCFUN1 (INT, taxisInqFtime, TAXISINQFTIME, taxisinqftime, INT)
-FCALLSCFUN1 (INT, taxisInqCalendar, TAXISINQCALENDAR, taxisinqcalendar, INT)
-FCALLSCFUN1 (INT, taxisInqTunit, TAXISINQTUNIT, taxisinqtunit, INT)
 FCALLSCFUN1 (INT, taxisInqNumavg, TAXISINQNUMAVG, taxisinqnumavg, INT)
 FCALLSCFUN1 (STRING, tunitNamePtr, TUNITNAMEPTR, tunitnameptr, INT)
 
@@ -496,5 +504,6 @@ FCALLSCFUN2 (STRING, tableInqParUnitsPtr, TABLEINQPARUNITSPTR, tableinqparunitsp
 FCALLSCSUB3 (streamDefHistory, STREAMDEFHISTORY, streamdefhistory, INT, INT, STRING)
 FCALLSCFUN1 (INT, streamInqHistorySize, STREAMINQHISTORYSIZE, streaminqhistorysize, INT)
 FCALLSCSUB2 (streamInqHistoryString, STREAMINQHISTORYSTRING, streaminqhistorystring, INT, PSTRING)
+FCALLSCSUB3 (gribapiLibraryVersion, GRIBAPILIBRARYVERSION, gribapilibraryversion, PINT, PINT, PINT)
 
 #endif
diff --git a/libcdi/src/cdi_cksum.c b/libcdi/src/cdi_cksum.c
index 775031a..58be0a3 100644
--- a/libcdi/src/cdi_cksum.c
+++ b/libcdi/src/cdi_cksum.c
@@ -1,4 +1,9 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <inttypes.h>
+#include <sys/types.h>
 #include <stdlib.h>
 
 #include "cdi_cksum.h"
@@ -11,7 +16,7 @@ uint32_t cdiCheckSum(int type, int count, void *buffer)
   uint32_t s = 0U;
   xassert(count >= 0);
   size_t elemSize = (size_t)serializeGetSizeInCore(1, type, NULL);
-  memcrc_r_eswap(&s, (const unsigned char*) buffer, count, elemSize);
-  s = memcrc_finish(&s, elemSize * (size_t)count);
+  memcrc_r_eswap(&s, (const unsigned char *)buffer, (size_t)count, elemSize);
+  s = memcrc_finish(&s, (off_t)(elemSize * (size_t)count));
   return s;
 }
diff --git a/libcdi/src/cdi_int.c b/libcdi/src/cdi_int.c
index f0231b1..3b9e462 100644
--- a/libcdi/src/cdi_int.c
+++ b/libcdi/src/cdi_int.c
@@ -5,19 +5,17 @@
 #include <stdarg.h>
 #include <ctype.h>
 
-#include "dmemory.h"
-
+#include "cdf.h"
 #include "cdi.h"
-#include "cdi_cksum.h"
 #include "cdi_int.h"
+#include "dmemory.h"
+#include "file.h"
 #include "gribapi.h"
 #ifdef HAVE_LIBNETCDF
 #include "stream_cdf.h"
 #endif
 #include "namespace.h"
-#include "serialize.h"
 #include "resource_handle.h"
-#include "resource_unpack.h"
 
 #if  defined  (HAVE_LIBCGRIBEX)
 #include "cgribex.h"
@@ -66,32 +64,14 @@ const char Filetypes[][9] = {
 
 int CDI_Debug   = 0;    /* If set to 1, debugging           */
 
-static int  STREAM_Debug = 0;   /* If set to 1, debugging */
-
 int cdiGribApiDebug     = 0;
 int cdiDefaultLeveltype = -1;
-static int cdiDataUnreduced = 0;
-static int cdiSortName = 0;
-static int cdiHaveMissval = 0;
-
-
-static int    streamCompareP ( void * streamptr1, void * streamptr2 );
-static void   streamDestroyP ( void * streamptr );
-static void   streamPrintP   ( void * streamptr, FILE * fp );
-static int    streamGetPackSize ( void * streamptr, void *context);
-static void   streamPack        ( void * streamptr, void * buff, int size, int * position, void *context );
-static int    streamTxCode      ( void );
-
-const resOps streamOps = {
-  streamCompareP,
-  streamDestroyP,
-  streamPrintP,
-  streamGetPackSize,
-  streamPack,
-  streamTxCode
-};
+int cdiDataUnreduced = 0;
+int cdiSortName = 0;
+int cdiHaveMissval = 0;
+
 
-long cdiGetenvInt(char *envName)
+static long cdiGetenvInt(char *envName)
 {
   char *envString;
   long envValue = -1;
@@ -131,6 +111,126 @@ long cdiGetenvInt(char *envName)
   return (envValue);
 }
 
+static void
+cdiPrintDefaults(void)
+{
+  fprintf(stderr, "default instID     :  %d\n"
+          "default modelID    :  %d\n"
+          "default tableID    :  %d\n"
+          "default missval    :  %g\n", cdiDefaultInstID,
+          cdiDefaultModelID, cdiDefaultTableID, cdiDefaultMissval);
+}
+
+void cdiPrintVersion(void)
+{
+  fprintf(stderr, "     CDI library version : %s\n", cdiLibraryVersion());
+#if  defined  (HAVE_LIBCGRIBEX)
+  fprintf(stderr, " CGRIBEX library version : %s\n", cgribexLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBGRIB_API)
+  fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersionString());
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+  fprintf(stderr, "  netCDF library version : %s\n", cdfLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBHDF5)
+  fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBSERVICE)
+  fprintf(stderr, " SERVICE library version : %s\n", srvLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+  fprintf(stderr, "   EXTRA library version : %s\n", extLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBIEG)
+  fprintf(stderr, "     IEG library version : %s\n", iegLibraryVersion());
+#endif
+  fprintf(stderr, "    FILE library version : %s\n", fileLibraryVersion());
+}
+
+void cdiDebug(int level)
+{
+  if ( level == 1 || (level &  2) ) CDI_Debug = 1;
+
+  if ( CDI_Debug ) Message("debug level %d", level);
+
+  if ( level == 1 || (level &  4) ) memDebug(1);
+
+  if ( level == 1 || (level &  8) ) fileDebug(1);
+
+  if ( level == 1 || (level & 16) )
+    {
+#if  defined  (HAVE_LIBGRIB)
+      gribSetDebug(1);
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+      cdfDebug(1);
+#endif
+#if  defined  (HAVE_LIBSERVICE)
+      srvDebug(1);
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+      extDebug(1);
+#endif
+#if  defined  (HAVE_LIBIEG)
+      iegDebug(1);
+#endif
+    }
+
+  if ( CDI_Debug )
+    {
+      cdiPrintDefaults();
+      cdiPrintDatatypes();
+    }
+}
+
+
+int cdiHaveFiletype(int filetype)
+{
+  int status = 0;
+
+  switch (filetype)
+    {
+#if  defined  (HAVE_LIBSERVICE)
+    case FILETYPE_SRV:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+    case FILETYPE_EXT:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBIEG)
+    case FILETYPE_IEG:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBGRIB)
+#if  defined  (HAVE_LIBGRIB_API) || defined  (HAVE_LIBCGRIBEX)
+    case FILETYPE_GRB:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBGRIB_API)
+    case FILETYPE_GRB2: { status = 1; break; }
+#endif
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+    case FILETYPE_NC:   { status = 1; break; }
+#if  defined  (HAVE_NETCDF2)
+    case FILETYPE_NC2:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_NETCDF4)
+    case FILETYPE_NC4:  { status = 1; break; }
+    case FILETYPE_NC4C: { status = 1; break; }
+#endif
+#endif
+    default: { status = 0; break; }
+    }
+
+  return (status);
+}
+
+void cdiDefTableID(int tableID)
+{
+  cdiDefaultTableID = tableID;
+  int modelID = cdiDefaultModelID = tableInqModel(tableID);
+  cdiDefaultInstID = modelInqInstitut(modelID);
+}
+
 static
 void cdiSetChunk(const char *chunkAlgo)
 {
@@ -271,9 +371,6 @@ void cdiInitialize(void)
 
       envString = getenv("PARTAB_PATH");
       if ( envString ) cdiPartabPath = strdup(envString);
-
-      envString = getenv("STREAM_DEBUG");
-      if ( envString ) STREAM_Debug = atoi(envString);
     }
 }
 
@@ -292,108 +389,6 @@ const char *strfiletype(int filetype)
 }
 
 
-stream_t *stream_to_pointer(int idx)
-{
-  return ( stream_t *) reshGetVal ( idx, &streamOps );
-}
-
-static
-void streamDefaultValue ( stream_t * streamptr )
-{
-  int i;
-
-  streamptr->self              = UNDEFID;
-  streamptr->accesstype        = UNDEFID;
-  streamptr->accessmode        = 0;
-  streamptr->filetype          = UNDEFID;
-  streamptr->byteorder         = UNDEFID;
-  streamptr->fileID            = 0;
-  streamptr->dimgroupID        = UNDEFID;
-  streamptr->filemode          = 0;
-  streamptr->numvals           = 0;
-  streamptr->filename          = NULL;
-  streamptr->record            = NULL;
-  streamptr->varsAllocated     = 0;
-  streamptr->nrecs             = 0;
-  streamptr->nvars             = 0;
-  streamptr->vars              = NULL;
-  streamptr->varinit           = 0;
-  streamptr->ncmode            = 0;
-  streamptr->curTsID           = UNDEFID;
-  streamptr->rtsteps           = 0;
-  streamptr->ntsteps           = UNDEFID;
-  streamptr->numTimestep       = 0;
-  streamptr->tsteps            = NULL;
-  streamptr->tstepsTableSize   = 0;
-  streamptr->tstepsNextID      = 0;
-  streamptr->historyID         = UNDEFID;
-  streamptr->vlistID           = UNDEFID;
-  streamptr->globalatts        = 0;
-  streamptr->localatts         = 0;
-  streamptr->vct.ilev          = 0;
-  streamptr->vct.mlev          = 0;
-  streamptr->vct.ilevID        = UNDEFID;
-  streamptr->vct.mlevID        = UNDEFID;
-  streamptr->unreduced         = cdiDataUnreduced;
-  streamptr->sortname          = cdiSortName;
-  streamptr->have_missval      = cdiHaveMissval;
-  streamptr->comptype          = COMPRESS_NONE;
-  streamptr->complevel         = 0;
-
-  basetimeInit(&streamptr->basetime);
-
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i]   = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i]   = UNDEFID;
-  for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->zaxisID[i]  = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncxvarID[i] = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncyvarID[i] = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncavarID[i] = UNDEFID;
-
-  streamptr->curfile           = 0;
-  streamptr->nfiles            = 0;
-  streamptr->fnames            = NULL;
-
-  streamptr->gribContainers    = NULL;
-  streamptr->vlistIDorig       = UNDEFID;
-}
-
-
-stream_t *stream_new_entry(void)
-{
-  stream_t *streamptr;
-
-  cdiInitialize(); /* ***************** make MT version !!! */
-
-  streamptr = (stream_t *) xmalloc(sizeof(stream_t));
-  streamDefaultValue ( streamptr );
-  streamptr->self = reshPut (( void * ) streamptr, &streamOps );
-
-  return streamptr;
-}
-
-
-void stream_delete_entry(stream_t *streamptr)
-{
-  int idx;
-
-  xassert ( streamptr );
-
-  idx = streamptr->self;
-  free ( streamptr );
-  reshRemove ( idx, &streamOps );
-
-  if ( STREAM_Debug )
-    Message("Removed idx %d from stream list", idx);
-}
-
-
-void stream_check_ptr(const char *caller, stream_t *streamptr)
-{
-  if ( streamptr == NULL )
-    Errorc("stream undefined!");
-}
-
-
 int streamSize(void)
 {
   return reshCountType ( &streamOps );
@@ -427,364 +422,6 @@ double cdiInqMissval(void)
   return (cdiDefaultMissval);
 }
 
-
-void vlist_check_contents(int vlistID)
-{
-  int index, nzaxis, zaxisID;
-
-  nzaxis = vlistNzaxis(vlistID);
-
-  for ( index = 0; index < nzaxis; index++ )
-    {
-      zaxisID = vlistZaxis(vlistID, index);
-      if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
-	cdiCheckZaxis(zaxisID);
-    }
-}
-
-
-int streamInqFileID(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->fileID);
-}
-
-/* not used anymore */
-/*
-void streamDefineTaxis(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  if ( streamptr->tsteps == NULL )
-    {
-      int varID, nvars;
-      int vlistID;
-
-      vlistID = streamptr->vlistID;
-
-      nvars = vlistNvars(vlistID);
-      for ( varID = 0; varID < nvars; varID++ )
-	if ( vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT ) break;
-
-      if ( varID == nvars )
-	{
-	  int taxisID;
-
-	  taxisID = vlistInqTaxis(vlistID);
-	  if ( taxisID == CDI_UNDEFID )
-	    {
-	      taxisID = taxisCreate(TAXIS_ABSOLUTE);
-	      vlistDefTaxis(vlistID, taxisID);
-	    }
-
-	  (void) streamDefTimestep(streamID, 0);
-	}
-      else
-	Error("time axis undefined");
-    }
-}
-*/
-
-void streamDefDimgroupID(int streamID, int dimgroupID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  streamptr->dimgroupID = dimgroupID;
-}
-
-
-int streamInqDimgroupID(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->dimgroupID);
-}
-
-
-void cdiDefAccesstype(int streamID, int type)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  if ( streamptr->accesstype == UNDEFID )
-    {
-      streamptr->accesstype = type;
-    }
-  else
-    {
-      if ( streamptr->accesstype != type )
-	{
-	  if ( streamptr->accesstype == TYPE_REC )
-	    Error("Changing access type from REC to VAR not allowed!");
-	  else
-	    Error("Changing access type from VAR to REC not allowed!");
-	}
-    }
-}
-
-
-int cdiInqAccesstype(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->accesstype);
-} 
-
-
-int streamInqNvars ( int streamID )
-{
-  stream_t * streamptr;
-  streamptr = ( stream_t * ) reshGetVal ( streamID, &streamOps );
-  return ( streamptr->nvars );
-}
-
-
-int  streamCompareP ( void * streamptr1, void * streamptr2 )
-{
-  stream_t * s1 = ( stream_t * ) streamptr1;
-  stream_t * s2 = ( stream_t * ) streamptr2;
-  int differ = -1;
-  int equal  = 0;
-  int len;
-
-  xassert ( s1 );
-  xassert ( s2 );
-
-  if ( s1->filetype  != s2->filetype  ) return differ;
-  if (  namespaceAdaptKey2 ( s1->vlistIDorig ) !=
-	namespaceAdaptKey2 ( s2->vlistIDorig )) return differ;
-  if ( s1->byteorder != s2->byteorder ) return differ;
-  if ( s1->comptype  != s2->comptype  ) return differ;
-  if ( s1->complevel != s2->complevel ) return differ;
-
-  if ( s1->filename )
-    {
-      len = strlen ( s1->filename ) + 1;
-      if ( memcmp ( s1->filename, s2->filename, len ))
-	return differ;
-    }
-  else if ( s2->filename )
-    return differ;
-
-  return equal;
-}
-
-
-void streamDestroyP ( void * streamptr )
-{
-  int id;
-  stream_t * sp = ( stream_t * ) streamptr;
-
-  xassert ( sp );
-
-  id = sp->self;
-  streamClose ( id );
-}
-
-
-void streamPrintP   ( void * streamptr, FILE * fp )
-{
-  stream_t * sp = ( stream_t * ) streamptr;
-
-  if ( !sp ) return;
-
-  fprintf ( fp, "#\n");
-  fprintf ( fp, "# streamID %d\n", sp->self);
-  fprintf ( fp, "#\n");
-  fprintf ( fp, "self          = %d\n", sp->self );
-  fprintf ( fp, "accesstype    = %d\n", sp->accesstype );
-  fprintf ( fp, "accessmode    = %d\n", sp->accessmode );
-  fprintf ( fp, "filetype      = %d\n", sp->filetype );
-  fprintf ( fp, "byteorder     = %d\n", sp->byteorder );
-  fprintf ( fp, "fileID        = %d\n", sp->fileID );
-  fprintf ( fp, "dimgroupID    = %d\n", sp->dimgroupID );
-  fprintf ( fp, "filemode      = %d\n", sp->filemode );
-  fprintf ( fp, "//off_t numvals;\n" );
-  fprintf ( fp, "filename      = %s\n", sp->filename );
-  fprintf ( fp, "//Record   *record;\n" );
-  fprintf ( fp, "nrecs         = %d\n", sp->nrecs );
-  fprintf ( fp, "nvars         = %d\n", sp->nvars );
-  fprintf ( fp, "varlocked     = %d\n", sp->varlocked );
-  fprintf ( fp, "//svarinfo_t *vars;\n" );
-  fprintf ( fp, "varsAllocated = %d\n", sp->varsAllocated );
-  fprintf ( fp, "varinit       = %d\n", sp->varinit );
-  fprintf ( fp, "curTsID       = %d\n", sp->curTsID );
-  fprintf ( fp, "rtsteps       = %d\n", sp->rtsteps );
-  fprintf ( fp, "//long ntsteps;\n" );
-  fprintf ( fp, "numTimestep   = %d\n", sp->numTimestep );
-  fprintf ( fp, "//  tsteps_t   *tsteps;\n" );
-  fprintf ( fp, "tstepsTableSize= %d\n", sp->tstepsTableSize );
-  fprintf ( fp, "tstepsNextID  = %d\n", sp->tstepsNextID );
-  fprintf ( fp, "//basetime_t  basetime;\n" );
-  fprintf ( fp, "ncmode        = %d\n", sp->ncmode );
-  fprintf ( fp, "vlistID       = %d\n", sp->vlistID );
-  fprintf ( fp, "//  int       xdimID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ydimID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       zaxisID[MAX_ZAXES_PS];\n" );
-  fprintf ( fp, "//  int       ncxvarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ncyvarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ncavarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "historyID     = %d\n", sp->historyID );
-  fprintf ( fp, "globalatts    = %d\n", sp->globalatts );
-  fprintf ( fp, "localatts     = %d\n", sp->localatts );
-  fprintf ( fp, "//  VCT       vct;\n" );
-  fprintf ( fp, "unreduced     = %d\n", sp->unreduced );
-  fprintf ( fp, "sortname      = %d\n", sp->sortname );
-  fprintf ( fp, "have_missval  = %d\n", sp->have_missval );
-  fprintf ( fp, "ztype         = %d\n", sp->comptype );
-  fprintf ( fp, "zlevel        = %d\n", sp->complevel );
-  fprintf ( fp, "curfile       = %d\n", sp->curfile );
-  fprintf ( fp, "nfiles        = %d\n", sp->nfiles );
-  fprintf ( fp, "//  char    **fnames;\n" );
-  fprintf ( fp, "//  void    **gribContainers;\n" );
-  fprintf ( fp, "vlistIDorig   = %d\n", sp->vlistIDorig );
-}
-
-
-void streamGetIndexList ( int nstreams, int * streamIndexList )
-{
-  reshGetResHListOfType ( nstreams, streamIndexList, &streamOps );
-}
-
-void
-cdiStreamSetupVlist(stream_t *streamptr, int vlistID, int vlistIDorig)
-{
-  int nvars = vlistNvars(vlistID);
-  streamptr->vlistID = vlistID;
-  streamptr->vlistIDorig = vlistIDorig;
-  for (int varID = 0; varID < nvars; varID++ )
-    {
-      int gridID  = vlistInqVarGrid(vlistID, varID);
-      int zaxisID = vlistInqVarZaxis(vlistID, varID);
-      stream_new_var(streamptr, gridID, zaxisID);
-      if ( streamptr->have_missval )
-        vlistDefVarMissval(vlistID, varID,
-                           vlistInqVarMissval(vlistID, varID));
-    }
-
-  if (streamptr->filemode == 'w' )
-    {
-      if ( streamptr->filetype == FILETYPE_NC  ||
-           streamptr->filetype == FILETYPE_NC2 ||
-           streamptr->filetype == FILETYPE_NC4 ||
-           streamptr->filetype == FILETYPE_NC4C )
-        {
-#ifdef HAVE_LIBNETCDF
-          void (*myCdfDefVars)(stream_t *streamptr)
-            = (void (*)(stream_t *))
-            namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
-          myCdfDefVars(streamptr);
-#endif
-        }
-      else if ( streamptr->filetype == FILETYPE_GRB  ||
-                streamptr->filetype == FILETYPE_GRB2 )
-        {
-          gribContainersNew(streamptr);
-        }
-    }
-}
-
-
-static int
-streamTxCode(void)
-{
-  return STREAM;
-}
-
-
-int streamNint = 11 ;
-
-
-static int
-streamGetPackSize(void * voidP, void *context)
-{
-  stream_t * streamP = ( stream_t * ) voidP;
-  int packBufferSize
-    = serializeGetSize(streamNint, DATATYPE_INT, context)
-    + serializeGetSize(2, DATATYPE_UINT32, context)
-    + serializeGetSize((int)strlen(streamP->filename) + 1,
-                       DATATYPE_TXT, context)
-    + serializeGetSize(1, DATATYPE_FLT64, context);
-  return packBufferSize;
-}
-
-
-static void
-streamPack(void * streamptr, void * packBuffer, int packBufferSize,
-           int * packBufferPos, void *context)
-{
-  stream_t * streamP = ( stream_t * ) streamptr;
-  int intBuffer[streamNint];
-
-  intBuffer[0]  = streamP->self;
-  intBuffer[1]  = streamP->filetype;
-  intBuffer[2]  = (int)strlen(streamP->filename) + 1;
-  intBuffer[3]  = streamP->vlistID;
-  intBuffer[4]  = streamP->vlistIDorig;
-  intBuffer[5]  = streamP->byteorder;
-  intBuffer[6]  = streamP->comptype;
-  intBuffer[7]  = streamP->complevel;
-  intBuffer[8]  = cdiDataUnreduced;
-  intBuffer[9]  = cdiSortName;
-  intBuffer[10] = cdiHaveMissval;
-
-  serializePack(intBuffer, streamNint, DATATYPE_INT, packBuffer, packBufferSize, packBufferPos, context);
-  uint32_t d = cdiCheckSum(DATATYPE_INT, streamNint, intBuffer);
-  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
-
-  serializePack(&cdiDefaultMissval, 1, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context);
-  serializePack(streamP->filename, intBuffer[2], DATATYPE_TXT, packBuffer, packBufferSize, packBufferPos, context);
-  d = cdiCheckSum(DATATYPE_TXT, intBuffer[2], streamP->filename);
-  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
-}
-
-struct streamAssoc
-streamUnpack(char * unpackBuffer, int unpackBufferSize,
-             int * unpackBufferPos, int originNamespace, void *context)
-{
-  int intBuffer[streamNint], streamID;
-  uint32_t d;
-  char filename[CDI_MAX_NAME];
-
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  intBuffer, streamNint, DATATYPE_INT, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &d, 1, DATATYPE_UINT32, context);
-  xassert(cdiCheckSum(DATATYPE_INT, streamNint, intBuffer) == d);
-
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &cdiDefaultMissval, 1, DATATYPE_FLT64, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &filename, intBuffer[2], DATATYPE_TXT, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &d, 1, DATATYPE_UINT32, context);
-  xassert(d == cdiCheckSum(DATATYPE_TXT, intBuffer[2], filename));
-  streamID = streamOpenWrite ( filename, intBuffer[1] );
-  xassert ( streamID >= 0 &&
-            namespaceAdaptKey ( intBuffer[0], originNamespace ) == streamID );
-  streamDefByteorder(streamID, intBuffer[5]);
-  streamDefCompType(streamID, intBuffer[6]);
-  streamDefCompLevel(streamID, intBuffer[7]);
-  cdiDefGlobal("REGULARGRID", intBuffer[8]);
-  cdiDefGlobal("SORTNAME", intBuffer[9]);
-  cdiDefGlobal("HAVE_MISSVAL", intBuffer[10]);
-  struct streamAssoc retval = { streamID, intBuffer[3], intBuffer[4] };
-  return retval;
-}
-
-
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/cdi_int.h b/libcdi/src/cdi_int.h
index 2470dbb..6580eee 100644
--- a/libcdi/src/cdi_int.h
+++ b/libcdi/src/cdi_int.h
@@ -13,6 +13,9 @@
 #include <math.h>
 #include <sys/types.h>
 
+/* dummy use of unused parameters to silence compiler warnings */
+#define  UNUSED(x) (void)x
+
 #ifndef strdupx
 #ifndef strdup
 char *strdup(const char *s);
@@ -140,6 +143,7 @@ typedef struct
   int       ilevel;
   int       ilevel2;
   int       ltype;
+  int       tsteptype;
   short     used;
   short     varID;
   short     levelID;
@@ -200,7 +204,7 @@ typedef struct {
   off_t       numvals;
   char       *filename;
   Record     *record;
-  int        nrecs;        /* number of records                  */
+  int         nrecs;        /* number of records                  */
   int         nvars;        /* number of variables                */
   int         varlocked;    /* variables locked                   */
   svarinfo_t *vars;
@@ -216,9 +220,9 @@ typedef struct {
   basetime_t  basetime;
   int         ncmode;
   int         vlistID;
-  int         xdimID[MAX_GRIDS_PS];
-  int         ydimID[MAX_GRIDS_PS];
-  int         zaxisID[MAX_ZAXES_PS];
+  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
+  int         zaxisID[MAX_ZAXES_PS];	//Warning: synchronous array to vlist_to_pointer(vlistID)->zaxisIDs
   int         ncxvarID[MAX_GRIDS_PS];
   int         ncyvarID[MAX_GRIDS_PS];
   int         ncavarID[MAX_GRIDS_PS];
@@ -262,14 +266,28 @@ extern int cdiDefaultLeveltype;
 extern int cdiNcChunksizehint;
 extern int cdiChunkType;
 extern int cdiSplitLtype105;
+extern int cdiDataUnreduced;
+extern int cdiSortName;
+extern int cdiHaveMissval;
+extern int STREAM_Debug;
+
 
 extern char *cdiPartabPath;
 extern int   cdiPartabIntern;
+extern const resOps streamOps;
 
-stream_t *stream_to_pointer(int idx);
-stream_t *stream_new_entry(void);
-void stream_delete_entry(stream_t *streamptr);
-void stream_check_ptr(const char *caller, stream_t *streamptr);
+static inline stream_t *
+stream_to_pointer(int idx)
+{
+  return reshGetVal(idx, &streamOps);
+}
+
+static inline void
+stream_check_ptr(const char *caller, stream_t *streamptr)
+{
+  if ( streamptr == NULL )
+    Errorc("stream undefined!");
+}
 
 int     streamInqFileID(int streamID);
 
@@ -322,8 +340,6 @@ void    streamGetIndexList ( int, int * );
 
 void  cdiInitialize(void);
 
-void stream_write_record(int streamID, int memtype, const void *data, int nmiss);
-
 void uuid2str(const char *uuid, char *uuidstr);
 void str2uuid(const char *uuidstr, char *uuid);
 
@@ -366,8 +382,6 @@ void cdiStreamSync_(stream_t *streamptr);
 
 char *cdiUnitNamePtr(int cdi_unit);
 
-extern const resOps streamOps;
-
 #endif  /* _CDI_INT_H */
 /*
  * Local Variables:
diff --git a/libcdi/src/cdi_util.c b/libcdi/src/cdi_util.c
index 18c00b6..7966321 100644
--- a/libcdi/src/cdi_util.c
+++ b/libcdi/src/cdi_util.c
@@ -2,28 +2,28 @@
 
 void cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis)
 {
-  unsigned int *uparam = (unsigned int *) ¶m;
-  unsigned int upnum;
-
-  *pdis = 0xff   & *uparam;
-  *pcat = 0xff   & *uparam >> 8;
-  upnum = 0xffff & *uparam >> 16;
-  if ( upnum > 0x7fff ) upnum = 0x8000 - upnum;
-  *pnum = upnum;
+  unsigned uparam = (unsigned)param;
+  unsigned upnum;
+
+  *pdis = 0xff   & uparam;
+  *pcat = 0xff   & uparam >> 8;
+  upnum = 0xffff & uparam >> 16;
+  if ( upnum > 0x7fffU ) upnum = 0x8000U - upnum;
+  *pnum = (int)upnum;
 }
 
 
 int cdiEncodeParam(int pnum, int pcat, int pdis)
 {
-  unsigned int uparam, upnum;
+  unsigned uparam, upnum;
 
   if ( pcat < 0 || pcat > 255 ) pcat = 255;
   if ( pdis < 0 || pdis > 255 ) pdis = 255;
 
-  upnum = pnum;
-  if ( pnum < 0 ) upnum = 0x8000 - pnum;
+  upnum = (unsigned)pnum;
+  if ( pnum < 0 ) upnum = (unsigned)(0x8000 - pnum);
 
-  uparam = upnum << 16 | pcat << 8 | pdis;
+  uparam = upnum << 16 | (unsigned)(pcat << 8) | (unsigned)pdis;
 
   return ((int)uparam);
 }
diff --git a/libcdi/src/cdilib.c b/libcdi/src/cdilib.c
index 885bec1..374932f 100644
--- a/libcdi/src/cdilib.c
+++ b/libcdi/src/cdilib.c
@@ -1,7 +1,7 @@
 
-/* Automatically generated by m214003 at 2014-06-27, do not edit */
+/* Automatically generated by m214003 at 2014-10-31, do not edit */
 
-/* CDILIB_VERSION="1.6.4" */
+/* CDILIB_VERSION="1.6.5.1" */
 
 #ifdef _ARCH_PWR6
 #pragma options nostrict
@@ -111,10 +111,19 @@ typedef struct {
 }resOps;
 
 enum {
-  RESH_UNUSED,             /* resource holds no value */
-  RESH_ASSIGNED,           /* resource is user-assigned */
-  RESH_PRE_ASSIGNED,       /* resource is pre-assigned by library */
-  RESH_CLOSED,             /* resource is marked immutable */
+  RESH_IN_USE_BIT = 1 << 0,
+  RESH_SYNC_BIT = 1 << 1,
+  /* resource holds no value */
+  RESH_UNUSED = 0,
+  /* resource was deleted and needs to be synced */
+  RESH_DESYNC_DELETED
+    = RESH_SYNC_BIT,
+  /* resource is synchronized */
+  RESH_IN_USE
+    = RESH_IN_USE_BIT,
+  /* resource is in use, desynchronized and needs to be synced */
+  RESH_DESYNC_IN_USE
+    = RESH_IN_USE_BIT | RESH_SYNC_BIT,
 };
 
 void   reshListCreate(int namespaceID);
@@ -122,11 +131,14 @@ void   reshListDestruct(int namespaceID);
 int    reshPut ( void *, const resOps * );
 void reshReplace(cdiResH resH, void *p, const resOps *ops);
 void   reshRemove ( cdiResH, const resOps * );
+/*> doesn't check resource type */
+void reshDestroy(cdiResH);
 
 int    reshCountType ( const resOps * );
 
-void * reshGetValue(const char *, cdiResH, const resOps * );
-#define reshGetVal(resH, ops)  reshGetValue(__func__, resH, ops)
+void * reshGetValue(const char* caller, const char* expressionString, cdiResH id, const resOps* ops);
+#define reshGetVal(resH, ops)  reshGetValue(__func__, #resH, resH, ops)
+
 
 void   reshGetResHListOfType ( int, int *, const resOps * );
 
@@ -146,9 +158,11 @@ cdiResHFilterApply(const resOps *p,
 
 void   reshPackBufferCreate ( char **, int *, void *context );
 void   reshPackBufferDestroy ( char ** );
-int    reshResourceGetPackSize(int resh, const resOps *ops, void *context);
-void   reshPackResource(int resh, const resOps *ops,
-                        void *buf, int buf_size, int *position, void *context);
+int    reshResourceGetPackSize_intern(int resh, const resOps *ops, void *context, const char* caller, const char* expressionString);
+#define reshResourceGetPackSize(resh, ops, context) reshResourceGetPackSize_intern(resh, ops, context, __func__, #resh)
+void   reshPackResource_intern(int resh, const resOps *ops, void *buf, int buf_size, int *position, void *context, const char* caller, const char* expressionString);
+#define reshPackResource(resh, ops, buf, buf_size, position, context) reshPackResource_intern(resh, ops, buf, buf_size, position, context, __func__, #resh)
+
 void   reshSetStatus ( cdiResH, const resOps *, int );
 int    reshGetStatus ( cdiResH, const resOps * );
 
@@ -218,6 +232,9 @@ double   cdiEncodeTimeval(int date, int time, taxis_t* taxis);
 void     timeval2vtime(double timevalue, taxis_t* taxis, int* vdate, int* vtime);
 double   vtime2timeval(int vdate, int vtime, taxis_t *taxis);
 
+void    ptaxisDefName(taxis_t *taxisptr, const char *name);
+void    ptaxisDefLongname(taxis_t *taxisptr, const char *name);
+void    taxisDestroyKernel(taxis_t *taxisptr);
 #if !defined (SX)
 extern const resOps taxisOps;
 #endif
@@ -380,7 +397,7 @@ srvrec_t *srvNew(void);
 void srvDelete(srvrec_t *srvp);
 
 int  srvRead(int fileID, srvrec_t *srvp);
-int  srvWrite(int fileID, srvrec_t *srvp);
+void srvWrite(int fileID, srvrec_t *srvp);
 
 int  srvInqHeader(srvrec_t *srvp, int *header);
 int  srvInqDataSP(srvrec_t *srvp, float *data);
@@ -563,6 +580,7 @@ int  iegDefDataDP(iegrec_t *iegp, const double *data);
 #ifndef  CDI_H_
 #define  CDI_H_
 
+#include <stdio.h>
 #include <sys/types.h>
 /*
 #if defined(__cplusplus)
@@ -596,6 +614,7 @@ extern "C" {
 
 /* File types */
 
+#define  FILETYPE_UNDEF          -1   /* Unknown/not yet defined file type */
 #define  FILETYPE_GRB             1   /* File type GRIB                       */
 #define  FILETYPE_GRB2            2   /* File type GRIB version 2             */
 #define  FILETYPE_NC              3   /* File type netCDF                     */
@@ -753,14 +772,15 @@ extern "C" {
 
 #define  TUNIT_SECOND             1
 #define  TUNIT_MINUTE             2
-#define  TUNIT_HOUR               3
-#define  TUNIT_DAY                4
-#define  TUNIT_MONTH              5
-#define  TUNIT_YEAR               6
-#define  TUNIT_QUARTER            7
-#define  TUNIT_3HOURS             8
-#define  TUNIT_6HOURS             9
-#define  TUNIT_12HOURS           10
+#define  TUNIT_QUARTER            3
+#define  TUNIT_30MINUTES          4
+#define  TUNIT_HOUR               5
+#define  TUNIT_3HOURS             6
+#define  TUNIT_6HOURS             7
+#define  TUNIT_12HOURS            8
+#define  TUNIT_DAY                9
+#define  TUNIT_MONTH             10
+#define  TUNIT_YEAR              11
 
 /* CALENDAR types */
 
@@ -780,7 +800,7 @@ char   *cdiStringError(int cdiErrno);
 
 void    cdiDebug(int debug);
 
-char   *cdiLibraryVersion(void);
+const char *cdiLibraryVersion(void);
 void    cdiPrintVersion(void);
 
 int     cdiHaveFiletype(int filetype);
@@ -882,6 +902,7 @@ void    streamWriteVarF(int streamID, int varID, const float *data_vec, int nmis
 
 /*      streamReadVar: Read a variable */
 void    streamReadVar(int streamID, int varID, double *data_vec, int *nmiss);
+void    streamReadVarF(int streamID, int varID, float *data_vec, int *nmiss);
 
 /*      streamWriteVarSlice: Write a horizontal slice of a variable */
 void    streamWriteVarSlice(int streamID, int varID, int levelID, const double *data_vec, int nmiss);
@@ -889,6 +910,7 @@ void    streamWriteVarSliceF(int streamID, int varID, int levelID, const float *
 
 /*      streamReadVarSlice: Read a horizontal slice of a variable */
 void    streamReadVarSlice(int streamID, int varID, int levelID, double *data_vec, int *nmiss);
+void    streamReadVarSliceF(int streamID, int varID, int levelID, float *data_vec, int *nmiss);
 
 void    streamWriteVarChunk(int streamID, int varID, const int rect[][2],
                             const double *data_vec, int nmiss);
@@ -903,7 +925,7 @@ void    streamWriteRecordF(int streamID, const float *data_vec, int nmiss);
 void    streamReadRecord(int streamID, double *data_vec, int *nmiss);
 void    streamCopyRecord(int streamIDdest, int streamIDsrc);
 
-void    streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
+void    streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
 
 /* VLIST routines */
 
@@ -1076,6 +1098,9 @@ int     vlistInqVarTimaccu(int vlistID, int varID);
 void    vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGeneratingProcess);
 int     vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID);
 
+void    vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDefinitionTemplate);
+int     vlistInqVarProductDefinitionTemplate(int vlistID, int varID);
+
 int     vlistInqVarSize(int vlistID, int varID);
 
 void    vlistDefIndex(int vlistID, int varID, int levID, int index);
@@ -1543,6 +1568,7 @@ char   *modelInqNamePtr(int modelID);
 /* Table routines */
 
 void    tableWriteC(const char *filename, int tableID);
+void    tableFWriteC(FILE *ptfp, int tableID);
 void    tableWrite(const char *filename, int tableID);
 int     tableRead(const char *tablefile);
 int     tableDef(int modelID, int tablenum, const char *tablename);
@@ -1563,9 +1589,9 @@ int     tableInqParName(int tableID, int code, char *name);
 int     tableInqParLongname(int tableID, int code, char *longname);
 int     tableInqParUnits(int tableID, int code, char *units);
 
-char   *tableInqParNamePtr(int tableID, int parID);
-char   *tableInqParLongnamePtr(int tableID, int parID);
-char   *tableInqParUnitsPtr(int tableID, int parID);
+const char *tableInqParNamePtr(int tableID, int parID);
+const char *tableInqParLongnamePtr(int tableID, int parID);
+const char *tableInqParUnitsPtr(int tableID, int parID);
 
 /* History routines */
 
@@ -1573,6 +1599,9 @@ void    streamDefHistory(int streamID, int size, const char *history);
 int     streamInqHistorySize(int streamID);
 void    streamInqHistoryString(int streamID, char *history);
 
+
+void gribapiLibraryVersion(int *major_version, int *minor_version, int *revision_version);
+
 /*
 #if defined (__cplusplus)
 }
@@ -1634,6 +1663,16 @@ void decode_caldaysec(int calendar, int julday, int secofday,
 #ifndef _BASETIME_H
 #define _BASETIME_H
 
+//#define USE_TIMECACHE 1
+#define MAX_TIMECACHE_SIZE 1024
+
+typedef struct {
+  int size;
+  int startid;
+  int maxvals;
+  double cache[MAX_TIMECACHE_SIZE];
+}
+timecache_t;
 
 typedef struct {
   int   ncvarid;
@@ -1641,6 +1680,7 @@ typedef struct {
   int   ncvarboundsid;
   int   leadtimeid;
   int   lwrf;     /* TRUE for time axis in WRF format */
+  timecache_t *timevar_cache;
 }
 basetime_t;
 
@@ -1758,7 +1798,7 @@ union namespaceSwitchValue namespaceSwitchGet(enum namespaceSwitch sw);
  * End:
  */
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#  include "config.h"
 #endif
 
 #include <inttypes.h>
@@ -2013,6 +2053,9 @@ cdiAbortC_serial(const char *caller, const char *filename,
 #include <math.h>
 #include <sys/types.h>
 
+/* dummy use of unused parameters to silence compiler warnings */
+#define  UNUSED(x) (void)x
+
 #ifndef strdupx
 #ifndef strdup
 char *strdup(const char *s);
@@ -2140,6 +2183,7 @@ typedef struct
   int       ilevel;
   int       ilevel2;
   int       ltype;
+  int       tsteptype;
   short     used;
   short     varID;
   short     levelID;
@@ -2200,7 +2244,7 @@ typedef struct {
   off_t       numvals;
   char       *filename;
   Record     *record;
-  int        nrecs;        /* number of records                  */
+  int         nrecs;        /* number of records                  */
   int         nvars;        /* number of variables                */
   int         varlocked;    /* variables locked                   */
   svarinfo_t *vars;
@@ -2216,9 +2260,9 @@ typedef struct {
   basetime_t  basetime;
   int         ncmode;
   int         vlistID;
-  int         xdimID[MAX_GRIDS_PS];
-  int         ydimID[MAX_GRIDS_PS];
-  int         zaxisID[MAX_ZAXES_PS];
+  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
+  int         zaxisID[MAX_ZAXES_PS];	//Warning: synchronous array to vlist_to_pointer(vlistID)->zaxisIDs
   int         ncxvarID[MAX_GRIDS_PS];
   int         ncyvarID[MAX_GRIDS_PS];
   int         ncavarID[MAX_GRIDS_PS];
@@ -2262,14 +2306,28 @@ extern int cdiDefaultLeveltype;
 extern int cdiNcChunksizehint;
 extern int cdiChunkType;
 extern int cdiSplitLtype105;
+extern int cdiDataUnreduced;
+extern int cdiSortName;
+extern int cdiHaveMissval;
+extern int STREAM_Debug;
+
 
 extern char *cdiPartabPath;
 extern int   cdiPartabIntern;
+extern const resOps streamOps;
 
-stream_t *stream_to_pointer(int idx);
-stream_t *stream_new_entry(void);
-void stream_delete_entry(stream_t *streamptr);
-void stream_check_ptr(const char *caller, stream_t *streamptr);
+static inline stream_t *
+stream_to_pointer(int idx)
+{
+  return reshGetVal(idx, &streamOps);
+}
+
+static inline void
+stream_check_ptr(const char *caller, stream_t *streamptr)
+{
+  if ( streamptr == NULL )
+    Errorc("stream undefined!");
+}
 
 int     streamInqFileID(int streamID);
 
@@ -2322,8 +2380,6 @@ void    streamGetIndexList ( int, int * );
 
 void  cdiInitialize(void);
 
-void stream_write_record(int streamID, int memtype, const void *data, int nmiss);
-
 void uuid2str(const char *uuid, char *uuidstr);
 void str2uuid(const char *uuidstr, char *uuid);
 
@@ -2366,8 +2422,6 @@ void cdiStreamSync_(stream_t *streamptr);
 
 char *cdiUnitNamePtr(int cdi_unit);
 
-extern const resOps streamOps;
-
 #endif  /* _CDI_INT_H */
 /*
  * Local Variables:
@@ -2437,13 +2491,14 @@ extern const resOps streamOps;
 /*
  *  Macros for the product definition section ( Section 1 )
  */
-#define  ISEC1_TABLE4_MINUTE    0
-#define  ISEC1_TABLE4_HOUR      1
-#define  ISEC1_TABLE4_DAY       2
-#define  ISEC1_TABLE4_3HOURS   10
-#define  ISEC1_TABLE4_6HOURS   11
-#define  ISEC1_TABLE4_12HOURS  12
-#define  ISEC1_TABLE4_QUARTER  13
+#define  ISEC1_TABLE4_MINUTE      0
+#define  ISEC1_TABLE4_HOUR        1
+#define  ISEC1_TABLE4_DAY         2
+#define  ISEC1_TABLE4_3HOURS     10
+#define  ISEC1_TABLE4_6HOURS     11
+#define  ISEC1_TABLE4_12HOURS    12
+#define  ISEC1_TABLE4_QUARTER    13
+#define  ISEC1_TABLE4_30MINUTES  14
 
 
 #define  ISEC1_CodeTable            (isec1[ 0])  /*  Version number of code table                 */
@@ -2602,12 +2657,6 @@ void  gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffe
 void  gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer);
 void  gribRepair1(int nrec, long recsize, unsigned char *gribbuffer);
 
-int grib1Sections(unsigned char *gribbuffer, long recsize, unsigned char **pdsp,
-		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp);
-int grib2Sections(unsigned char *gribbuffer, long recsize, unsigned char **idsp,
-		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
-		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
-
 int   gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize);
 
 int   gribBzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize);
@@ -2626,7 +2675,7 @@ int   gribFileSeek(int fileID, long *offset);
 int   gribReadSize(int fileID);
 int   gribVersion(unsigned char *buffer, size_t buffersize);
 
-int   gribGinfo(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
+int   grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
 
 double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation);
 
@@ -2676,7 +2725,7 @@ double calculate_pfactor(const double* spectralField, long fieldTruncation, long
 #define  GRIB2_GTYPE_GME                 100  /*  hexagonal GME grid                                   */
 #define  GRIB2_GTYPE_UNSTRUCTURED        101  /*  General Unstructured Grid                            */
 
-const char *gribapiLibraryVersion(void);
+const char *gribapiLibraryVersionString(void);
 void gribContainersNew(stream_t * streamptr);
 void gribContainersDelete(stream_t * streamptr);
 void *gribHandleNew(int editionNumber);
@@ -2706,9 +2755,9 @@ int cgribexScanTimestep2(stream_t * streamptr);
 int cgribexScanTimestep(stream_t * streamptr);
 
 int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval);
+		  int unreduced, int *nmiss, double missval);
 
-size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
 		     long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize);
 
@@ -2730,7 +2779,7 @@ int gribapiScanTimestep2(stream_t * streamptr);
 int gribapiScanTimestep(stream_t * streamptr);
 
 int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID);
+		  int unreduced, int *nmiss, double missval, int vlistID, int varID);
 
 size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
@@ -2756,16 +2805,16 @@ int   grbInqContents(stream_t * streamptr);
 int   grbInqTimestep(stream_t * streamptr, int tsID);
 
 int   grbInqRecord(stream_t * streamptr, int *varID, int *levelID);
-int   grbDefRecord(stream_t * streamptr);
-int   grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
-int   grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
-int   grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
+void  grbDefRecord(stream_t * streamptr);
+void  grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
+void  grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
+void  grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
 
 void  grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss);
 void  grb_write_var(stream_t * streamptr, int varID, int memtype, const void *data, int nmiss);
 
 void  grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss);
-int   grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
+void  grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
 
 int   grib1ltypeToZaxisType(int grib_ltype);
 int   grib2ltypeToZaxisType(int grib_ltype);
@@ -2795,18 +2844,21 @@ int    cdfInqHistorySize(stream_t *streamptr);
 void   cdfInqHistoryString(stream_t *streamptr, char *history);
 
 void   cdfEndDef(stream_t * streamptr);
-int    cdfDefRecord(stream_t * streamptr);
+void   cdfDefRecord(stream_t * streamptr);
 
-int    cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
 
-int    cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
 void   cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
 
 void   cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss);
+void   cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss);
+
 void   cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
 
-int    cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
-int    cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
+void   cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
+void   cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss);
+void   cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
 
 void   cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
                            const int rect[][2], const void *data, int nmiss);
@@ -2824,17 +2876,24 @@ void   cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 #ifndef _TABLEPAR_H
 #define _TABLEPAR_H
 
+enum {
+  TABLE_DUP_NAME = 1 << 0,
+  TABLE_DUP_LONGNAME = 1 << 1,
+  TABLE_DUP_UNITS = 1 << 2,
+};
+
 typedef struct
 {
   int   id;	     /* Parameter number (GRIB) */
-  char *name;	     /* Parameter name */
-  char *longname;    /* Parameter long name */
-  char *units;	     /* Parameter units */
+  int dupflags;      /* keep track of which attributes got strdup'ed */
+  const char *name;	     /* Parameter name */
+  const char *longname;    /* Parameter long name */
+  const char *units;	     /* Parameter units */
 }
 PAR;
 
 
-void tableLink(int tableID, PAR *pars, int npars);
+static void tableLink(int tableID, const PAR *pars, int npars);
 int tableDef(int modelID, int tablegribID, const char *tablename);
 
 #endif
@@ -2850,1230 +2909,1230 @@ int tableDef(int modelID, int tablegribID, const char *tablename);
 #ifndef _TABLE_H
 #define _TABLE_H
 
-static PAR echam4[] = {
-  {   4, "precip",      "total precipitation",                      "m/s"      },
-  {  34, "low_cld",     "low cloud",                                 NULL      },
-  {  35, "mid_cld",     "mid cloud",                                 NULL      },
-  {  36, "hih_cld",     "high cloud",                                NULL      },
-  { 129, "geosp",       "surface geopotential (orography)",         "m^2/s^2"  },
-  { 130, "t",           "temperature",                              "K"        },
-  { 131, "u",           "u-velocity",                               "m/s"      },
-  { 132, "v",           "v-velocity",                               "m/s"      },
-  { 133, "sq",          "specific humidity",                        "kg/kg"    },
-  { 134, "aps",         "Surface pressure",                         "Pa"       },
-  { 135, "omega",       "vertical velocity",                        "Pa/s"     },
-  { 138, "svo",         "vorticity",                                "1/s"      },
-  { 139, "ts",          "surface temperature",                      "K"        },
-  { 140, "ws",          "soil wetness",                             "m"        },
-  { 141, "sn",          "snow depth",                               "m"        },
-  { 142, "aprl",        "large scale precipitation",                "m/s"      },
-  { 143, "aprc",        "convective  precipitation",                "m/s"      },
-  { 144, "aprs",        "snow fall",                                "m/s"      },
-  { 145, "vdis",        "boundary layer dissipation",               "W/m^2"    },
-  { 146, "ahfs",        "surface sensible heat flux",               "W/m^2"    },
-  { 147, "ahfl",        "surface latent heat flux",                 "W/m^2"    },
-  { 148, "stream",      "streamfunction",                           "m^2/s"    },
-  { 149, "velopot",     "velocity potential",                       "m^2/s"    },
-  { 151, "slp",         "mean sea level pressure",                  "Pa"       },
-  { 152, "lsp",         "log surface pressure",                      NULL      },
-  { 153, "sx",          "liquid water content",                     "kg/kg"    },
-  { 155, "sd",          "divergence",                               "1/s"      },
-  { 156, "geopoth",     "geopotential height",                      "m"        },
-  { 157, "rhumidity",   "relative humidity",                        "fraction" },
-  { 158, "var158",      "tendency of surface pressure",             "Pa/s"     },
-  { 159, "ustar3",      "ustar3",                                   "m^3/s^3"  },
-  { 160, "runoff",      "surface runoff",                           "m/s"      },
-  { 161, "alwc",        "liquid water content",                     "kg/kg"    },
-  { 162, "aclc",        "cloud cover",                              "fraction" },
-  { 163, "aclcv",       "total cloud cover",                        "fraction" },
-  { 164, "aclcov",      "total cloud cover",                        "fraction" },
-  { 165, "u10",         "10m u-velocity",                           "m/s"      },
-  { 166, "v10",         "10m v-velocity",                           "m/s"      },
-  { 167, "temp2",       "2m temperature",                           "K"        },
-  { 168, "dew2",        "2m dew point temperature",                 "K"        },
-  { 169, "tsurf",       "surface temperature",                      "K"        },
-  { 170, "td",          "deep soil temperature",                    "K"        },
-  { 171, "wind10",      "10m windspeed",                            "m/s"      },
-  { 172, "slm",         "land sea mask",                            "fraction" },
-  { 173, "az0",         "surface roughness length",                 "m"        },
-  { 174, "alb",         "surface background albedo",                "fraction" },
-  { 175, "albedo",      "surface albedo",                           "fraction" },
-  { 176, "srads",       "net surface solar radiation",              "W/m^2"    },
-  { 177, "trads",       "net surface thermal radiation",            "W/m^2"    },
-  { 178, "srad0",       "net top solar radiation",                  "W/m^2"    },
-  { 179, "trad0",       "top thermal radiation (OLR)",              "W/m^2"    },
-  { 180, "ustr",        "surface u-stress",                         "Pa"       },
-  { 181, "vstr",        "surface v-stress",                         "Pa"       },
-  { 182, "evap",        "surface evaporation",                      "m/s"      },
-  { 183, "tdcl",        "soil temperature",                         "K"        },
-  { 185, "srafs",       "net surf. solar radiation   (clear sky)",  "W/m^2"    },
-  { 186, "trafs",       "net surf. thermal radiation (clear sky)",  "W/m^2"    },
-  { 187, "sraf0",       "net top solar radiation     (clear sky)",  "W/m^2"    },
-  { 188, "traf0",       "net top thermal radiation   (clear sky)",  "W/m^2"    },
-  { 189, "sclfs",       "surface solar cloud forcing",              "W/m^2"    },
-  { 190, "tclfs",       "surface thermal cloud forcing",            "W/m^2"    },
-  { 191, "sclf0",       "top solar cloud forcing",                  "W/m^2"    },
-  { 192, "tclf0",       "top thermal cloud forcing",                "W/m^2"    },
-  { 193, "wl",          "skin reservoir content",                   "m"        },
-  { 194, "wlm1",        "skin reservoir content of plants",         "m"        },
-  { 195, "ustrgw",      "u-gravity wave stress",                    "Pa"       },
-  { 196, "vstrgw",      "v-gravity wave stress",                    "Pa"       },
-  { 197, "vdisgw",      "gravity wave dissipation",                 "W/m^2"    },
-  { 198, "vgrat",       "vegetation ratio",                         "fraction" },
-  { 199, "varor",       "orographic variance",                      "m^2"      },
-  { 200, "vlt",         "leaf area index",                           NULL      },
-  { 201, "t2max",       "maximum 2m-temperature",                   "K"        },
-  { 202, "t2min",       "minimum 2m-temperature",                   "K"        },
-  { 203, "srad0u",      "top solar radiation upward",               "W/m^2"    },
-  { 204, "sradsu",      "surface solar radiation upward",           "W/m^2"    },
-  { 205, "tradsu",      "surface thermal radiation upward",         "W/m^2"    },
-  { 206, "tsn",         "snow temperature",                         "K"        },
-  { 207, "td3",         "soil temperature 3",                       "K"        },
-  { 208, "td4",         "soil temperature 4",                       "K"        },
-  { 209, "td5",         "soil temperature 5",                       "K"        },
-  { 210, "seaice",      "sea ice cover",                            "fraction" },
-  { 211, "siced",       "sea ice depth",                            "m"        },
-  { 212, "forest",      "vegetation type",                          "fraction" },
-  { 213, "teff",        "(effective) sea-ice skin temperature",     "K"        },
-  { 214, "tsmax",       "maximum surface temperature",              "K"        },
-  { 215, "tsmin",       "minimum surface temperature",              "K"        },
-  { 216, "wimax",       "maximum 10m-wind speed",                   "m/s"      },
-  { 217, "topmax",      "maximum height of convective cloud tops",  "Pa"       },
-  { 218, "snmel",       "snow melt",                                "m/s"      },
-  { 219, "runtoc",      "surface runoff into ocean",                 NULL      },
-  { 220, "tslin",       "land: residual surface heat budget",       "W/m^2"    },
-  { 221, "dsnac",       "snow depth change",                        "m/s"      },
-  { 222, "alwcac",      "liquid water content",                     "kg/kg"    },
-  { 223, "aclcac",      "cloud cover",                              "fraction" },
-  { 224, "tke",         "turbulent kinetic energy",                  NULL      },
-  { 225, "tkem1",       "turbulent kinetic energy (t-1)",            NULL      },
-  { 226, "fao",         "FAO data set (soil data flags)",            NULL      },
-  { 227, "rgcgn",       "heat capacity of soil",                     NULL      },
-  { 228, "sodif",       "soil diffusivity",                          NULL      },
-  { 229, "wsmx",        "field capacity of soil",                   "m"        },
-  { 230, "qvi",         "vertically integrated specific humidity",  "kg/m^2"   },
-  { 231, "alwcvi",      "vertically integrated liquid water cont.", "kg/m^2"   },
-  { 232, "glac",        "glacier mask",                             "fraction" },
-  { 233, "runlnd",      "surface runoff not running into ocean",     NULL      },
-  { 259, "windspeed",   "windspeed (sqrt(u^2+v^2))",                 NULL      },
-  { 260, "precip",      "total precipitation",                      "m/s"      },
-  { 261, "net_top",     "total top radiation",                       NULL      },
-  { 262, "net_bot",     "total surface radiation",                   NULL      },
-  { 263, "net_heat",    "net surface heat flux",                     NULL      },
-  { 264, "net_water",   "total surface water",                       NULL      },
-  { 268, "sw_atm",       NULL,                                       NULL      },
-  { 269, "lw_atm",       NULL,                                       NULL      },
-  { 270, "net_atm",      NULL,                                       NULL      },
-  { 271, "surf_runoff", "surface runoff",                            NULL      },
-  { 275, "fresh_water",  NULL,                                       NULL      },
+static const PAR echam4[] = {
+  {   4, 0, "precip",      "total precipitation",                      "m/s"      },
+  {  34, 0, "low_cld",     "low cloud",                                 NULL      },
+  {  35, 0, "mid_cld",     "mid cloud",                                 NULL      },
+  {  36, 0, "hih_cld",     "high cloud",                                NULL      },
+  { 129, 0, "geosp",       "surface geopotential (orography)",         "m^2/s^2"  },
+  { 130, 0, "t",           "temperature",                              "K"        },
+  { 131, 0, "u",           "u-velocity",                               "m/s"      },
+  { 132, 0, "v",           "v-velocity",                               "m/s"      },
+  { 133, 0, "sq",          "specific humidity",                        "kg/kg"    },
+  { 134, 0, "aps",         "Surface pressure",                         "Pa"       },
+  { 135, 0, "omega",       "vertical velocity",                        "Pa/s"     },
+  { 138, 0, "svo",         "vorticity",                                "1/s"      },
+  { 139, 0, "ts",          "surface temperature",                      "K"        },
+  { 140, 0, "ws",          "soil wetness",                             "m"        },
+  { 141, 0, "sn",          "snow depth",                               "m"        },
+  { 142, 0, "aprl",        "large scale precipitation",                "m/s"      },
+  { 143, 0, "aprc",        "convective  precipitation",                "m/s"      },
+  { 144, 0, "aprs",        "snow fall",                                "m/s"      },
+  { 145, 0, "vdis",        "boundary layer dissipation",               "W/m^2"    },
+  { 146, 0, "ahfs",        "surface sensible heat flux",               "W/m^2"    },
+  { 147, 0, "ahfl",        "surface latent heat flux",                 "W/m^2"    },
+  { 148, 0, "stream",      "streamfunction",                           "m^2/s"    },
+  { 149, 0, "velopot",     "velocity potential",                       "m^2/s"    },
+  { 151, 0, "slp",         "mean sea level pressure",                  "Pa"       },
+  { 152, 0, "lsp",         "log surface pressure",                      NULL      },
+  { 153, 0, "sx",          "liquid water content",                     "kg/kg"    },
+  { 155, 0, "sd",          "divergence",                               "1/s"      },
+  { 156, 0, "geopoth",     "geopotential height",                      "m"        },
+  { 157, 0, "rhumidity",   "relative humidity",                        "fraction" },
+  { 158, 0, "var158",      "tendency of surface pressure",             "Pa/s"     },
+  { 159, 0, "ustar3",      "ustar3",                                   "m^3/s^3"  },
+  { 160, 0, "runoff",      "surface runoff",                           "m/s"      },
+  { 161, 0, "alwc",        "liquid water content",                     "kg/kg"    },
+  { 162, 0, "aclc",        "cloud cover",                              "fraction" },
+  { 163, 0, "aclcv",       "total cloud cover",                        "fraction" },
+  { 164, 0, "aclcov",      "total cloud cover",                        "fraction" },
+  { 165, 0, "u10",         "10m u-velocity",                           "m/s"      },
+  { 166, 0, "v10",         "10m v-velocity",                           "m/s"      },
+  { 167, 0, "temp2",       "2m temperature",                           "K"        },
+  { 168, 0, "dew2",        "2m dew point temperature",                 "K"        },
+  { 169, 0, "tsurf",       "surface temperature",                      "K"        },
+  { 170, 0, "td",          "deep soil temperature",                    "K"        },
+  { 171, 0, "wind10",      "10m windspeed",                            "m/s"      },
+  { 172, 0, "slm",         "land sea mask",                            "fraction" },
+  { 173, 0, "az0",         "surface roughness length",                 "m"        },
+  { 174, 0, "alb",         "surface background albedo",                "fraction" },
+  { 175, 0, "albedo",      "surface albedo",                           "fraction" },
+  { 176, 0, "srads",       "net surface solar radiation",              "W/m^2"    },
+  { 177, 0, "trads",       "net surface thermal radiation",            "W/m^2"    },
+  { 178, 0, "srad0",       "net top solar radiation",                  "W/m^2"    },
+  { 179, 0, "trad0",       "top thermal radiation (OLR)",              "W/m^2"    },
+  { 180, 0, "ustr",        "surface u-stress",                         "Pa"       },
+  { 181, 0, "vstr",        "surface v-stress",                         "Pa"       },
+  { 182, 0, "evap",        "surface evaporation",                      "m/s"      },
+  { 183, 0, "tdcl",        "soil temperature",                         "K"        },
+  { 185, 0, "srafs",       "net surf. solar radiation   (clear sky)",  "W/m^2"    },
+  { 186, 0, "trafs",       "net surf. thermal radiation (clear sky)",  "W/m^2"    },
+  { 187, 0, "sraf0",       "net top solar radiation     (clear sky)",  "W/m^2"    },
+  { 188, 0, "traf0",       "net top thermal radiation   (clear sky)",  "W/m^2"    },
+  { 189, 0, "sclfs",       "surface solar cloud forcing",              "W/m^2"    },
+  { 190, 0, "tclfs",       "surface thermal cloud forcing",            "W/m^2"    },
+  { 191, 0, "sclf0",       "top solar cloud forcing",                  "W/m^2"    },
+  { 192, 0, "tclf0",       "top thermal cloud forcing",                "W/m^2"    },
+  { 193, 0, "wl",          "skin reservoir content",                   "m"        },
+  { 194, 0, "wlm1",        "skin reservoir content of plants",         "m"        },
+  { 195, 0, "ustrgw",      "u-gravity wave stress",                    "Pa"       },
+  { 196, 0, "vstrgw",      "v-gravity wave stress",                    "Pa"       },
+  { 197, 0, "vdisgw",      "gravity wave dissipation",                 "W/m^2"    },
+  { 198, 0, "vgrat",       "vegetation ratio",                         "fraction" },
+  { 199, 0, "varor",       "orographic variance",                      "m^2"      },
+  { 200, 0, "vlt",         "leaf area index",                           NULL      },
+  { 201, 0, "t2max",       "maximum 2m-temperature",                   "K"        },
+  { 202, 0, "t2min",       "minimum 2m-temperature",                   "K"        },
+  { 203, 0, "srad0u",      "top solar radiation upward",               "W/m^2"    },
+  { 204, 0, "sradsu",      "surface solar radiation upward",           "W/m^2"    },
+  { 205, 0, "tradsu",      "surface thermal radiation upward",         "W/m^2"    },
+  { 206, 0, "tsn",         "snow temperature",                         "K"        },
+  { 207, 0, "td3",         "soil temperature 3",                       "K"        },
+  { 208, 0, "td4",         "soil temperature 4",                       "K"        },
+  { 209, 0, "td5",         "soil temperature 5",                       "K"        },
+  { 210, 0, "seaice",      "sea ice cover",                            "fraction" },
+  { 211, 0, "siced",       "sea ice depth",                            "m"        },
+  { 212, 0, "forest",      "vegetation type",                          "fraction" },
+  { 213, 0, "teff",        "(effective) sea-ice skin temperature",     "K"        },
+  { 214, 0, "tsmax",       "maximum surface temperature",              "K"        },
+  { 215, 0, "tsmin",       "minimum surface temperature",              "K"        },
+  { 216, 0, "wimax",       "maximum 10m-wind speed",                   "m/s"      },
+  { 217, 0, "topmax",      "maximum height of convective cloud tops",  "Pa"       },
+  { 218, 0, "snmel",       "snow melt",                                "m/s"      },
+  { 219, 0, "runtoc",      "surface runoff into ocean",                 NULL      },
+  { 220, 0, "tslin",       "land: residual surface heat budget",       "W/m^2"    },
+  { 221, 0, "dsnac",       "snow depth change",                        "m/s"      },
+  { 222, 0, "alwcac",      "liquid water content",                     "kg/kg"    },
+  { 223, 0, "aclcac",      "cloud cover",                              "fraction" },
+  { 224, 0, "tke",         "turbulent kinetic energy",                  NULL      },
+  { 225, 0, "tkem1",       "turbulent kinetic energy (t-1)",            NULL      },
+  { 226, 0, "fao",         "FAO data set (soil data flags)",            NULL      },
+  { 227, 0, "rgcgn",       "heat capacity of soil",                     NULL      },
+  { 228, 0, "sodif",       "soil diffusivity",                          NULL      },
+  { 229, 0, "wsmx",        "field capacity of soil",                   "m"        },
+  { 230, 0, "qvi",         "vertically integrated specific humidity",  "kg/m^2"   },
+  { 231, 0, "alwcvi",      "vertically integrated liquid water cont.", "kg/m^2"   },
+  { 232, 0, "glac",        "glacier mask",                             "fraction" },
+  { 233, 0, "runlnd",      "surface runoff not running into ocean",     NULL      },
+  { 259, 0, "windspeed",   "windspeed (sqrt(u^2+v^2))",                 NULL      },
+  { 260, 0, "precip",      "total precipitation",                      "m/s"      },
+  { 261, 0, "net_top",     "total top radiation",                       NULL      },
+  { 262, 0, "net_bot",     "total surface radiation",                   NULL      },
+  { 263, 0, "net_heat",    "net surface heat flux",                     NULL      },
+  { 264, 0, "net_water",   "total surface water",                       NULL      },
+  { 268, 0, "sw_atm",       NULL,                                       NULL      },
+  { 269, 0, "lw_atm",       NULL,                                       NULL      },
+  { 270, 0, "net_atm",      NULL,                                       NULL      },
+  { 271, 0, "surf_runoff", "surface runoff",                            NULL      },
+  { 275, 0, "fresh_water",  NULL,                                       NULL      },
 };
 
-static PAR echam5[] = {
-  {   4, "precip",     "total precipitation",                       "kg/m^2s" },
-  {  79, "swnirac",    "net surface NIR flux acc.",                 "W/m^2"   },
-  {  80, "swdifnirac", "fraction of diffuse NIR acc.",              "W/m^2"   },
-  {  81, "swvisac",    "net surface visible flux acc.",             "W/m^2"   },
-  {  82, "swdifvisac", "fraction of diffuse visible acc.",          "W/m^2"   },
-  {  83, "ocu",        "ocean eastw. velocity (coupled mode)",      "m/s"     },
-  {  84, "ocv",        "ocean northw. velocity (coupled mode)",     "m/s"     },
-  {  85, "tradl",      "net LW radiation 200mb",                    "W/m^2"   },
-  {  86, "sradl",      "net SW radiation 200mb",                    "W/m^2"   },
-  {  87, "trafl",      "net LW radiation 200mb (clear sky)",        "W/m^2"   },
-  {  88, "srafl",      "net SW radiation 200mb (clear sky)",        "W/m^2"   },
-  {  89, "amlcorac",   "mixed layer flux correction",               "W/m^2"   },
-  {  90, "amlheatac",  "mixed layer heat content",                  "J/m^2"   },
-  {  91, "trfliac",    "net LW radiation over ice",                 "W/m^2"   },
-  {  92, "trflwac",    "net LW radiation over water",               "W/m^2"   },
-  {  93, "trfllac",    "net LW radiation over land",                "W/m^2"   },
-  {  94, "sofliac",    "net SW radiation over ice",                 "W/m^2"   },
-  {  95, "soflwac",    "net SW radiation over water",               "W/m^2"   },
-  {  96, "sofllac",    "net SW radiation over land",                "W/m^2"   },
-  {  97, "friac",      "ice cover (fraction of grid box)",           NULL     },
-  { 102, "tsi",        "surface temperature of ice",                "K"       },
-  { 103, "tsw",        "surface temperature of water",              "K"       },
-  { 104, "ustri",      "zonal      wind stress over ice",           "Pa"      },
-  { 105, "vstri",      "meridional wind stress over ice",           "Pa"      },
-  { 106, "ustrw",      "zonal      wind stress over water",         "Pa"      },
-  { 107, "vstrw",      "meridional wind stress over water",         "Pa"      },
-  { 108, "ustrl",      "zonal      wind stress over land",          "Pa"      },
-  { 109, "vstrl",      "meridional wind stress over land",          "Pa"      },
-  { 110, "ahfliac",    "latent heat flux over ice",                 "W/m^2"   },
-  { 111, "ahflwac",    "latent heat flux over water",               "W/m^2"   },
-  { 112, "ahfllac",    "latent heat flux over land",                "W/m^2"   },
-  { 113, "evapiac",    "evaporation over ice",                      "kg/m^2s" },
-  { 114, "evapwac",    "evaporation over water",                    "kg/m^2s" },
-  { 115, "evaplac",    "evaporation over land",                     "kg/m^2s" },
-  { 116, "az0i",       "roughness length over ice",                 "m"       },
-  { 117, "az0w",       "roughness length over water",               "m"       },
-  { 118, "az0l",       "roughness length over land",                "m"       },
-  { 119, "ahfsiac",    "sensible heat flux over ice",               "W/m^2"   },
-  { 120, "ahfswac",    "sensible heat flux over water",             "W/m^2"   },
-  { 121, "ahfslac",    "sensible heat flux over land",              "W/m^2"   },
-  { 122, "alsoi",      "albedo of ice",                              NULL     },
-  { 123, "alsow",      "albedo of water",                            NULL     },
-  { 124, "alsol",      "albedo of land",                             NULL     },
-  { 125, "ahfice",     "conductive heat flux through ice",          "W/m^2"   },
-  { 126, "qres",       "residual heat flux for melting sea ice",    "W/m^2"   },
-  { 127, "alake",      "lake fraction",                              NULL     },
-  { 128, "rintop",     "low level inversion",                        NULL     },
-  { 129, "geosp",      "surface geopotential (orography)",          "m^2/s^2" },
-  { 130, "t",          "temperature",                               "K"       },
-  { 131, "u",          "u-velocity",                                "m/s"     },
-  { 132, "v",          "v-velocity",                                "m/s"     },
-  { 133, "q",          "specific humidity",                         "kg/kg"   },
-  { 134, "aps",        "surface pressure",                          "Pa"      },
-  { 135, "omega",      "vertical velocity",                         "Pa/s"    },
-  { 136, "acdnc",      "cloud droplet number concentration",        "1/m^3"   },
-  { 137, "apmeb",      "(P-E) error",                               "kg/m^2s" },
-  { 138, "svo",        "vorticity",                                 "1/s"     },
-  { 139, "tslm1",      "surface temperature of land",               "K"       },
-  { 140, "ws",         "soil wetness",                              "m"       },
-  { 141, "sn",         "water equivalent snow depth",               "m"       },
-  { 142, "aprl",       "large scale precipitation",                 "kg/m^2s" },
-  { 143, "aprc",       "convective  precipitation",                 "kg/m^2s" },
-  { 144, "aprs",       "snow fall",                                 "kg/m^2s" },
-  { 145, "vdis",       "boundary layer dissipation",                "W/m^2"   },
-  { 146, "ahfs",       "sensible heat flux",                        "W/m^2"   },
-  { 147, "ahfl",       "latent heat flux",                          "W/m^2"   },
-  { 148, "stream",     "streamfunction",                            "m^2/s"   },
-  { 149, "velopot",    "velocity potential",                        "m^2/s"   },
-  { 150, "xivi",       "vertically integrated cloud ice",           "kg/m^2"  },
-  { 151, "slp",        "mean sea level pressure",                   "Pa"      },
-  { 152, "lsp",        "log surface pressure",                       NULL     },
-  { 153, "xl",         "cloud water",                               "kg/kg"   },
-  { 154, "xi",         "cloud ice",                                 "kg/kg"   },
-  { 155, "sd",         "divergence",                                "1/s"     },
-  { 156, "geopoth",    "geopotential height",                       "m"       },
-  { 157, "rhumidity",  "relative humidity",                          NULL     },
-  { 159, "wind10w",    "10m windspeed over water",                  "m/s"     },
-  { 160, "runoff",     "surface runoff and drainage",               "kg/m^2s" },
-  { 161, "drain",      "drainage",                                  "kg/m^2s" },
-  { 162, "aclc",       "cloud cover",                                NULL     },
-  { 164, "aclcov",     "total cloud cover",                          NULL     },
-  { 165, "u10",        "10m u-velocity",                            "m/s"     },
-  { 166, "v10",        "10m v-velocity",                            "m/s"     },
-  { 167, "temp2",      "2m temperature",                            "K"       },
-  { 168, "dew2",       "2m dew point temperature",                  "K"       },
-  { 169, "tsurf",      "surface temperature",                       "K"       },
-  { 170, "xvar",       "variance of total water amount",            "kg/kg"   },
-  { 171, "wind10",     "10m windspeed",                             "m/s"     },
-  { 172, "slm",        "land sea mask (1. = land, 0. = sea/lakes)",  NULL     },
-  { 173, "az0",        "roughness length",                          "m"       },
-  { 174, "alb",        "surface background albedo",                  NULL     },
-  { 175, "albedo",     "surface albedo",                             NULL     },
-  { 176, "srads",      "net surface SW radiation",                  "W/m^2"   },
-  { 177, "trads",      "net surface LW radiation",                  "W/m^2"   },
-  { 178, "srad0",      "net top SW radiation",                      "W/m^2"   },
-  { 179, "trad0",      "net top LW radiation (-OLR)",               "W/m^2"   },
-  { 180, "ustr",       "u-stress",                                  "Pa"      },
-  { 181, "vstr",       "v-stress",                                  "Pa"      },
-  { 182, "evap",       "evaporation",                               "kg/m^2s" },
-  { 183, "xskew",      "skewness of total water amount qv+qi+ql",    NULL     },
-  { 184, "srad0d",     "top incoming SW radiation",                 "W/m^2"   },
-  { 185, "srafs",      "net surface SW radiation (clear sky)",      "W/m^2"   },
-  { 186, "trafs",      "net surface LW radiation (clear sky)",      "W/m^2"   },
-  { 187, "sraf0",      "net top SW radiation   (clear sky)",        "W/m^2"   },
-  { 188, "traf0",      "net top LW radiation   (clear sky)",        "W/m^2"   },
-  { 189, "sclfs",      "net surface SW cloud forcing (176-185)",    "W/m^2"   },
-  { 190, "tclfs",      "net surface LW cloud forcing (177-186)",    "W/m^2"   },
-  { 191, "sclf0",      "net SW top cloud forcing (178-187)",        "W/m^2"   },
-  { 192, "tclf0",      "net LW top cloud forcing (179-188)",        "W/m^2"   },
-  { 193, "wl",         "skin reservoir content",                    "m"       },
-  { 194, "slf",        "fractional land cover",                      NULL     },
-  { 195, "ustrgw",     "u-gravity wave stress",                     "Pa"      },
-  { 196, "vstrgw",     "v-gravity wave stress",                     "Pa"      },
-  { 197, "vdisgw",     "gravity wave dissipation",                  "W/m^2"   },
-  { 198, "vgrat",      "vegetation ratio",                           NULL     },
-  { 199, "orostd",     "orographic standard deviation",             "m"       },
-  { 200, "vlt",        "leaf area index",                            NULL     },
-  { 201, "t2max",      "maximum 2m-temperature",                    "K"       },
-  { 202, "t2min",      "minimum 2m-temperature",                    "K"       },
-  { 203, "srad0u",     "top SW radiation upward",                   "W/m^2"   },
-  { 204, "sradsu",     "surface SW radiation upward",               "W/m^2"   },
-  { 205, "tradsu",     "surface LW radiation upward",               "W/m^2"   },
-  { 206, "grndflux",   "surface ground heat flux",                   NULL     },
-  { 207, "tsoil",      "deep soil temperatures (5 layers)",         "K"       },
-  { 208, "ahfcon",     "conductive heat flux through ice",          "W/m^2"   },
-  { 209, "ahfres",     "res. heat flux for melting ice",            "W/m^2"   },
-  { 210, "seaice",     "ice cover (fraction of ice+water)",          NULL     },
-  { 211, "siced",      "ice thickness",                             "m"       },
-  { 212, "forest",     "forest fraction",                            NULL     },
-  { 213, "gld",        "glacier thickness",                         "m"       },
-  { 214, "sni",        "water equivalent of snow on ice",           "m"       },
-  { 215, "rogl",       "glacier runoff",                            "kg/m^2s" },
-  { 216, "wimax",      "maximum 10m-wind speed",                    "m/s"     },
-  { 217, "topmax",     "maximum height of convective cloud tops",   "Pa"      },
-  { 218, "snmel",      "snow melt",                                 "kg/m^2s" },
-  { 219, "runtoc",     "surface runoff into ocean",                 "kg/m^2s" },
-  { 220, "runlnd",     "surface runoff not running into ocean",     "kg/m^2s" },
-  { 221, "apmegl",     "P-E over land ice",                         "kg/m^2s" },
-  { 222, "snacl",      "snow accumulation over land",               "kg/m^2s" },
-  { 223, "aclcac",     "cloud cover",                                NULL     },
-  { 224, "tke",        "turbulent kinetic energy",                  "m^2/s^2" },
-  { 225, "tkem1",      "turbulent kinetic energy (t-1)",            "m^2/s^2" },
-  { 226, "fao",        "FAO data set (soil data flags) 0...5",       NULL     },
-  { 227, "rgcgn",      "heat capacity of soil",                      NULL     },
-  { 228, "sodif",      "soil diffusivity",                          "m^2/s"   },
-  { 229, "wsmx",       "field capacity of soil",                    "m"       },
-  { 230, "qvi",        "vertically integrated water vapor",         "kg/m^2"  },
-  { 231, "xlvi",       "vertically integrated cloud water",         "kg/m^2"  },
-  { 232, "glac",       "fraction of land covered by glaciers",       NULL     },
-  { 233, "snc",        "snow depth at the canopy",                  "m"       },
-  { 234, "rtype",      "type of convection",                        "0...3"   },
-  { 235, "abso4",      "anthropogenic sulfur burden",               "kg/m^2"  },
-  { 236, "ao3",        "ipcc ozone",                                "kg/m^2"  },
-  { 237, "tropo",      "WMO defined tropopause height",             "Pa"      },
-  { 259, "windspeed",  "windspeed (sqrt(u^2+v^2))",                 "m/s"     },
-  { 260, "precip",     "total precipitation  (142+143)",            "kg/m^2s" },
-  { 261, "net_top",    "total top radiation  (178+179)",            "W/m^2"   },
-  { 262, "net_bot",    "total surface radiation (176+177)",         "W/m^2"   },
-  { 272, "mastrfu",    "mass stream function",                      "kg/s"    },
+static const PAR echam5[] = {
+  {   4, 0, "precip",     "total precipitation",                       "kg/m^2s" },
+  {  79, 0, "swnirac",    "net surface NIR flux acc.",                 "W/m^2"   },
+  {  80, 0, "swdifnirac", "fraction of diffuse NIR acc.",              "W/m^2"   },
+  {  81, 0, "swvisac",    "net surface visible flux acc.",             "W/m^2"   },
+  {  82, 0, "swdifvisac", "fraction of diffuse visible acc.",          "W/m^2"   },
+  {  83, 0, "ocu",        "ocean eastw. velocity (coupled mode)",      "m/s"     },
+  {  84, 0, "ocv",        "ocean northw. velocity (coupled mode)",     "m/s"     },
+  {  85, 0, "tradl",      "net LW radiation 200mb",                    "W/m^2"   },
+  {  86, 0, "sradl",      "net SW radiation 200mb",                    "W/m^2"   },
+  {  87, 0, "trafl",      "net LW radiation 200mb (clear sky)",        "W/m^2"   },
+  {  88, 0, "srafl",      "net SW radiation 200mb (clear sky)",        "W/m^2"   },
+  {  89, 0, "amlcorac",   "mixed layer flux correction",               "W/m^2"   },
+  {  90, 0, "amlheatac",  "mixed layer heat content",                  "J/m^2"   },
+  {  91, 0, "trfliac",    "net LW radiation over ice",                 "W/m^2"   },
+  {  92, 0, "trflwac",    "net LW radiation over water",               "W/m^2"   },
+  {  93, 0, "trfllac",    "net LW radiation over land",                "W/m^2"   },
+  {  94, 0, "sofliac",    "net SW radiation over ice",                 "W/m^2"   },
+  {  95, 0, "soflwac",    "net SW radiation over water",               "W/m^2"   },
+  {  96, 0, "sofllac",    "net SW radiation over land",                "W/m^2"   },
+  {  97, 0, "friac",      "ice cover (fraction of grid box)",           NULL     },
+  { 102, 0, "tsi",        "surface temperature of ice",                "K"       },
+  { 103, 0, "tsw",        "surface temperature of water",              "K"       },
+  { 104, 0, "ustri",      "zonal      wind stress over ice",           "Pa"      },
+  { 105, 0, "vstri",      "meridional wind stress over ice",           "Pa"      },
+  { 106, 0, "ustrw",      "zonal      wind stress over water",         "Pa"      },
+  { 107, 0, "vstrw",      "meridional wind stress over water",         "Pa"      },
+  { 108, 0, "ustrl",      "zonal      wind stress over land",          "Pa"      },
+  { 109, 0, "vstrl",      "meridional wind stress over land",          "Pa"      },
+  { 110, 0, "ahfliac",    "latent heat flux over ice",                 "W/m^2"   },
+  { 111, 0, "ahflwac",    "latent heat flux over water",               "W/m^2"   },
+  { 112, 0, "ahfllac",    "latent heat flux over land",                "W/m^2"   },
+  { 113, 0, "evapiac",    "evaporation over ice",                      "kg/m^2s" },
+  { 114, 0, "evapwac",    "evaporation over water",                    "kg/m^2s" },
+  { 115, 0, "evaplac",    "evaporation over land",                     "kg/m^2s" },
+  { 116, 0, "az0i",       "roughness length over ice",                 "m"       },
+  { 117, 0, "az0w",       "roughness length over water",               "m"       },
+  { 118, 0, "az0l",       "roughness length over land",                "m"       },
+  { 119, 0, "ahfsiac",    "sensible heat flux over ice",               "W/m^2"   },
+  { 120, 0, "ahfswac",    "sensible heat flux over water",             "W/m^2"   },
+  { 121, 0, "ahfslac",    "sensible heat flux over land",              "W/m^2"   },
+  { 122, 0, "alsoi",      "albedo of ice",                              NULL     },
+  { 123, 0, "alsow",      "albedo of water",                            NULL     },
+  { 124, 0, "alsol",      "albedo of land",                             NULL     },
+  { 125, 0, "ahfice",     "conductive heat flux through ice",          "W/m^2"   },
+  { 126, 0, "qres",       "residual heat flux for melting sea ice",    "W/m^2"   },
+  { 127, 0, "alake",      "lake fraction",                              NULL     },
+  { 128, 0, "rintop",     "low level inversion",                        NULL     },
+  { 129, 0, "geosp",      "surface geopotential (orography)",          "m^2/s^2" },
+  { 130, 0, "t",          "temperature",                               "K"       },
+  { 131, 0, "u",          "u-velocity",                                "m/s"     },
+  { 132, 0, "v",          "v-velocity",                                "m/s"     },
+  { 133, 0, "q",          "specific humidity",                         "kg/kg"   },
+  { 134, 0, "aps",        "surface pressure",                          "Pa"      },
+  { 135, 0, "omega",      "vertical velocity",                         "Pa/s"    },
+  { 136, 0, "acdnc",      "cloud droplet number concentration",        "1/m^3"   },
+  { 137, 0, "apmeb",      "(P-E) error",                               "kg/m^2s" },
+  { 138, 0, "svo",        "vorticity",                                 "1/s"     },
+  { 139, 0, "tslm1",      "surface temperature of land",               "K"       },
+  { 140, 0, "ws",         "soil wetness",                              "m"       },
+  { 141, 0, "sn",         "water equivalent snow depth",               "m"       },
+  { 142, 0, "aprl",       "large scale precipitation",                 "kg/m^2s" },
+  { 143, 0, "aprc",       "convective  precipitation",                 "kg/m^2s" },
+  { 144, 0, "aprs",       "snow fall",                                 "kg/m^2s" },
+  { 145, 0, "vdis",       "boundary layer dissipation",                "W/m^2"   },
+  { 146, 0, "ahfs",       "sensible heat flux",                        "W/m^2"   },
+  { 147, 0, "ahfl",       "latent heat flux",                          "W/m^2"   },
+  { 148, 0, "stream",     "streamfunction",                            "m^2/s"   },
+  { 149, 0, "velopot",    "velocity potential",                        "m^2/s"   },
+  { 150, 0, "xivi",       "vertically integrated cloud ice",           "kg/m^2"  },
+  { 151, 0, "slp",        "mean sea level pressure",                   "Pa"      },
+  { 152, 0, "lsp",        "log surface pressure",                       NULL     },
+  { 153, 0, "xl",         "cloud water",                               "kg/kg"   },
+  { 154, 0, "xi",         "cloud ice",                                 "kg/kg"   },
+  { 155, 0, "sd",         "divergence",                                "1/s"     },
+  { 156, 0, "geopoth",    "geopotential height",                       "m"       },
+  { 157, 0, "rhumidity",  "relative humidity",                          NULL     },
+  { 159, 0, "wind10w",    "10m windspeed over water",                  "m/s"     },
+  { 160, 0, "runoff",     "surface runoff and drainage",               "kg/m^2s" },
+  { 161, 0, "drain",      "drainage",                                  "kg/m^2s" },
+  { 162, 0, "aclc",       "cloud cover",                                NULL     },
+  { 164, 0, "aclcov",     "total cloud cover",                          NULL     },
+  { 165, 0, "u10",        "10m u-velocity",                            "m/s"     },
+  { 166, 0, "v10",        "10m v-velocity",                            "m/s"     },
+  { 167, 0, "temp2",      "2m temperature",                            "K"       },
+  { 168, 0, "dew2",       "2m dew point temperature",                  "K"       },
+  { 169, 0, "tsurf",      "surface temperature",                       "K"       },
+  { 170, 0, "xvar",       "variance of total water amount",            "kg/kg"   },
+  { 171, 0, "wind10",     "10m windspeed",                             "m/s"     },
+  { 172, 0, "slm",        "land sea mask (1. = land, 0. = sea/lakes)",  NULL     },
+  { 173, 0, "az0",        "roughness length",                          "m"       },
+  { 174, 0, "alb",        "surface background albedo",                  NULL     },
+  { 175, 0, "albedo",     "surface albedo",                             NULL     },
+  { 176, 0, "srads",      "net surface SW radiation",                  "W/m^2"   },
+  { 177, 0, "trads",      "net surface LW radiation",                  "W/m^2"   },
+  { 178, 0, "srad0",      "net top SW radiation",                      "W/m^2"   },
+  { 179, 0, "trad0",      "net top LW radiation (-OLR)",               "W/m^2"   },
+  { 180, 0, "ustr",       "u-stress",                                  "Pa"      },
+  { 181, 0, "vstr",       "v-stress",                                  "Pa"      },
+  { 182, 0, "evap",       "evaporation",                               "kg/m^2s" },
+  { 183, 0, "xskew",      "skewness of total water amount qv+qi+ql",    NULL     },
+  { 184, 0, "srad0d",     "top incoming SW radiation",                 "W/m^2"   },
+  { 185, 0, "srafs",      "net surface SW radiation (clear sky)",      "W/m^2"   },
+  { 186, 0, "trafs",      "net surface LW radiation (clear sky)",      "W/m^2"   },
+  { 187, 0, "sraf0",      "net top SW radiation   (clear sky)",        "W/m^2"   },
+  { 188, 0, "traf0",      "net top LW radiation   (clear sky)",        "W/m^2"   },
+  { 189, 0, "sclfs",      "net surface SW cloud forcing (176-185)",    "W/m^2"   },
+  { 190, 0, "tclfs",      "net surface LW cloud forcing (177-186)",    "W/m^2"   },
+  { 191, 0, "sclf0",      "net SW top cloud forcing (178-187)",        "W/m^2"   },
+  { 192, 0, "tclf0",      "net LW top cloud forcing (179-188)",        "W/m^2"   },
+  { 193, 0, "wl",         "skin reservoir content",                    "m"       },
+  { 194, 0, "slf",        "fractional land cover",                      NULL     },
+  { 195, 0, "ustrgw",     "u-gravity wave stress",                     "Pa"      },
+  { 196, 0, "vstrgw",     "v-gravity wave stress",                     "Pa"      },
+  { 197, 0, "vdisgw",     "gravity wave dissipation",                  "W/m^2"   },
+  { 198, 0, "vgrat",      "vegetation ratio",                           NULL     },
+  { 199, 0, "orostd",     "orographic standard deviation",             "m"       },
+  { 200, 0, "vlt",        "leaf area index",                            NULL     },
+  { 201, 0, "t2max",      "maximum 2m-temperature",                    "K"       },
+  { 202, 0, "t2min",      "minimum 2m-temperature",                    "K"       },
+  { 203, 0, "srad0u",     "top SW radiation upward",                   "W/m^2"   },
+  { 204, 0, "sradsu",     "surface SW radiation upward",               "W/m^2"   },
+  { 205, 0, "tradsu",     "surface LW radiation upward",               "W/m^2"   },
+  { 206, 0, "grndflux",   "surface ground heat flux",                   NULL     },
+  { 207, 0, "tsoil",      "deep soil temperatures (5 layers)",         "K"       },
+  { 208, 0, "ahfcon",     "conductive heat flux through ice",          "W/m^2"   },
+  { 209, 0, "ahfres",     "res. heat flux for melting ice",            "W/m^2"   },
+  { 210, 0, "seaice",     "ice cover (fraction of ice+water)",          NULL     },
+  { 211, 0, "siced",      "ice thickness",                             "m"       },
+  { 212, 0, "forest",     "forest fraction",                            NULL     },
+  { 213, 0, "gld",        "glacier thickness",                         "m"       },
+  { 214, 0, "sni",        "water equivalent of snow on ice",           "m"       },
+  { 215, 0, "rogl",       "glacier runoff",                            "kg/m^2s" },
+  { 216, 0, "wimax",      "maximum 10m-wind speed",                    "m/s"     },
+  { 217, 0, "topmax",     "maximum height of convective cloud tops",   "Pa"      },
+  { 218, 0, "snmel",      "snow melt",                                 "kg/m^2s" },
+  { 219, 0, "runtoc",     "surface runoff into ocean",                 "kg/m^2s" },
+  { 220, 0, "runlnd",     "surface runoff not running into ocean",     "kg/m^2s" },
+  { 221, 0, "apmegl",     "P-E over land ice",                         "kg/m^2s" },
+  { 222, 0, "snacl",      "snow accumulation over land",               "kg/m^2s" },
+  { 223, 0, "aclcac",     "cloud cover",                                NULL     },
+  { 224, 0, "tke",        "turbulent kinetic energy",                  "m^2/s^2" },
+  { 225, 0, "tkem1",      "turbulent kinetic energy (t-1)",            "m^2/s^2" },
+  { 226, 0, "fao",        "FAO data set (soil data flags) 0...5",       NULL     },
+  { 227, 0, "rgcgn",      "heat capacity of soil",                      NULL     },
+  { 228, 0, "sodif",      "soil diffusivity",                          "m^2/s"   },
+  { 229, 0, "wsmx",       "field capacity of soil",                    "m"       },
+  { 230, 0, "qvi",        "vertically integrated water vapor",         "kg/m^2"  },
+  { 231, 0, "xlvi",       "vertically integrated cloud water",         "kg/m^2"  },
+  { 232, 0, "glac",       "fraction of land covered by glaciers",       NULL     },
+  { 233, 0, "snc",        "snow depth at the canopy",                  "m"       },
+  { 234, 0, "rtype",      "type of convection",                        "0...3"   },
+  { 235, 0, "abso4",      "anthropogenic sulfur burden",               "kg/m^2"  },
+  { 236, 0, "ao3",        "ipcc ozone",                                "kg/m^2"  },
+  { 237, 0, "tropo",      "WMO defined tropopause height",             "Pa"      },
+  { 259, 0, "windspeed",  "windspeed (sqrt(u^2+v^2))",                 "m/s"     },
+  { 260, 0, "precip",     "total precipitation  (142+143)",            "kg/m^2s" },
+  { 261, 0, "net_top",    "total top radiation  (178+179)",            "W/m^2"   },
+  { 262, 0, "net_bot",    "total surface radiation (176+177)",         "W/m^2"   },
+  { 272, 0, "mastrfu",    "mass stream function",                      "kg/s"    },
 };
 
-static PAR echam6[] = {
-  {   4, "precip",         "total precipitation",                       "kg m-2 s-1" },
-  {  34, "low_cld",        "low cloud",                                  NULL        },
-  {  35, "mid_cld",        "mid cloud",                                  NULL        },
-  {  36, "hih_cld",        "high cloud",                                 NULL        },
-  {  68, "fage",           "aging factor of snow on ice",                NULL        },
-  {  69, "snifrac",        "fraction of ice covered with snow",          NULL        },
-  {  70, "barefrac",       "bare ice fraction",                          NULL        },
-  {  71, "alsom",          "albedo of melt ponds",                       NULL        },
-  {  72, "alsobs",         "albedo of bare ice and snow",                NULL        },
-  {  73, "sicepdw",        "melt pond depth on sea-ice",                "m"          },
-  {  74, "sicepdi",        "ice thickness on melt pond",                "m"          },
-  {  75, "tsicepdi",       "ice temperature on frozen melt pond",       "K"          },
-  {  76, "sicepres",       "residual heat flux",                        "W m-2"      },
-  {  77, "ameltdepth",     "total melt pond depth",                     "m"          },
-  {  78, "ameltfrac",      "fractional area of melt ponds on sea-ice",   NULL        },
-  {  79, "albedo_vis_dir", "surface albedo visible range direct",        NULL        },
-  {  80, "albedo_nir_dir", "surface albedo NIR range direct",            NULL        },
-  {  81, "albedo_vis_dif", "surface albedo visible range diffuse",       NULL        },
-  {  82, "albedo_nir_dif", "surface albedo NIR range diffuse",           NULL        },
-  {  83, "ocu",            "ocean eastw. velocity (coupled mode)",      "m/s"        },
-  {  84, "ocv",            "ocean northw. velocity (coupled mode)",     "m/s"        },
-  {  85, "tradl",          "thermal radiation 200mb",                   "W m-2"      },
-  {  86, "sradl",          "solar radiation 200mb",                     "W m-2"      },
-  {  87, "trafl",          "thermal radiation 200mb (clear sky)",       "W m-2"      },
-  {  88, "srafl",          "solar radiation 200mb (clear sky)",         "W m-2"      },
-  {  89, "amlcorac",       "mixed layer flux correction",               "W m-2"      },
-  {  90, "amlheatac",      "mixed layer heat content",                  "J m-2"      },
-  {  91, "trfliac",        "LW flux over ice",                          "W m-2"      },
-  {  92, "trflwac",        "LW flux over water",                        "W m-2"      },
-  {  93, "trfllac",        "LW flux over land",                         "W m-2"      },
-  {  94, "sofliac",        "SW flux over ice",                          "W m-2"      },
-  {  95, "soflwac",        "SW flux over water",                        "W m-2"      },
-  {  96, "sofllac",        "SW flux over land",                         "W m-2"      },
-  {  97, "friac",          "ice cover (fraction of grid box)",           NULL        },
-  { 102, "tsi",            "surface temperature of ice",                "K"          },
-  { 103, "tsw",            "surface temperature of water",              "K"          },
-  { 104, "ustri",          "zonal      wind stress over ice",           "Pa"         },
-  { 105, "vstri",          "meridional wind stress over ice",           "Pa"         },
-  { 106, "ustrw",          "zonal      wind stress over water",         "Pa"         },
-  { 107, "vstrw",          "meridional wind stress over water",         "Pa"         },
-  { 108, "ustrl",          "zonal      wind stress over land",          "Pa"         },
-  { 109, "vstrl",          "meridional wind stress over land",          "Pa"         },
-  { 110, "ahfliac",        "latent heat flux over ice",                 "W m-2"      },
-  { 111, "ahflwac",        "latent heat flux over water",               "W m-2"      },
-  { 112, "ahfllac",        "latent heat flux over land",                "W m-2"      },
-  { 113, "evapiac",        "evaporation over ice",                      "kg m-2 s-1" },
-  { 114, "evapwac",        "evaporation over water",                    "kg m-2 s-1" },
-  { 115, "evaplac",        "evaporation over land",                     "kg m-2 s-1" },
-  { 116, "az0i",           "roughness length over ice",                 "m"          },
-  { 117, "az0w",           "roughness length over water",               "m"          },
-  { 118, "az0l",           "roughness length over land",                "m"          },
-  { 119, "ahfsiac",        "sensible heat flux over ice",               "W m-2"      },
-  { 120, "ahfswac",        "sensible heat flux over water",             "W m-2"      },
-  { 121, "ahfslac",        "sensible heat flux over land",              "W m-2"      },
-  { 122, "alsoi",          "albedo of ice",                              NULL        },
-  { 123, "alsow",          "albedo of water",                            NULL        },
-  { 124, "alsol",          "albedo of land",                             NULL        },
-  { 125, "ahfice",         "conductive heat flux",                      "W m-2"      },
-  { 126, "qres",           "residual heat flux for melting sea ice",    "W m-2"      },
-  { 127, "alake",          "lake fraction of grid box",                 "fraction"   },
-  { 128, "rintop",         "low level inversion",                        NULL        },
-  { 129, "geosp",          "surface geopotential (orography)",          "m^2/s^2"    },
-  { 130, "t",              "temperature",                               "K"          },
-  { 131, "u",              "u-velocity",                                "m/s"        },
-  { 132, "v",              "v-velocity",                                "m/s"        },
-  { 133, "q",              "specific humidity",                         "kg/kg"      },
-  { 134, "aps",            "surface pressure",                          "Pa"         },
-  { 135, "omega",          "vertical velocity",                         "Pa/s"       },
-  { 136, "acdnc",          "cloud droplet number concentration",        "1 m-3"      },
-  { 137, "apmeb",          "vert. integr. tendencies of water",         "kg m-2 s-1" },
-  { 138, "svo",            "vorticity",                                 "1/s"        },
-  { 139, "tslm1",          "surface temperature of land",               "K"          },
-  { 140, "ws",             "soil wetness",                              "m"          },
-  { 141, "sn",             "snow depth",                                "m"          },
-  { 142, "aprl",           "large scale precipitation",                 "kg m-2 s-1" },
-  { 143, "aprc",           "convective  precipitation",                 "kg m-2 s-1" },
-  { 144, "aprs",           "snow fall",                                 "kg m-2 s-1" },
-  { 145, "vdis",           "boundary layer dissipation",                "W m-2"      },
-  { 146, "ahfs",           "sensible heat flux",                        "W m-2"      },
-  { 147, "ahfl",           "latent heat flux",                          "W m-2"      },
-  { 148, "stream",         "streamfunction",                            "m^2/s"      },
-  { 149, "velopot",        "velocity potential",                        "m^2/s"      },
-  { 150, "xivi",           "vertically integrated cloud ice",           "kg m-2"     },
-  { 151, "slp",            "mean sea level pressure",                   "Pa"         },
-  { 152, "lsp",            "log surface pressure",                       NULL        },
-  { 153, "xl",             "cloud water",                               "kg/kg"      },
-  { 154, "xi",             "cloud ice",                                 "kg/kg"      },
-  { 155, "sd",             "divergence",                                "1/s"        },
-  { 156, "geopoth",        "geopotential height",                       "m"          },
-  { 157, "rhumidity",      "relative humidity",                         "fraction"   },
-  { 158, "var158",         "tendency of surface pressure",              "Pa/s"       },
-  { 159, "wind10w",        "10m windspeed over water",                  "m/s"        },
-  { 160, "runoff",         "surface runoff and drainage",               "kg m-2 s-1" },
-  { 161, "drain",          "drainage",                                  "kg m-2 s-1" },
-  { 162, "aclc",           "cloud cover",                                NULL        },
-  { 163, "aclcv",          "total cloud cover",                          NULL        },
-  { 164, "aclcov",         "total cloud cover (mean)",                   NULL        },
-  { 165, "u10",            "10m u-velocity",                            "m/s"        },
-  { 166, "v10",            "10m v-velocity",                            "m/s"        },
-  { 167, "temp2",          "2m temperature",                            "K"          },
-  { 168, "dew2",           "2m dew point temperature",                  "K"          },
-  { 169, "tsurf",          "surface temperature",                       "K"          },
-  { 170, "xvar",           "variance of total water amount qv+qi+ql",   "kg/kg"      },
-  { 171, "wind10",         "10m windspeed",                             "m/s"        },
-  { 172, "slm",            "land sea mask (1. = land, 0. = sea/lakes)",  NULL        },
-  { 173, "az0",            "roughness length",                          "m"          },
-  { 174, "alb",            "surface background albedo",                  NULL        },
-  { 175, "albedo",         "surface albedo",                             NULL        },
-  { 176, "srads",          "net surface solar radiation",               "W m-2"      },
-  { 177, "trads",          "net surface thermal radiation",             "W m-2"      },
-  { 178, "srad0",          "net top solar radiation",                   "W m-2"      },
-  { 179, "trad0",          "top thermal radiation (OLR)",               "W m-2"      },
-  { 180, "ustr",           "u-stress",                                  "Pa"         },
-  { 181, "vstr",           "v-stress",                                  "Pa"         },
-  { 182, "evap",           "evaporation",                               "kg m-2 s-1" },
-  { 183, "xskew",          "skewness of total water amount qv+qi+ql",    NULL        },
-  { 184, "srad0d",         "top incoming solar radiation",              "W m-2"      },
-  { 185, "srafs",          "net surf. solar radiation   (clear sky)",   "W m-2"      },
-  { 186, "trafs",          "net surf. thermal radiation (clear sky)",   "W m-2"      },
-  { 187, "sraf0",          "net top solar radiation     (clear sky)",   "W m-2"      },
-  { 188, "traf0",          "net top thermal radiation   (clear sky)",   "W m-2"      },
-  { 189, "sclfs",          "surface solar cloud forcing",               "W m-2"      },
-  { 190, "tclfs",          "surface thermal cloud forcing",             "W m-2"      },
-  { 191, "sclf0",          "SW top cloud forcing (178-187)",            "W m-2"      },
-  { 192, "tclf0",          "LW top cloud forcing (179-188)",            "W m-2"      },
-  { 193, "wl",             "skin reservoir content",                    "m"          },
-  { 194, "slf",            "sea land fraction",                          NULL        },
-  { 195, "ustrgw",         "u-gravity wave stress",                     "Pa"         },
-  { 196, "vstrgw",         "v-gravity wave stress",                     "Pa"         },
-  { 197, "vdisgw",         "gravity wave dissipation",                  "W m-2"      },
-  { 198, "vgrat",          "vegetation ratio",                           NULL        },
-  { 199, "orostd",         "orographic standard deviation",             "m"          },
-  { 200, "vlt",            "leaf area index",                            NULL        },
-  { 201, "t2max",          "maximum 2m-temperature",                    "K"          },
-  { 202, "t2min",          "minimum 2m-temperature",                    "K"          },
-  { 203, "srad0u",         "top solar radiation upward",                "W m-2"      },
-  { 204, "sradsu",         "surface solar radiation upward",            "W m-2"      },
-  { 205, "tradsu",         "surface thermal radiation upward",          "W m-2"      },
-  { 206, "grndflux",       "surface ground heat flux",                   NULL        },
-  { 207, "tsoil",          "deep soil temperatures (5 layers)",         "K"          },
-  { 208, "ahfcon",         "conductive heat flux through ice",          "W m-2"      },
-  { 209, "ahfres",         "melting of ice",                            "W m-2"      },
-  { 210, "seaice",         "ice cover (fraction of 1-SLM)",              NULL        },
-  { 211, "siced",          "ice depth",                                 "m"          },
-  { 212, "forest",         "forest fraction",                            NULL        },
-  { 213, "gld",            "glacier depth",                             "m"          },
-  { 214, "sni",            "water equivalent of snow on ice",           "m"          },
-  { 215, "rogl",           "glacier runoff",                            "kg m-2 s-1" },
-  { 216, "wimax",          "maximum 10m-wind speed",                    "m/s"        },
-  { 217, "topmax",         "maximum height of convective cloud tops",   "Pa"         },
-  { 218, "snmel",          "snow melt",                                 "kg m-2 s-1" },
-  { 219, "runtoc",         "surface runoff into ocean",                 "kg m-2 s-1" },
-  { 220, "runlnd",         "surface runoff not running into ocean",     "kg m-2 s-1" },
-  { 221, "apmegl",         "P-E over land ice",                         "kg m-2 s-1" },
-  { 222, "snacl",          "snow accumulation over land",               "kg m-2 s-1" },
-  { 223, "aclcac",         "cloud cover",                                NULL        },
-  { 224, "tke",            "turbulent kinetic energy",                  "m^2/s^2"    },
-  { 225, "tkem1",          "turbulent kinetic energy (t-1)",            "m^2/s^2"    },
-  { 226, "fao",            "FAO data set (soil data flags)",            "0...5"      },
-  { 227, "rgcgn",          "heat capacity of soil",                      NULL        },
-  { 228, "sodif",          "diffusivity of soil and land ice",          "m^2/s"      },
-  { 229, "wsmx",           "field capacity of soil",                    "m"          },
-  { 230, "qvi",            "vertically integrated water vapor",         "kg m-2"     },
-  { 231, "xlvi",           "vertically integrated cloud water",         "kg m-2"     },
-  { 232, "glac",           "fraction of land covered by glaciers",       NULL        },
-  { 233, "snc",            "snow depth at the canopy",                  "m"          },
-  { 234, "rtype",          "type of convection",                        "0...3"      },
-  { 235, "abso4",          "antropogenic sulfur burden",                "kg m-2"     },
-  { 236, "ao3",            "ipcc ozone",                                "kg m-2"     },
-  { 237, "tropo",          "WMO defined tropopause height",             "Pa"         },
-  { 259, "windspeed",      "windspeed (sqrt(u^2+v^2))",                 "m/s"        },
-  { 260, "precip",         "total precipitation  (142+143)",            "kg m-2 s-1" },
-  { 261, "net_top",        "total top radiation  (178+179)",            "W m-2"      },
-  { 262, "net_bot",        "total surface radiation (176+177)",         "W m-2"      },
-  { 272, "mastfru",        "mass stream function",                      "kg/s"       },
+static const PAR echam6[] = {
+  {   4, 0, "precip",         "total precipitation",                       "kg m-2 s-1" },
+  {  34, 0, "low_cld",        "low cloud",                                  NULL        },
+  {  35, 0, "mid_cld",        "mid cloud",                                  NULL        },
+  {  36, 0, "hih_cld",        "high cloud",                                 NULL        },
+  {  68, 0, "fage",           "aging factor of snow on ice",                NULL        },
+  {  69, 0, "snifrac",        "fraction of ice covered with snow",          NULL        },
+  {  70, 0, "barefrac",       "bare ice fraction",                          NULL        },
+  {  71, 0, "alsom",          "albedo of melt ponds",                       NULL        },
+  {  72, 0, "alsobs",         "albedo of bare ice and snow",                NULL        },
+  {  73, 0, "sicepdw",        "melt pond depth on sea-ice",                "m"          },
+  {  74, 0, "sicepdi",        "ice thickness on melt pond",                "m"          },
+  {  75, 0, "tsicepdi",       "ice temperature on frozen melt pond",       "K"          },
+  {  76, 0, "sicepres",       "residual heat flux",                        "W m-2"      },
+  {  77, 0, "ameltdepth",     "total melt pond depth",                     "m"          },
+  {  78, 0, "ameltfrac",      "fractional area of melt ponds on sea-ice",   NULL        },
+  {  79, 0, "albedo_vis_dir", "surface albedo visible range direct",        NULL        },
+  {  80, 0, "albedo_nir_dir", "surface albedo NIR range direct",            NULL        },
+  {  81, 0, "albedo_vis_dif", "surface albedo visible range diffuse",       NULL        },
+  {  82, 0, "albedo_nir_dif", "surface albedo NIR range diffuse",           NULL        },
+  {  83, 0, "ocu",            "ocean eastw. velocity (coupled mode)",      "m/s"        },
+  {  84, 0, "ocv",            "ocean northw. velocity (coupled mode)",     "m/s"        },
+  {  85, 0, "tradl",          "thermal radiation 200mb",                   "W m-2"      },
+  {  86, 0, "sradl",          "solar radiation 200mb",                     "W m-2"      },
+  {  87, 0, "trafl",          "thermal radiation 200mb (clear sky)",       "W m-2"      },
+  {  88, 0, "srafl",          "solar radiation 200mb (clear sky)",         "W m-2"      },
+  {  89, 0, "amlcorac",       "mixed layer flux correction",               "W m-2"      },
+  {  90, 0, "amlheatac",      "mixed layer heat content",                  "J m-2"      },
+  {  91, 0, "trfliac",        "LW flux over ice",                          "W m-2"      },
+  {  92, 0, "trflwac",        "LW flux over water",                        "W m-2"      },
+  {  93, 0, "trfllac",        "LW flux over land",                         "W m-2"      },
+  {  94, 0, "sofliac",        "SW flux over ice",                          "W m-2"      },
+  {  95, 0, "soflwac",        "SW flux over water",                        "W m-2"      },
+  {  96, 0, "sofllac",        "SW flux over land",                         "W m-2"      },
+  {  97, 0, "friac",          "ice cover (fraction of grid box)",           NULL        },
+  { 102, 0, "tsi",            "surface temperature of ice",                "K"          },
+  { 103, 0, "tsw",            "surface temperature of water",              "K"          },
+  { 104, 0, "ustri",          "zonal      wind stress over ice",           "Pa"         },
+  { 105, 0, "vstri",          "meridional wind stress over ice",           "Pa"         },
+  { 106, 0, "ustrw",          "zonal      wind stress over water",         "Pa"         },
+  { 107, 0, "vstrw",          "meridional wind stress over water",         "Pa"         },
+  { 108, 0, "ustrl",          "zonal      wind stress over land",          "Pa"         },
+  { 109, 0, "vstrl",          "meridional wind stress over land",          "Pa"         },
+  { 110, 0, "ahfliac",        "latent heat flux over ice",                 "W m-2"      },
+  { 111, 0, "ahflwac",        "latent heat flux over water",               "W m-2"      },
+  { 112, 0, "ahfllac",        "latent heat flux over land",                "W m-2"      },
+  { 113, 0, "evapiac",        "evaporation over ice",                      "kg m-2 s-1" },
+  { 114, 0, "evapwac",        "evaporation over water",                    "kg m-2 s-1" },
+  { 115, 0, "evaplac",        "evaporation over land",                     "kg m-2 s-1" },
+  { 116, 0, "az0i",           "roughness length over ice",                 "m"          },
+  { 117, 0, "az0w",           "roughness length over water",               "m"          },
+  { 118, 0, "az0l",           "roughness length over land",                "m"          },
+  { 119, 0, "ahfsiac",        "sensible heat flux over ice",               "W m-2"      },
+  { 120, 0, "ahfswac",        "sensible heat flux over water",             "W m-2"      },
+  { 121, 0, "ahfslac",        "sensible heat flux over land",              "W m-2"      },
+  { 122, 0, "alsoi",          "albedo of ice",                              NULL        },
+  { 123, 0, "alsow",          "albedo of water",                            NULL        },
+  { 124, 0, "alsol",          "albedo of land",                             NULL        },
+  { 125, 0, "ahfice",         "conductive heat flux",                      "W m-2"      },
+  { 126, 0, "qres",           "residual heat flux for melting sea ice",    "W m-2"      },
+  { 127, 0, "alake",          "lake fraction of grid box",                 "fraction"   },
+  { 128, 0, "rintop",         "low level inversion",                        NULL        },
+  { 129, 0, "geosp",          "surface geopotential (orography)",          "m^2/s^2"    },
+  { 130, 0, "t",              "temperature",                               "K"          },
+  { 131, 0, "u",              "u-velocity",                                "m/s"        },
+  { 132, 0, "v",              "v-velocity",                                "m/s"        },
+  { 133, 0, "q",              "specific humidity",                         "kg/kg"      },
+  { 134, 0, "aps",            "surface pressure",                          "Pa"         },
+  { 135, 0, "omega",          "vertical velocity",                         "Pa/s"       },
+  { 136, 0, "acdnc",          "cloud droplet number concentration",        "1 m-3"      },
+  { 137, 0, "apmeb",          "vert. integr. tendencies of water",         "kg m-2 s-1" },
+  { 138, 0, "svo",            "vorticity",                                 "1/s"        },
+  { 139, 0, "tslm1",          "surface temperature of land",               "K"          },
+  { 140, 0, "ws",             "soil wetness",                              "m"          },
+  { 141, 0, "sn",             "snow depth",                                "m"          },
+  { 142, 0, "aprl",           "large scale precipitation",                 "kg m-2 s-1" },
+  { 143, 0, "aprc",           "convective  precipitation",                 "kg m-2 s-1" },
+  { 144, 0, "aprs",           "snow fall",                                 "kg m-2 s-1" },
+  { 145, 0, "vdis",           "boundary layer dissipation",                "W m-2"      },
+  { 146, 0, "ahfs",           "sensible heat flux",                        "W m-2"      },
+  { 147, 0, "ahfl",           "latent heat flux",                          "W m-2"      },
+  { 148, 0, "stream",         "streamfunction",                            "m^2/s"      },
+  { 149, 0, "velopot",        "velocity potential",                        "m^2/s"      },
+  { 150, 0, "xivi",           "vertically integrated cloud ice",           "kg m-2"     },
+  { 151, 0, "slp",            "mean sea level pressure",                   "Pa"         },
+  { 152, 0, "lsp",            "log surface pressure",                       NULL        },
+  { 153, 0, "xl",             "cloud water",                               "kg/kg"      },
+  { 154, 0, "xi",             "cloud ice",                                 "kg/kg"      },
+  { 155, 0, "sd",             "divergence",                                "1/s"        },
+  { 156, 0, "geopoth",        "geopotential height",                       "m"          },
+  { 157, 0, "rhumidity",      "relative humidity",                         "fraction"   },
+  { 158, 0, "var158",         "tendency of surface pressure",              "Pa/s"       },
+  { 159, 0, "wind10w",        "10m windspeed over water",                  "m/s"        },
+  { 160, 0, "runoff",         "surface runoff and drainage",               "kg m-2 s-1" },
+  { 161, 0, "drain",          "drainage",                                  "kg m-2 s-1" },
+  { 162, 0, "aclc",           "cloud cover",                                NULL        },
+  { 163, 0, "aclcv",          "total cloud cover",                          NULL        },
+  { 164, 0, "aclcov",         "total cloud cover (mean)",                   NULL        },
+  { 165, 0, "u10",            "10m u-velocity",                            "m/s"        },
+  { 166, 0, "v10",            "10m v-velocity",                            "m/s"        },
+  { 167, 0, "temp2",          "2m temperature",                            "K"          },
+  { 168, 0, "dew2",           "2m dew point temperature",                  "K"          },
+  { 169, 0, "tsurf",          "surface temperature",                       "K"          },
+  { 170, 0, "xvar",           "variance of total water amount qv+qi+ql",   "kg/kg"      },
+  { 171, 0, "wind10",         "10m windspeed",                             "m/s"        },
+  { 172, 0, "slm",            "land sea mask (1. = land, 0. = sea/lakes)",  NULL        },
+  { 173, 0, "az0",            "roughness length",                          "m"          },
+  { 174, 0, "alb",            "surface background albedo",                  NULL        },
+  { 175, 0, "albedo",         "surface albedo",                             NULL        },
+  { 176, 0, "srads",          "net surface solar radiation",               "W m-2"      },
+  { 177, 0, "trads",          "net surface thermal radiation",             "W m-2"      },
+  { 178, 0, "srad0",          "net top solar radiation",                   "W m-2"      },
+  { 179, 0, "trad0",          "top thermal radiation (OLR)",               "W m-2"      },
+  { 180, 0, "ustr",           "u-stress",                                  "Pa"         },
+  { 181, 0, "vstr",           "v-stress",                                  "Pa"         },
+  { 182, 0, "evap",           "evaporation",                               "kg m-2 s-1" },
+  { 183, 0, "xskew",          "skewness of total water amount qv+qi+ql",    NULL        },
+  { 184, 0, "srad0d",         "top incoming solar radiation",              "W m-2"      },
+  { 185, 0, "srafs",          "net surf. solar radiation   (clear sky)",   "W m-2"      },
+  { 186, 0, "trafs",          "net surf. thermal radiation (clear sky)",   "W m-2"      },
+  { 187, 0, "sraf0",          "net top solar radiation     (clear sky)",   "W m-2"      },
+  { 188, 0, "traf0",          "net top thermal radiation   (clear sky)",   "W m-2"      },
+  { 189, 0, "sclfs",          "surface solar cloud forcing",               "W m-2"      },
+  { 190, 0, "tclfs",          "surface thermal cloud forcing",             "W m-2"      },
+  { 191, 0, "sclf0",          "SW top cloud forcing (178-187)",            "W m-2"      },
+  { 192, 0, "tclf0",          "LW top cloud forcing (179-188)",            "W m-2"      },
+  { 193, 0, "wl",             "skin reservoir content",                    "m"          },
+  { 194, 0, "slf",            "sea land fraction",                          NULL        },
+  { 195, 0, "ustrgw",         "u-gravity wave stress",                     "Pa"         },
+  { 196, 0, "vstrgw",         "v-gravity wave stress",                     "Pa"         },
+  { 197, 0, "vdisgw",         "gravity wave dissipation",                  "W m-2"      },
+  { 198, 0, "vgrat",          "vegetation ratio",                           NULL        },
+  { 199, 0, "orostd",         "orographic standard deviation",             "m"          },
+  { 200, 0, "vlt",            "leaf area index",                            NULL        },
+  { 201, 0, "t2max",          "maximum 2m-temperature",                    "K"          },
+  { 202, 0, "t2min",          "minimum 2m-temperature",                    "K"          },
+  { 203, 0, "srad0u",         "top solar radiation upward",                "W m-2"      },
+  { 204, 0, "sradsu",         "surface solar radiation upward",            "W m-2"      },
+  { 205, 0, "tradsu",         "surface thermal radiation upward",          "W m-2"      },
+  { 206, 0, "grndflux",       "surface ground heat flux",                   NULL        },
+  { 207, 0, "tsoil",          "deep soil temperatures (5 layers)",         "K"          },
+  { 208, 0, "ahfcon",         "conductive heat flux through ice",          "W m-2"      },
+  { 209, 0, "ahfres",         "melting of ice",                            "W m-2"      },
+  { 210, 0, "seaice",         "ice cover (fraction of 1-SLM)",              NULL        },
+  { 211, 0, "siced",          "ice depth",                                 "m"          },
+  { 212, 0, "forest",         "forest fraction",                            NULL        },
+  { 213, 0, "gld",            "glacier depth",                             "m"          },
+  { 214, 0, "sni",            "water equivalent of snow on ice",           "m"          },
+  { 215, 0, "rogl",           "glacier runoff",                            "kg m-2 s-1" },
+  { 216, 0, "wimax",          "maximum 10m-wind speed",                    "m/s"        },
+  { 217, 0, "topmax",         "maximum height of convective cloud tops",   "Pa"         },
+  { 218, 0, "snmel",          "snow melt",                                 "kg m-2 s-1" },
+  { 219, 0, "runtoc",         "surface runoff into ocean",                 "kg m-2 s-1" },
+  { 220, 0, "runlnd",         "surface runoff not running into ocean",     "kg m-2 s-1" },
+  { 221, 0, "apmegl",         "P-E over land ice",                         "kg m-2 s-1" },
+  { 222, 0, "snacl",          "snow accumulation over land",               "kg m-2 s-1" },
+  { 223, 0, "aclcac",         "cloud cover",                                NULL        },
+  { 224, 0, "tke",            "turbulent kinetic energy",                  "m^2/s^2"    },
+  { 225, 0, "tkem1",          "turbulent kinetic energy (t-1)",            "m^2/s^2"    },
+  { 226, 0, "fao",            "FAO data set (soil data flags)",            "0...5"      },
+  { 227, 0, "rgcgn",          "heat capacity of soil",                      NULL        },
+  { 228, 0, "sodif",          "diffusivity of soil and land ice",          "m^2/s"      },
+  { 229, 0, "wsmx",           "field capacity of soil",                    "m"          },
+  { 230, 0, "qvi",            "vertically integrated water vapor",         "kg m-2"     },
+  { 231, 0, "xlvi",           "vertically integrated cloud water",         "kg m-2"     },
+  { 232, 0, "glac",           "fraction of land covered by glaciers",       NULL        },
+  { 233, 0, "snc",            "snow depth at the canopy",                  "m"          },
+  { 234, 0, "rtype",          "type of convection",                        "0...3"      },
+  { 235, 0, "abso4",          "antropogenic sulfur burden",                "kg m-2"     },
+  { 236, 0, "ao3",            "ipcc ozone",                                "kg m-2"     },
+  { 237, 0, "tropo",          "WMO defined tropopause height",             "Pa"         },
+  { 259, 0, "windspeed",      "windspeed (sqrt(u^2+v^2))",                 "m/s"        },
+  { 260, 0, "precip",         "total precipitation  (142+143)",            "kg m-2 s-1" },
+  { 261, 0, "net_top",        "total top radiation  (178+179)",            "W m-2"      },
+  { 262, 0, "net_bot",        "total surface radiation (176+177)",         "W m-2"      },
+  { 272, 0, "mastfru",        "mass stream function",                      "kg/s"       },
 };
 
-static PAR mpiom1[] = {
-  {   2, "THO",      "temperature",                     "C"        },
-  {   5, "SAO",      "salinity",                        "psu"      },
-  {   3, "UKO",      "zon. velocity",                   "m/s"      },
-  {   4, "VKE",      "mer. velocity",                   "m/s"      },
-  { 303, "UKOMFL",   "zon. velocity (divergence free)", "m/s"      },
-  { 304, "VKEMFL",   "mer. velocity (divergence free)", "m/s"      },
-  {   7, "WO",       "ver. velocity",                   "m/s"      },
-  {   8, "RHO",      "insitu density",                  "kg/m**3"  },
-  {   6, "PO",       "pressure",                        "Pa"       },
-  {  67, "EMINPO",   "freshwaterflux by restoring",     "m/s"      },
-  {  70, "FLUM",     "total heatflux",                  "W/m**2"   },
-  {  79, "PEM",      "total freshwaterflux",            "m/s"      },
-  {  13, "SICTHO",   "ice thickness",                   "m"        },
-  {  15, "SICOMO",   "ice compactness",                 "frac."    },
-  {  35, "SICUO",    "zon. ice velocity",               "m/s"      },
-  {  36, "SICVE",    "mer. ice velocity",               "m/s"      },
-  {  92, "TAFO",     "surface air temperature",         "C"        },
-  { 164, "FCLOU",    "cloud cover",                      NULL      },
-  {  52, "TXO",      "surface u-stress",                "Pa/1025." },
-  {  53, "TYE",      "surface v-stress",                "Pa/1025." },
-  { 260, "FPREC",    "prescr. precipitation",           "m/s"      },
-  {  80, "FSWR",     "downward shortwave rad.",         "W/m**2"   },
-  {  81, "FTDEW",    "dewpoint temperature",            "K"        },
-  { 171, "FU10",     "10m windspeed",                   "m/s"      },
-  { 141, "SICSNO",   "snow thickness",                  "m"        },
-  { 176, "QSWO",     "heat flux shortwave",             "W/m**2"   },
-  { 177, "QLWO",     "heat flux longwave",              "W/m**2"   },
-  { 147, "QLAO",     "heat flux latent",                "W/m**2"   },
-  { 146, "QSEO",     "heat flux sensible",              "W/m**2"   },
-  {  65, "PRECO",    "net freshwater flux + runoff",    "m/s"      },
-  {   1, "ZO",       "sealevel",                        "m"        },
-  {  82, "Z1O",      "sealevel change",                 "m"        },
-  {  69, "KCONDEP",  "depth of convection",             "level"    },
-  {  27, "PSIUWE",   "hor. bar. streamfunction",        "Sv"       },
-  {  83, "AMLD",     "mixed layer depth",               "m"        },
-  { 172, "WETO",     "landseamask (pressure points)",    NULL      },
-  { 507, "AMSUE",    "landseamask (vector points v)",    NULL      },
-  { 508, "AMSUO",    "landseamask (vector points u)",    NULL      },
-  {  84, "DEPTO",    "depth at pressure points",        "m"        },
-  { 484, "DEUTO",    "depth at vector points (u)",      "m"        },
-  { 584, "DEUTE",    "depth at vector points (v)",      "m"        },
-  { 184, "DDUO",     "level thickness (vector u )",     "m"        },
-  { 284, "DDUE",     "level thickness (vector v )",     "m"        },
-  { 384, "DDPO",     "level thickness (pressure )",     "m"        },
-  {  85, "DLXP",     "grid distance x",                 "m"        },
-  {  86, "DLYP",     "grid distance y",                 "m"        },
-  { 185, "DLXU",     "grid distance x  (vector u)",     "m"        },
-  { 186, "DLYU",     "grid distance y  (vector u)",     "m"        },
-  { 285, "DLXV",     "grid distance x  (vector v)",     "m"        },
-  { 286, "DLYV",     "grid distance y  (vector v)",     "m"        },
-  {  54, "GILA",     "latitude in radiants",            "rad"      },
-  {  55, "GIPH",     "longitude in radiants",           "rad"      },
-  { 354, "ALAT",     "latitude in degrees (pressure)",  "deg"      },
-  { 355, "ALON",     "longitude in degrees (pressure)", "deg"      },
-  { 154, "ALATU",    "latitude in degrees (vector u)",  "deg"      },
-  { 155, "ALONU",    "longitude in degrees (vector u)", "deg"      },
-  { 254, "ALATV",    "latitude in degrees (vector v)",  "deg"      },
-  { 255, "ALONV",    "longitude in degrees (vector v)", "deg"      },
-  { 110, "AVO",      "vertical impuls diffusion",       "m**2/s"   },
-  { 111, "DVO",      "vertical T,S diffusion",          "m**2/s"   },
-  { 142, "SICTRU",   "seaice transport x",              "m**2/s"   },
-  { 143, "SICTRV",   "seaice transport y",              "m**2/s"   },
-  { 612, "WTMIX",    "wind mixing",                     "m**2/s"   },
-  { 183, "zmld",     "mixed layer depth (SJ)",          "m"        },
-  { 207, "WGO",      "GM vertical velocity",            "m/s"      },
-  { 305, "rivrun",   "RiverRunoff",                     "m/s"      },
-  { 158, "TMCDO",    "mon. mean depth of convection",   "level"    },
-  { 247, "DQSWO",    "heatflux sw over water",          "W/m**2"   },
-  { 248, "DQLWO",    "heatflux lw over water",          "W/m**2"   },
-  { 249, "DQSEO",    "heatflux se over water",          "W/m**2"   },
-  { 250, "DQLAO",    "heatflux la over water",          "W/m**2"   },
-  { 251, "DQTHO",    "heatflux net over water",         "W/m**2"   },
-  { 252, "DQSWI",    "heatflux sw over seaice",         "W/m**2"   },
-  { 253, "DQLWI",    "heatflux lw over seaice",         "W/m**2"   },
-  { 254, "DQSEI",    "heatflux se over seaice",         "W/m**2"   },
-  { 255, "DQLAI",    "heatflux la over seaice",         "W/m**2"   },
-  { 256, "DQTHI",    "heatflux net over seaice",        "W/m**2"   },
-  { 257, "DTICEO",   "Equi. temp over seaice",          "K"        },
-  { 270, "AOFLNHWO", "oasis net heat flux water",       "W/m**2"   },
-  { 271, "AOFLSHWO", "oasis downward short wave",       "W/m**2"   },
-  { 272, "AOFLRHIO", "oasis residual heat flux ice",    "W/m**2"   },
-  { 273, "AOFLCHIO", "oasis conduct. heat flux ice",    "W/m**2"   },
-  { 274, "AOFLFRWO", "oasis fluid fresh water flux",    "m/s"      },
-  { 275, "AOFLFRIO", "oasis solid fresh water flux",    "m/s"      },
-  { 276, "AOFLTXWO", "oasis wind stress water x",       "Pa/102"   },
-  { 277, "AOFLTYWO", "oasis wind stress water y",       "Pa/102"   },
-  { 278, "AOFLTXIO", "oasis wind stress ice x",         "Pa/102"   },
-  { 279, "AOFLTYIO", "oasis wind stress ice x",         "Pa/102"   },
-  { 280, "AOFLWSVO", "oasis wind speed",                "m/s"      },
+static const PAR mpiom1[] = {
+  {   2, 0, "THO",      "temperature",                     "C"        },
+  {   5, 0, "SAO",      "salinity",                        "psu"      },
+  {   3, 0, "UKO",      "zon. velocity",                   "m/s"      },
+  {   4, 0, "VKE",      "mer. velocity",                   "m/s"      },
+  { 303, 0, "UKOMFL",   "zon. velocity (divergence free)", "m/s"      },
+  { 304, 0, "VKEMFL",   "mer. velocity (divergence free)", "m/s"      },
+  {   7, 0, "WO",       "ver. velocity",                   "m/s"      },
+  {   8, 0, "RHO",      "insitu density",                  "kg/m**3"  },
+  {   6, 0, "PO",       "pressure",                        "Pa"       },
+  {  67, 0, "EMINPO",   "freshwaterflux by restoring",     "m/s"      },
+  {  70, 0, "FLUM",     "total heatflux",                  "W/m**2"   },
+  {  79, 0, "PEM",      "total freshwaterflux",            "m/s"      },
+  {  13, 0, "SICTHO",   "ice thickness",                   "m"        },
+  {  15, 0, "SICOMO",   "ice compactness",                 "frac."    },
+  {  35, 0, "SICUO",    "zon. ice velocity",               "m/s"      },
+  {  36, 0, "SICVE",    "mer. ice velocity",               "m/s"      },
+  {  92, 0, "TAFO",     "surface air temperature",         "C"        },
+  { 164, 0, "FCLOU",    "cloud cover",                      NULL      },
+  {  52, 0, "TXO",      "surface u-stress",                "Pa/1025." },
+  {  53, 0, "TYE",      "surface v-stress",                "Pa/1025." },
+  { 260, 0, "FPREC",    "prescr. precipitation",           "m/s"      },
+  {  80, 0, "FSWR",     "downward shortwave rad.",         "W/m**2"   },
+  {  81, 0, "FTDEW",    "dewpoint temperature",            "K"        },
+  { 171, 0, "FU10",     "10m windspeed",                   "m/s"      },
+  { 141, 0, "SICSNO",   "snow thickness",                  "m"        },
+  { 176, 0, "QSWO",     "heat flux shortwave",             "W/m**2"   },
+  { 177, 0, "QLWO",     "heat flux longwave",              "W/m**2"   },
+  { 147, 0, "QLAO",     "heat flux latent",                "W/m**2"   },
+  { 146, 0, "QSEO",     "heat flux sensible",              "W/m**2"   },
+  {  65, 0, "PRECO",    "net freshwater flux + runoff",    "m/s"      },
+  {   1, 0, "ZO",       "sealevel",                        "m"        },
+  {  82, 0, "Z1O",      "sealevel change",                 "m"        },
+  {  69, 0, "KCONDEP",  "depth of convection",             "level"    },
+  {  27, 0, "PSIUWE",   "hor. bar. streamfunction",        "Sv"       },
+  {  83, 0, "AMLD",     "mixed layer depth",               "m"        },
+  { 172, 0, "WETO",     "landseamask (pressure points)",    NULL      },
+  { 507, 0, "AMSUE",    "landseamask (vector points v)",    NULL      },
+  { 508, 0, "AMSUO",    "landseamask (vector points u)",    NULL      },
+  {  84, 0, "DEPTO",    "depth at pressure points",        "m"        },
+  { 484, 0, "DEUTO",    "depth at vector points (u)",      "m"        },
+  { 584, 0, "DEUTE",    "depth at vector points (v)",      "m"        },
+  { 184, 0, "DDUO",     "level thickness (vector u )",     "m"        },
+  { 284, 0, "DDUE",     "level thickness (vector v )",     "m"        },
+  { 384, 0, "DDPO",     "level thickness (pressure )",     "m"        },
+  {  85, 0, "DLXP",     "grid distance x",                 "m"        },
+  {  86, 0, "DLYP",     "grid distance y",                 "m"        },
+  { 185, 0, "DLXU",     "grid distance x  (vector u)",     "m"        },
+  { 186, 0, "DLYU",     "grid distance y  (vector u)",     "m"        },
+  { 285, 0, "DLXV",     "grid distance x  (vector v)",     "m"        },
+  { 286, 0, "DLYV",     "grid distance y  (vector v)",     "m"        },
+  {  54, 0, "GILA",     "latitude in radiants",            "rad"      },
+  {  55, 0, "GIPH",     "longitude in radiants",           "rad"      },
+  { 354, 0, "ALAT",     "latitude in degrees (pressure)",  "deg"      },
+  { 355, 0, "ALON",     "longitude in degrees (pressure)", "deg"      },
+  { 154, 0, "ALATU",    "latitude in degrees (vector u)",  "deg"      },
+  { 155, 0, "ALONU",    "longitude in degrees (vector u)", "deg"      },
+  { 254, 0, "ALATV",    "latitude in degrees (vector v)",  "deg"      },
+  { 255, 0, "ALONV",    "longitude in degrees (vector v)", "deg"      },
+  { 110, 0, "AVO",      "vertical impuls diffusion",       "m**2/s"   },
+  { 111, 0, "DVO",      "vertical T,S diffusion",          "m**2/s"   },
+  { 142, 0, "SICTRU",   "seaice transport x",              "m**2/s"   },
+  { 143, 0, "SICTRV",   "seaice transport y",              "m**2/s"   },
+  { 612, 0, "WTMIX",    "wind mixing",                     "m**2/s"   },
+  { 183, 0, "zmld",     "mixed layer depth (SJ)",          "m"        },
+  { 207, 0, "WGO",      "GM vertical velocity",            "m/s"      },
+  { 305, 0, "rivrun",   "RiverRunoff",                     "m/s"      },
+  { 158, 0, "TMCDO",    "mon. mean depth of convection",   "level"    },
+  { 247, 0, "DQSWO",    "heatflux sw over water",          "W/m**2"   },
+  { 248, 0, "DQLWO",    "heatflux lw over water",          "W/m**2"   },
+  { 249, 0, "DQSEO",    "heatflux se over water",          "W/m**2"   },
+  { 250, 0, "DQLAO",    "heatflux la over water",          "W/m**2"   },
+  { 251, 0, "DQTHO",    "heatflux net over water",         "W/m**2"   },
+  { 252, 0, "DQSWI",    "heatflux sw over seaice",         "W/m**2"   },
+  { 253, 0, "DQLWI",    "heatflux lw over seaice",         "W/m**2"   },
+  { 254, 0, "DQSEI",    "heatflux se over seaice",         "W/m**2"   },
+  { 255, 0, "DQLAI",    "heatflux la over seaice",         "W/m**2"   },
+  { 256, 0, "DQTHI",    "heatflux net over seaice",        "W/m**2"   },
+  { 257, 0, "DTICEO",   "Equi. temp over seaice",          "K"        },
+  { 270, 0, "AOFLNHWO", "oasis net heat flux water",       "W/m**2"   },
+  { 271, 0, "AOFLSHWO", "oasis downward short wave",       "W/m**2"   },
+  { 272, 0, "AOFLRHIO", "oasis residual heat flux ice",    "W/m**2"   },
+  { 273, 0, "AOFLCHIO", "oasis conduct. heat flux ice",    "W/m**2"   },
+  { 274, 0, "AOFLFRWO", "oasis fluid fresh water flux",    "m/s"      },
+  { 275, 0, "AOFLFRIO", "oasis solid fresh water flux",    "m/s"      },
+  { 276, 0, "AOFLTXWO", "oasis wind stress water x",       "Pa/102"   },
+  { 277, 0, "AOFLTYWO", "oasis wind stress water y",       "Pa/102"   },
+  { 278, 0, "AOFLTXIO", "oasis wind stress ice x",         "Pa/102"   },
+  { 279, 0, "AOFLTYIO", "oasis wind stress ice x",         "Pa/102"   },
+  { 280, 0, "AOFLWSVO", "oasis wind speed",                "m/s"      },
 };
 
-static PAR ecmwf[] = {
-  {   1, "STRF",   "Stream function",                                            "m**2 s**-1"            },
-  {   2, "VPOT",   "Velocity potential",                                         "m**2 s**-1"            },
-  {   3, "PT",     "Potential temperature",                                      "K"                     },
-  {   4, "EQPT",   "Equivalent potential temperature",                           "K"                     },
-  {   5, "SEPT",   "Saturated equivalent potential temperature",                 "K"                     },
-  {  11, "UDVW",   "U component of divergent wind",                              "m s**-1"               },
-  {  12, "VDVW",   "V component of divergent wind",                              "m s**-1"               },
-  {  13, "URTW",   "U component of rotational wind",                             "m s**-1"               },
-  {  14, "VRTW",   "V component of rotational wind",                             "m s**-1"               },
-  {  21, "UCTP",   "Unbalanced component of temperature",                        "K"                     },
-  {  22, "UCLN",   "Unbalanced component of logarithm of surface pressure",       NULL                   },
-  {  23, "UCDV",   "Unbalanced component of divergence",                         "s**-1"                 },
-  {  26, "CL",     "Lake cover",                                                  NULL                   },
-  {  27, "CVL",    "Low vegetation cover",                                        NULL                   },
-  {  28, "CVH",    "High vegetation cover",                                       NULL                   },
-  {  29, "TVL",    "Type of low vegetation",                                      NULL                   },
-  {  30, "TVH",    "Type of high vegetation",                                     NULL                   },
-  {  31, "CI",     "Sea-ice cover",                                               NULL                   },
-  {  32, "ASN",    "Snow albedo",                                                 NULL                   },
-  {  33, "RSN",    "Snow density kg",                                            "m**-3"                 },
-  {  34, "SSTK",   "Sea surface temperature",                                    "K"                     },
-  {  35, "ISTL1",  "Ice surface temperature layer 1",                            "K"                     },
-  {  36, "ISTL2",  "Ice surface temperature layer 2",                            "K"                     },
-  {  37, "ISTL3",  "Ice surface temperature layer 3",                            "K"                     },
-  {  38, "ISTL4",  "Ice surface temperature layer 4",                            "K"                     },
-  {  39, "SWVL1",  "Volumetric soil water layer 1",                              "m**3 m**-3"            },
-  {  40, "SWVL2",  "Volumetric soil water layer 2",                              "m**3 m**-3"            },
-  {  41, "SWVL3",  "Volumetric soil water layer 3",                              "m**3 m**-3"            },
-  {  42, "SWVL4",  "Volumetric soil water layer 4",                              "m**3 m**-3"            },
-  {  43, "SLT",    "Soil type",                                                   NULL                   },
-  {  44, "ES",     "Snow evaporation m of water",                                 NULL                   },
-  {  45, "SMLT",   "Snowmelt m of water",                                         NULL                   },
-  {  46, "SDUR",   "Solar duration",                                             "s"                     },
-  {  47, "DSRP",   "Direct solar radiation",                                     "w m**-2"               },
-  {  48, "MAGSS",  "Magnitude of surface stress",                                "N m**-2 s"             },
-  {  49, "WG10",   "Wind gust at 10 metres",                                     "m s**-1"               },
-  {  50, "LSPF",   "Large-scale precipitation fraction",                         "s"                     },
-  {  51, "MX2T24", "Maximum 2 metre temperature",                                "K"                     },
-  {  52, "MN2T24", "Minimum 2 metre temperature",                                "K"                     },
-  {  53, "MONT",   "Montgomery potential",                                       "m**2 s**-2"            },
-  {  54, "PRES",   "Pressure",                                                   "Pa"                    },
-  {  55, "MN2T24", "Mean 2 metre temperature past 24 hours",                     "K"                     },
-  {  56, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours",            "K"                     },
-  {  60, "PV",     "Potential vorticity",                                        "K m**2 kg**-1 s**-1"   },
-  { 127, "AT",     "Atmospheric tide",                                            NULL                   },
-  { 128, "BV",     "Budget values",                                               NULL                   },
-  { 129, "Z",      "Geopotential",                                               "m**2 s**-2"            },
-  { 130, "T",      "Temperature",                                                "K"                     },
-  { 131, "U",      "U velocity",                                                 "m s**-1"               },
-  { 132, "V",      "V velocity",                                                 "m s**-1"               },
-  { 133, "Q",      "Specific humidity",                                          "kg kg**-1"             },
-  { 134, "SP",     "Surface pressure",                                           "Pa"                    },
-  { 135, "W",      "Vertical velocity",                                          "Pa s**-1"              },
-  { 136, "TCW",    "Total column water",                                         "kg m**-2"              },
-  { 137, "TCWV",   "Total column water vapour",                                  "kg m**-2"              },
-  { 138, "VO",     "Vorticity (relative)",                                       "s**-1"                 },
-  { 139, "STL1",   "Soil temperature level 1",                                   "K"                     },
-  { 140, "SWL1",   "Soil wetness level 1 m of water",                             NULL                   },
-  { 141, "SD",     "Snow depth         1 m of water equivalent",                  NULL                   },
-  { 142, "LSP",    "Stratiform precipitation (Large scale precipitation)",       "m"                     },
-  { 143, "CP",     "Convective precipitation",                                   "m"                     },
-  { 144, "SF",     "Snowfall (convective + stratiform)",                         "m"                     },
-  { 145, "BLD",    "Boundary layer dissipation",                                 "W m**-2 s"             },
-  { 146, "SSHF",   "Surface sensible heat flux",                                 "W m**-2 s"             },
-  { 147, "SLHF",   "Surface latent heat flux",                                   "W m**-2 s"             },
-  { 148, "CHNK",   "Charnock",                                                    NULL                   },
-  { 149, "SNR",    "Surface net radiation",                                      "W m**-2 s"             },
-  { 150, "TNR",    "Top net radiation",                                           NULL                   },
-  { 151, "MSL",    "Mean sea-level pressure",                                    "Pa"                    },
-  { 152, "LNSP",   "Logarithm of surface pressure",                               NULL                   },
-  { 153, "SWHR",   "Short-wave heating rate",                                    "K"                     },
-  { 154, "LWHR",   "Long-wave heating rate",                                     "K"                     },
-  { 155, "D",      "Divergence",                                                 "s**-1"                 },
-  { 156, "GH",     "Height m Geopotential height",                                NULL                   },
-  { 157, "R",      "Relative humidity",                                          "%"                     },
-  { 158, "TSP",    "Tendency of surface pressure",                               "Pa s**-1"              },
-  { 159, "BLH",    "Boundary layer height",                                      "m"                     },
-  { 160, "SDOR",   "Standard deviation of orography",                             NULL                   },
-  { 161, "ISOR",   "Anisotropy of sub-gridscale orography",                       NULL                   },
-  { 162, "ANOR",   "Angle of sub-gridscale orography",                           "rad"                   },
-  { 163, "SLOR",   "Slope of sub-gridscale orography",                            NULL                   },
-  { 164, "TCC",    "Total cloud cover",                                           NULL                   },
-  { 165, "U10M",   "10 metre U wind component",                                  "m s**-1"               },
-  { 166, "V10M",   "10 metre V wind component",                                  "m s**-1"               },
-  { 167, "T2M",    "2 metre temperature",                                        "K"                     },
-  { 168, "D2M",    "2 metre dewpoint temperature",                               "K"                     },
-  { 169, "SSRD",   "Surface solar radiation downwards",                          "W m**-2 s"             },
-  { 170, "STL2",   "Soil temperature level 2",                                   "K"                     },
-  { 171, "SWL2",   "Soil wetness level 2",                                       "m of water"            },
-  { 172, "LSM",    "Land/sea mask",                                               NULL                   },
-  { 173, "SR",     "Surface roughness",                                          "m"                     },
-  { 174, "AL",     "Albedo",                                                      NULL                   },
-  { 175, "STRD",   "Surface thermal radiation downwards",                        "W m**-2 s"             },
-  { 176, "SSR",    "Surface solar radiation",                                    "W m**-2 s"             },
-  { 177, "STR",    "Surface thermal radiation",                                  "W m**-2 s"             },
-  { 178, "TSR",    "Top solar radiation",                                        "W m**-2 s"             },
-  { 179, "TTR",    "Top thermal radiation",                                      "W m**-2 s"             },
-  { 180, "EWSS",   "East/West surface stress",                                   "N m**-2 s"             },
-  { 181, "NSSS",   "North/South surface stress",                                 "N m**-2 s"             },
-  { 182, "E",      "Evaporation",                                                "m of water"            },
-  { 183, "STL3",   "Soil temperature level 3",                                   "K"                     },
-  { 184, "SWL3",   "Soil wetness level 3",                                       "m of water"            },
-  { 185, "CCC",    "Convective cloud cover",                                      NULL                   },
-  { 186, "LCC",    "Low cloud cover",                                             NULL                   },
-  { 187, "MCC",    "Medium cloud cover",                                          NULL                   },
-  { 188, "HCC",    "High cloud cover",                                            NULL                   },
-  { 189, "SUND",   "Sunshine duration",                                          "s"                     },
-  { 190, "EWOV",   "EW component of subgrid orographic variance",                "m**2"                  },
-  { 191, "NSOV",   "NS component of subgrid orographic variance",                "m**2"                  },
-  { 192, "NWOV",   "NWSE component of subgrid orographic variance",              "m**2"                  },
-  { 193, "NEOV",   "NESW component of subgrid orographic variance",              "m**2"                  },
-  { 194, "BTMP",   "Brightness temperature",                                     "K"                     },
-  { 195, "LGWS",   "Lat. component of gravity wave stress",                      "N m**-2 s"             },
-  { 196, "MGWS",   "Meridional component of gravity wave stress",                "N m**-2 s"             },
-  { 197, "GWD",    "Gravity wave dissipation",                                   "W m**-2 s"             },
-  { 198, "SRC",    "Skin reservoir content",                                     "m of water"            },
-  { 199, "VEG",    "Vegetation fraction",                                         NULL                   },
-  { 200, "VSO",    "Variance of sub-gridscale orography",                        "m**2"                  },
-  { 201, "MX2T",   "Maximum 2 metre temperature since previous post-processing", "K"                     },
-  { 202, "MN2T",   "Minimum 2 metre temperature since previous post-processing", "K"                     },
-  { 203, "O3",     "Ozone mass mixing ratio",                                    "kg kg**-1"             },
-  { 204, "PAW",    "Precipiation analysis weights",                               NULL                   },
-  { 205, "RO",     "Runoff",                                                     "m"                     },
-  { 206, "TCO3",   "Total column ozone",                                         "kg m**-2"              },
-  { 207, "WS10",   "10 meter windspeed",                                         "m s**-1"               },
-  { 208, "TSRC",   "Top net solar radiation, clear sky",                         "W m**-2"               },
-  { 209, "TTRC",   "Top net thermal radiation, clear sky",                       "W m**-2"               },
-  { 210, "SSRC",   "Surface net solar radiation, clear sky",                     "W m**-2"               },
-  { 211, "STRC",   "Surface net thermal radiation, clear sky",                   "W m**-2"               },
-  { 212, "SI",     "Solar insolation",                                           "W m**-2"               },
-  { 214, "DHR",    "Diabatic heating by radiation",                              "K"                     },
-  { 215, "DHVD",   "Diabatic heating by vertical diffusion",                     "K"                     },
-  { 216, "DHCC",   "Diabatic heating by cumulus convection",                     "K"                     },
-  { 217, "DHLC",   "Diabatic heating large-scale condensation",                  "K"                     },
-  { 218, "VDZW",   "Vertical diffusion of zonal wind",                           "m s**-1"               },
-  { 219, "VDMW",   "Vertical diffusion of meridional wind",                      "m s**-1"               },
-  { 220, "EWGD",   "EW gravity wave drag tendency",                              "m s**-1"               },
-  { 221, "NSGD",   "NS gravity wave drag tendency",                              "m s**-1"               },
-  { 222, "CTZW",   "Convective tendency of zonal wind",                          "m s**-1"               },
-  { 223, "CTMW",   "Convective tendency of meridional wind",                     "m s**-1"               },
-  { 224, "VDH",    "Vertical diffusion of humidity",                             "kg kg**-1"             },
-  { 225, "HTCC",   "Humidity tendency by cumulus convection",                    "kg kg**-1"             },
-  { 226, "HTLC",   "Humidity tendency large-scale condensation",                 "kg kg**-1"             },
-  { 227, "CRNH",   "Change from removing negative humidity",                     "kg kg**-1"             },
-  { 228, "TP",     "Total precipitation",                                        "m"                     },
-  { 229, "IEWS",   "Instantaneous X surface stress",                             "N m**-2"               },
-  { 230, "INSS",   "Instantaneous Y surface stress",                             "N m**-2"               },
-  { 231, "ISHF",   "Instantaneous surface heat flux",                            "W m**-2"               },
-  { 232, "IE",     "Instantaneous moisture flux",                                "kg m**-2 s"            },
-  { 233, "ASQ",    "Apparent surface humidity",                                  "kg kg**-1"             },
-  { 234, "LSRH",   "Logarithm of surface roughness length for heat",              NULL                   },
-  { 235, "SKT",    "Skin temperature",                                           "K"                     },
-  { 236, "STL4",   "Soil temperature level 4",                                   "K"                     },
-  { 237, "SWL4",   "Soil wetness level 4",                                       "m"                     },
-  { 238, "TSN",    "Temperature of snow layer",                                  "K"                     },
-  { 239, "CSF",    "Convective snowfall",                                        "m of water equivalent" },
-  { 240, "LSF",    "Large-scale snowfall",                                       "m of water equivalent" },
-  { 241, "ACF",    "Accumulated cloud fraction tendency",                         NULL                   },
-  { 242, "ALW",    "Accumulated liquid water tendency",                           NULL                   },
-  { 243, "FAL",    "Forecast albedo",                                             NULL                   },
-  { 244, "FSR",    "Forecast surface roughness",                                 "m"                     },
-  { 245, "FLSR",   "Forecast log of surface roughness for heat",                  NULL                   },
-  { 246, "CLWC",   "Cloud liquid water content",                                 "kg kg**-1"             },
-  { 247, "CIWC",   "Cloud ice water content",                                    "kg kg**-1"             },
-  { 248, "CC",     "Cloud cover",                                                 NULL                   },
-  { 249, "AIW",    "Accumulated ice water tendency",                              NULL                   },
-  { 250, "ICE",    "Ice age",                                                     NULL                   },
-  { 251, "ATTE",   "Adiabatic tendency of temperature",                          "K"                     },
-  { 252, "ATHE",   "Adiabatic tendency of humidity",                             "kg kg**-1"             },
-  { 253, "ATZE",   "Adiabatic tendency of zonal wind",                           "m s**-1"               },
-  { 254, "ATMW",   "Adiabatic tendency of meridional wind",                      "m s**-1"               },
+static const PAR ecmwf[] = {
+  {   1, 0, "STRF",   "Stream function",                                            "m**2 s**-1"            },
+  {   2, 0, "VPOT",   "Velocity potential",                                         "m**2 s**-1"            },
+  {   3, 0, "PT",     "Potential temperature",                                      "K"                     },
+  {   4, 0, "EQPT",   "Equivalent potential temperature",                           "K"                     },
+  {   5, 0, "SEPT",   "Saturated equivalent potential temperature",                 "K"                     },
+  {  11, 0, "UDVW",   "U component of divergent wind",                              "m s**-1"               },
+  {  12, 0, "VDVW",   "V component of divergent wind",                              "m s**-1"               },
+  {  13, 0, "URTW",   "U component of rotational wind",                             "m s**-1"               },
+  {  14, 0, "VRTW",   "V component of rotational wind",                             "m s**-1"               },
+  {  21, 0, "UCTP",   "Unbalanced component of temperature",                        "K"                     },
+  {  22, 0, "UCLN",   "Unbalanced component of logarithm of surface pressure",       NULL                   },
+  {  23, 0, "UCDV",   "Unbalanced component of divergence",                         "s**-1"                 },
+  {  26, 0, "CL",     "Lake cover",                                                  NULL                   },
+  {  27, 0, "CVL",    "Low vegetation cover",                                        NULL                   },
+  {  28, 0, "CVH",    "High vegetation cover",                                       NULL                   },
+  {  29, 0, "TVL",    "Type of low vegetation",                                      NULL                   },
+  {  30, 0, "TVH",    "Type of high vegetation",                                     NULL                   },
+  {  31, 0, "CI",     "Sea-ice cover",                                               NULL                   },
+  {  32, 0, "ASN",    "Snow albedo",                                                 NULL                   },
+  {  33, 0, "RSN",    "Snow density kg",                                            "m**-3"                 },
+  {  34, 0, "SSTK",   "Sea surface temperature",                                    "K"                     },
+  {  35, 0, "ISTL1",  "Ice surface temperature layer 1",                            "K"                     },
+  {  36, 0, "ISTL2",  "Ice surface temperature layer 2",                            "K"                     },
+  {  37, 0, "ISTL3",  "Ice surface temperature layer 3",                            "K"                     },
+  {  38, 0, "ISTL4",  "Ice surface temperature layer 4",                            "K"                     },
+  {  39, 0, "SWVL1",  "Volumetric soil water layer 1",                              "m**3 m**-3"            },
+  {  40, 0, "SWVL2",  "Volumetric soil water layer 2",                              "m**3 m**-3"            },
+  {  41, 0, "SWVL3",  "Volumetric soil water layer 3",                              "m**3 m**-3"            },
+  {  42, 0, "SWVL4",  "Volumetric soil water layer 4",                              "m**3 m**-3"            },
+  {  43, 0, "SLT",    "Soil type",                                                   NULL                   },
+  {  44, 0, "ES",     "Snow evaporation m of water",                                 NULL                   },
+  {  45, 0, "SMLT",   "Snowmelt m of water",                                         NULL                   },
+  {  46, 0, "SDUR",   "Solar duration",                                             "s"                     },
+  {  47, 0, "DSRP",   "Direct solar radiation",                                     "w m**-2"               },
+  {  48, 0, "MAGSS",  "Magnitude of surface stress",                                "N m**-2 s"             },
+  {  49, 0, "WG10",   "Wind gust at 10 metres",                                     "m s**-1"               },
+  {  50, 0, "LSPF",   "Large-scale precipitation fraction",                         "s"                     },
+  {  51, 0, "MX2T24", "Maximum 2 metre temperature",                                "K"                     },
+  {  52, 0, "MN2T24", "Minimum 2 metre temperature",                                "K"                     },
+  {  53, 0, "MONT",   "Montgomery potential",                                       "m**2 s**-2"            },
+  {  54, 0, "PRES",   "Pressure",                                                   "Pa"                    },
+  {  55, 0, "MN2T24", "Mean 2 metre temperature past 24 hours",                     "K"                     },
+  {  56, 0, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours",            "K"                     },
+  {  60, 0, "PV",     "Potential vorticity",                                        "K m**2 kg**-1 s**-1"   },
+  { 127, 0, "AT",     "Atmospheric tide",                                            NULL                   },
+  { 128, 0, "BV",     "Budget values",                                               NULL                   },
+  { 129, 0, "Z",      "Geopotential",                                               "m**2 s**-2"            },
+  { 130, 0, "T",      "Temperature",                                                "K"                     },
+  { 131, 0, "U",      "U velocity",                                                 "m s**-1"               },
+  { 132, 0, "V",      "V velocity",                                                 "m s**-1"               },
+  { 133, 0, "Q",      "Specific humidity",                                          "kg kg**-1"             },
+  { 134, 0, "SP",     "Surface pressure",                                           "Pa"                    },
+  { 135, 0, "W",      "Vertical velocity",                                          "Pa s**-1"              },
+  { 136, 0, "TCW",    "Total column water",                                         "kg m**-2"              },
+  { 137, 0, "TCWV",   "Total column water vapour",                                  "kg m**-2"              },
+  { 138, 0, "VO",     "Vorticity (relative)",                                       "s**-1"                 },
+  { 139, 0, "STL1",   "Soil temperature level 1",                                   "K"                     },
+  { 140, 0, "SWL1",   "Soil wetness level 1 m of water",                             NULL                   },
+  { 141, 0, "SD",     "Snow depth         1 m of water equivalent",                  NULL                   },
+  { 142, 0, "LSP",    "Stratiform precipitation (Large scale precipitation)",       "m"                     },
+  { 143, 0, "CP",     "Convective precipitation",                                   "m"                     },
+  { 144, 0, "SF",     "Snowfall (convective + stratiform)",                         "m"                     },
+  { 145, 0, "BLD",    "Boundary layer dissipation",                                 "W m**-2 s"             },
+  { 146, 0, "SSHF",   "Surface sensible heat flux",                                 "W m**-2 s"             },
+  { 147, 0, "SLHF",   "Surface latent heat flux",                                   "W m**-2 s"             },
+  { 148, 0, "CHNK",   "Charnock",                                                    NULL                   },
+  { 149, 0, "SNR",    "Surface net radiation",                                      "W m**-2 s"             },
+  { 150, 0, "TNR",    "Top net radiation",                                           NULL                   },
+  { 151, 0, "MSL",    "Mean sea-level pressure",                                    "Pa"                    },
+  { 152, 0, "LNSP",   "Logarithm of surface pressure",                               NULL                   },
+  { 153, 0, "SWHR",   "Short-wave heating rate",                                    "K"                     },
+  { 154, 0, "LWHR",   "Long-wave heating rate",                                     "K"                     },
+  { 155, 0, "D",      "Divergence",                                                 "s**-1"                 },
+  { 156, 0, "GH",     "Height m Geopotential height",                                NULL                   },
+  { 157, 0, "R",      "Relative humidity",                                          "%"                     },
+  { 158, 0, "TSP",    "Tendency of surface pressure",                               "Pa s**-1"              },
+  { 159, 0, "BLH",    "Boundary layer height",                                      "m"                     },
+  { 160, 0, "SDOR",   "Standard deviation of orography",                             NULL                   },
+  { 161, 0, "ISOR",   "Anisotropy of sub-gridscale orography",                       NULL                   },
+  { 162, 0, "ANOR",   "Angle of sub-gridscale orography",                           "rad"                   },
+  { 163, 0, "SLOR",   "Slope of sub-gridscale orography",                            NULL                   },
+  { 164, 0, "TCC",    "Total cloud cover",                                           NULL                   },
+  { 165, 0, "U10M",   "10 metre U wind component",                                  "m s**-1"               },
+  { 166, 0, "V10M",   "10 metre V wind component",                                  "m s**-1"               },
+  { 167, 0, "T2M",    "2 metre temperature",                                        "K"                     },
+  { 168, 0, "D2M",    "2 metre dewpoint temperature",                               "K"                     },
+  { 169, 0, "SSRD",   "Surface solar radiation downwards",                          "W m**-2 s"             },
+  { 170, 0, "STL2",   "Soil temperature level 2",                                   "K"                     },
+  { 171, 0, "SWL2",   "Soil wetness level 2",                                       "m of water"            },
+  { 172, 0, "LSM",    "Land/sea mask",                                               NULL                   },
+  { 173, 0, "SR",     "Surface roughness",                                          "m"                     },
+  { 174, 0, "AL",     "Albedo",                                                      NULL                   },
+  { 175, 0, "STRD",   "Surface thermal radiation downwards",                        "W m**-2 s"             },
+  { 176, 0, "SSR",    "Surface solar radiation",                                    "W m**-2 s"             },
+  { 177, 0, "STR",    "Surface thermal radiation",                                  "W m**-2 s"             },
+  { 178, 0, "TSR",    "Top solar radiation",                                        "W m**-2 s"             },
+  { 179, 0, "TTR",    "Top thermal radiation",                                      "W m**-2 s"             },
+  { 180, 0, "EWSS",   "East/West surface stress",                                   "N m**-2 s"             },
+  { 181, 0, "NSSS",   "North/South surface stress",                                 "N m**-2 s"             },
+  { 182, 0, "E",      "Evaporation",                                                "m of water"            },
+  { 183, 0, "STL3",   "Soil temperature level 3",                                   "K"                     },
+  { 184, 0, "SWL3",   "Soil wetness level 3",                                       "m of water"            },
+  { 185, 0, "CCC",    "Convective cloud cover",                                      NULL                   },
+  { 186, 0, "LCC",    "Low cloud cover",                                             NULL                   },
+  { 187, 0, "MCC",    "Medium cloud cover",                                          NULL                   },
+  { 188, 0, "HCC",    "High cloud cover",                                            NULL                   },
+  { 189, 0, "SUND",   "Sunshine duration",                                          "s"                     },
+  { 190, 0, "EWOV",   "EW component of subgrid orographic variance",                "m**2"                  },
+  { 191, 0, "NSOV",   "NS component of subgrid orographic variance",                "m**2"                  },
+  { 192, 0, "NWOV",   "NWSE component of subgrid orographic variance",              "m**2"                  },
+  { 193, 0, "NEOV",   "NESW component of subgrid orographic variance",              "m**2"                  },
+  { 194, 0, "BTMP",   "Brightness temperature",                                     "K"                     },
+  { 195, 0, "LGWS",   "Lat. component of gravity wave stress",                      "N m**-2 s"             },
+  { 196, 0, "MGWS",   "Meridional component of gravity wave stress",                "N m**-2 s"             },
+  { 197, 0, "GWD",    "Gravity wave dissipation",                                   "W m**-2 s"             },
+  { 198, 0, "SRC",    "Skin reservoir content",                                     "m of water"            },
+  { 199, 0, "VEG",    "Vegetation fraction",                                         NULL                   },
+  { 200, 0, "VSO",    "Variance of sub-gridscale orography",                        "m**2"                  },
+  { 201, 0, "MX2T",   "Maximum 2 metre temperature since previous post-processing", "K"                     },
+  { 202, 0, "MN2T",   "Minimum 2 metre temperature since previous post-processing", "K"                     },
+  { 203, 0, "O3",     "Ozone mass mixing ratio",                                    "kg kg**-1"             },
+  { 204, 0, "PAW",    "Precipiation analysis weights",                               NULL                   },
+  { 205, 0, "RO",     "Runoff",                                                     "m"                     },
+  { 206, 0, "TCO3",   "Total column ozone",                                         "kg m**-2"              },
+  { 207, 0, "WS10",   "10 meter windspeed",                                         "m s**-1"               },
+  { 208, 0, "TSRC",   "Top net solar radiation, clear sky",                         "W m**-2"               },
+  { 209, 0, "TTRC",   "Top net thermal radiation, clear sky",                       "W m**-2"               },
+  { 210, 0, "SSRC",   "Surface net solar radiation, clear sky",                     "W m**-2"               },
+  { 211, 0, "STRC",   "Surface net thermal radiation, clear sky",                   "W m**-2"               },
+  { 212, 0, "SI",     "Solar insolation",                                           "W m**-2"               },
+  { 214, 0, "DHR",    "Diabatic heating by radiation",                              "K"                     },
+  { 215, 0, "DHVD",   "Diabatic heating by vertical diffusion",                     "K"                     },
+  { 216, 0, "DHCC",   "Diabatic heating by cumulus convection",                     "K"                     },
+  { 217, 0, "DHLC",   "Diabatic heating large-scale condensation",                  "K"                     },
+  { 218, 0, "VDZW",   "Vertical diffusion of zonal wind",                           "m s**-1"               },
+  { 219, 0, "VDMW",   "Vertical diffusion of meridional wind",                      "m s**-1"               },
+  { 220, 0, "EWGD",   "EW gravity wave drag tendency",                              "m s**-1"               },
+  { 221, 0, "NSGD",   "NS gravity wave drag tendency",                              "m s**-1"               },
+  { 222, 0, "CTZW",   "Convective tendency of zonal wind",                          "m s**-1"               },
+  { 223, 0, "CTMW",   "Convective tendency of meridional wind",                     "m s**-1"               },
+  { 224, 0, "VDH",    "Vertical diffusion of humidity",                             "kg kg**-1"             },
+  { 225, 0, "HTCC",   "Humidity tendency by cumulus convection",                    "kg kg**-1"             },
+  { 226, 0, "HTLC",   "Humidity tendency large-scale condensation",                 "kg kg**-1"             },
+  { 227, 0, "CRNH",   "Change from removing negative humidity",                     "kg kg**-1"             },
+  { 228, 0, "TP",     "Total precipitation",                                        "m"                     },
+  { 229, 0, "IEWS",   "Instantaneous X surface stress",                             "N m**-2"               },
+  { 230, 0, "INSS",   "Instantaneous Y surface stress",                             "N m**-2"               },
+  { 231, 0, "ISHF",   "Instantaneous surface heat flux",                            "W m**-2"               },
+  { 232, 0, "IE",     "Instantaneous moisture flux",                                "kg m**-2 s"            },
+  { 233, 0, "ASQ",    "Apparent surface humidity",                                  "kg kg**-1"             },
+  { 234, 0, "LSRH",   "Logarithm of surface roughness length for heat",              NULL                   },
+  { 235, 0, "SKT",    "Skin temperature",                                           "K"                     },
+  { 236, 0, "STL4",   "Soil temperature level 4",                                   "K"                     },
+  { 237, 0, "SWL4",   "Soil wetness level 4",                                       "m"                     },
+  { 238, 0, "TSN",    "Temperature of snow layer",                                  "K"                     },
+  { 239, 0, "CSF",    "Convective snowfall",                                        "m of water equivalent" },
+  { 240, 0, "LSF",    "Large-scale snowfall",                                       "m of water equivalent" },
+  { 241, 0, "ACF",    "Accumulated cloud fraction tendency",                         NULL                   },
+  { 242, 0, "ALW",    "Accumulated liquid water tendency",                           NULL                   },
+  { 243, 0, "FAL",    "Forecast albedo",                                             NULL                   },
+  { 244, 0, "FSR",    "Forecast surface roughness",                                 "m"                     },
+  { 245, 0, "FLSR",   "Forecast log of surface roughness for heat",                  NULL                   },
+  { 246, 0, "CLWC",   "Cloud liquid water content",                                 "kg kg**-1"             },
+  { 247, 0, "CIWC",   "Cloud ice water content",                                    "kg kg**-1"             },
+  { 248, 0, "CC",     "Cloud cover",                                                 NULL                   },
+  { 249, 0, "AIW",    "Accumulated ice water tendency",                              NULL                   },
+  { 250, 0, "ICE",    "Ice age",                                                     NULL                   },
+  { 251, 0, "ATTE",   "Adiabatic tendency of temperature",                          "K"                     },
+  { 252, 0, "ATHE",   "Adiabatic tendency of humidity",                             "kg kg**-1"             },
+  { 253, 0, "ATZE",   "Adiabatic tendency of zonal wind",                           "m s**-1"               },
+  { 254, 0, "ATMW",   "Adiabatic tendency of meridional wind",                      "m s**-1"               },
 };
 
-static PAR remo[] = {
-  {  14, "FTKVM",     "turbulent transfer coefficient of momentum in the atmosphere",   NULL           },
-  {  15, "FTKVH",     "turbulent transfer coefficient of heat in the atmosphere",       NULL           },
-  {  38, "U10ER",     "10m u-velocity",                                                "m/s"           },
-  {  39, "V10ER",     "10m v-velocity",                                                "m/s"           },
-  {  40, "CAPE",      "convetive available potential energy",                           NULL           },
-  {  41, "GHPBL",     "height of the planetary boudary layer",                         "gpm"           },
-  {  42, "BETA",      "BETA",                                                           NULL           },
-  {  43, "WMINLOK",   "WMINLOK",                                                        NULL           },
-  {  44, "WMAXLOK",   "WMAXLOK",                                                        NULL           },
-  {  45, "VBM10M",    "maximum of the expected gust velocity near the surface",        "m/s"           },
-  {  46, "BFLHS",     "surface sensible heat flux",                                    "W/m**2"        },
-  {  47, "BFLQDS",    "surface latent heat flux",                                      "W/m**2"        },
-  {  48, "TMCM",      "turbulent transfer coefficient of momentum at the surface",      NULL           },
-  {  49, "TRSOL",     "TRSOL",                                                          NULL           },
-  {  50, "TMCH",      "turbulent transfer coefficient of heat at the surface",          NULL           },
-  {  51, "EMTEF",     "EMTEF",                                                          NULL           },
-  {  52, "TRSOF",     "TRSOF",                                                          NULL           },
-  {  53, "DRAIN",     "drainage",                                                      "mm"            },
-  {  54, "TSL",       "surface temperature (land)",                                    "K"             },
-  {  55, "TSW",       "surface temperature (water)",                                   "K"             },
-  {  56, "TSI",       "surface temperature (ice)",                                     "K"             },
-  {  57, "USTRL",     "surface u-stress (land)",                                       "Pa"            },
-  {  58, "USTRW",     "surface u-stress (water)",                                      "Pa"            },
-  {  59, "USTRI",     "surface u-stress (ice)",                                        "Pa"            },
-  {  60, "VSTRL",     "surface v-stress (land)",                                       "Pa"            },
-  {  61, "VSTRW",     "surface v-stress (water)",                                      "Pa"            },
-  {  62, "VSTRI",     "surface v-stress (ice)",                                        "Pa"            },
-  {  63, "EVAPL",     "surface evaporation (land)",                                    "mm"            },
-  {  64, "EVAPW",     "surface evaporation (water)",                                   "mm"            },
-  {  65, "EVAPI",     "surface evaporation (ice)",                                     "mm"            },
-  {  66, "AHFLL",     "surface latent heat flux (land)",                               "W/m**2"        },
-  {  67, "AHFLW",     "surface latent heat flux (water)",                              "W/m**2"        },
-  {  68, "AHFLI",     "surface latent heat flux (ice)",                                "W/m**2"        },
-  {  69, "AHFSL",     "surface sensible heat flux (land)",                             "W/m**2"        },
-  {  70, "AHFSW",     "surface sensible heat flux (water)",                            "W/m**2"        },
-  {  71, "AHFSI",     "surface sensible heat flux (ice)",                              "W/m**2"        },
-  {  72, "AZ0L",      "surface roughness length (land)",                               "m"             },
-  {  73, "AZ0W",      "surface roughness length (water)",                              "m"             },
-  {  74, "AZ0I",      "surface roughness length (ice)",                                "m"             },
-  {  75, "ALSOL",     "surface albedo (land)",                                         "fract."        },
-  {  76, "ALSOW",     "surface albedo (water)",                                        "fract."        },
-  {  77, "ALSOI",     "surface albedo (ice)",                                          "fract."        },
-  {  81, "TMCHL",     "turbulent transfer coefficient of heat at the surface (land)",   NULL           },
-  {  82, "TMCHW",     "turbulent transfer coefficient of heat at the surface (water)",  NULL           },
-  {  83, "TMCHI",     "turbulent transfer coefficient of heat at the surface (ice)",    NULL           },
-  {  84, "QDBL",      "specific humidity surface (land)",                              "kg/kg"         },
-  {  85, "QDBW",      "specific humidity surface (water)",                             "kg/kg"         },
-  {  86, "QDBI",      "specific humidity surface (ice)",                               "kg/kg"         },
-  {  87, "BFLHSL",    "surface sensible heat flux (land)",                             "W/m**2"        },
-  {  88, "BFLHSW",    "surface sensible heat flux (water)",                            "W/m**2"        },
-  {  89, "BFLHSI",    "surface sensible heat flux (ice)",                              "W/m**2"        },
-  {  90, "BFLQDSL",   "surface latent heat flux (land)",                               "W/m**2"        },
-  {  91, "BFLQDSW",   "surface latent heat flux (water)",                              "W/m**2"        },
-  {  92, "BFLQDSI",   "surface latent heat flux (ice)",                                "W/m**2"        },
-  {  93, "AHFICE",    "sea-ice: conductive heat",                                      "W/m"           },
-  {  94, "QRES",      "residual heat flux for melting sea ice",                        "W/m**2"        },
-  {  95, "SRFL",      "SRFL",                                                           NULL           },
-  {  96, "QDBOXS",    "horizontal transport of water vapour",                          "kg/m**2"       },
-  {  97, "QWBOXS",    "horizontal transport of cloud water",                           "kg/m**2"       },
-  {  98, "EKBOXS",    "horizontal transport of kinetic energy",                        "(3600*J)/m**2" },
-  {  99, "FHBOXS",    "horizontal transport of sensible heat",                         "(3600*J)/m**2" },
-  { 100, "FIBOXS",    "horizontal transport of potential energy",                      "(3600*J)/m**2" },
-  { 101, "TLAMBDA",   "heat conductivity of dry soil",                                 "W/(K*m)"       },
-  { 103, "DLAMBDA",   "parameter for increasing the heat conductivity of the soil",     NULL           },
-  { 104, "PORVOL",    "pore volume",                                                    NULL           },
-  { 105, "FCAP",      "field capacity of soil",                                         NULL           },
-  { 106, "WI3",       "fraction of frozen soil",                                        NULL           },
-  { 107, "WI4",       "fraction of frozen soil",                                        NULL           },
-  { 108, "WI5",       "fraction of frozen soil",                                        NULL           },
-  { 109, "WI",        "fraction of frozen soil",                                        NULL           },
-  { 110, "WICL",      "fraction of frozen soil",                                        NULL           },
-  { 112, "QDB",       "specific humidity surface",                                     "kg/kg"         },
-  { 129, "FIB",       "surface geopotential (orography)",                              "m"             },
-  { 130, "T",         "temperature",                                                   "K"             },
-  { 131, "U",         "u-velocity",                                                    "m/s"           },
-  { 132, "V",         "v-velocity",                                                    "m/s"           },
-  { 133, "QD",        "specific humidity",                                             "kg/kg"         },
-  { 134, "PS",        "Surface pressure",                                              "Pa"            },
-  { 135, "VERVEL",    "Vertical velocity",                                             "Pa/s"          },
-  { 138, "SVO",       "vorticity",                                                     "1/s"           },
-  { 139, "TS",        "surface temperature",                                           "K"             },
-  { 140, "WS",        "soil wetness",                                                  "m"             },
-  { 141, "SN",        "snow depth",                                                    "m"             },
-  { 142, "APRL",      "large scale precipitation",                                     "mm"            },
-  { 143, "APRC",      "convective  precipitation",                                     "mm"            },
-  { 144, "APRS",      "snow fall",                                                     "mm"            },
-  { 145, "VDIS",      "boundary layer dissipation",                                    "W/m**2"        },
-  { 146, "AHFS",      "surface sensible heat flux",                                    "W/m**2"        },
-  { 147, "AHFL",      "surface latent heat flux",                                      "W/m**2"        },
-  { 148, "STREAM",    "streamfunction",                                                "m**2/s"        },
-  { 149, "VELOPOT",   "velocity potential",                                            "m**2/s"        },
-  { 151, "PSRED",     "mean sea level pressure",                                       "Pa"            },
-  { 152, "LSP",       "log surface pressure",                                           NULL           },
-  { 153, "QW",        "liquid water content",                                          "kg/kg"         },
-  { 155, "SD",        "divergence",                                                    "1/s"           },
-  { 156, "FI",        "geopotential height",                                           "gpm"           },
-  { 159, "USTAR3",    "ustar**3",                                                      "m**3/s**3"     },
-  { 160, "RUNOFF",    "surface runoff",                                                "mm"            },
-  { 162, "ACLC",      "cloud cover",                                                   "fract."        },
-  { 163, "ACLCV",     "total cloud cover",                                             "fract."        },
-  { 164, "ACLCOV",    "total cloud cover",                                             "fract."        },
-  { 165, "U10",       "10m u-velocity",                                                "m/s"           },
-  { 166, "V10",       "10m v-velocity",                                                "m/s"           },
-  { 167, "TEMP2",     "2m temperature",                                                "K"             },
-  { 168, "DEW2",      "2m dew point temperature",                                      "K"             },
-  { 169, "TSURF",     "surface temperature (land)",                                    "K"             },
-  { 170, "TD",        "deep soil temperature",                                         "K"             },
-  { 171, "WIND10",    "10m windspeed",                                                 "m/s"           },
-  { 172, "BLA",       "land sea mask",                                                 "fract."        },
-  { 173, "AZ0",       "surface roughness length",                                      "m"             },
-  { 174, "ALB",       "surface background albedo",                                     "fract."        },
-  { 175, "ALBEDO",    "surface albedo",                                                "fract."        },
-  { 176, "SRADS",     "net surface solar radiation",                                   "W/m**2"        },
-  { 177, "TRADS",     "net surface thermal radiation",                                 "W/m**2"        },
-  { 178, "SRAD0",     "net top solar radiation",                                       "W/m**2"        },
-  { 179, "TRAD0",     "top thermal radiation (OLR)",                                   "W/m**2"        },
-  { 180, "USTR",      "surface u-stress",                                              "Pa"            },
-  { 181, "VSTR",      "surface v-stress",                                              "Pa"            },
-  { 182, "EVAP",      "surface evaporation",                                           "mm"            },
-  { 183, "TDCL",      "soil temperature",                                              "K"             },
-  { 185, "SRAFS",     "net surf. solar radiation   (clear sky)",                       "W/m**2"        },
-  { 186, "TRAFS",     "net surf. thermal radiation (clear sky)",                       "W/m**2"        },
-  { 187, "SRAF0",     "net top solar radiation     (clear sky)",                       "W/m**2"        },
-  { 188, "TRAF0",     "net top thermal radiation   (clear sky)",                       "W/m**2"        },
-  { 189, "SCLFS",     "surface solar cloud forcing",                                   "W/m**2"        },
-  { 190, "TCLFS",     "surface thermal cloud forcing",                                 "W/m**2"        },
-  { 191, "SCLF0",     "top solar cloud forcing",                                       "W/m**2"        },
-  { 192, "TCLF0",     "top thermal cloud forcing",                                     "W/m**2"        },
-  { 194, "WL",        "skin reservoir content",                                        "m"             },
-  { 195, "USTRGW",    "u-gravity wave stress",                                         "Pa"            },
-  { 196, "VSTRGW",    "v-gravity wave stress",                                         "Pa"            },
-  { 197, "VDISGW",    "gravity wave dissipation",                                      "W/m**2"        },
-  { 198, "VGRAT",     "vegetation ratio",                                               NULL           },
-  { 199, "VAROR",     "orographic variance (for surface runoff)",                       NULL           },
-  { 200, "VLT",       "leaf area index",                                                NULL           },
-  { 201, "T2MAX",     "maximum 2m-temperature",                                        "K"             },
-  { 202, "T2MIN",     "minimum 2m-temperature",                                        "K"             },
-  { 203, "SRAD0U",    "top solar radiation upward",                                    "W/m**2"        },
-  { 204, "SRADSU",    "surface solar radiation upward",                                "W/m**2"        },
-  { 205, "TRADSU",    "surface thermal radiation upward",                              "W/m**2"        },
-  { 206, "TSN",       "snow temperature",                                              "K"             },
-  { 207, "TD3",       "soil temperature",                                              "K"             },
-  { 208, "TD4",       "soil temperature",                                              "K"             },
-  { 209, "TD5",       "soil temperature",                                              "K"             },
-  { 210, "SEAICE",    "sea ice cover",                                                 "fract."        },
-  { 211, "SICED",     "sea ice depth",                                                 "m"             },
-  { 212, "FOREST",    "vegetation type",                                                NULL           },
-  { 213, "TEFF",      "(effective) sea-ice skin temperature",                          "K"             },
-  { 214, "TSMAX",     "maximum surface temperature",                                   "K"             },
-  { 215, "TSMIN",     "minimum surface temperature",                                   "K"             },
-  { 216, "WIMAX",     "maximum 10m-wind speed",                                        "m/s"           },
-  { 217, "TOPMAX",    "maximum height of convective cloud tops",                       "Pa"            },
-  { 218, "SNMEL",     "snow melt",                                                     "mm"            },
-  { 220, "TSLIN",     "land: residual surface heat budget",                            "W/m**2"        },
-  { 221, "DSNAC",     "snow depth change",                                             "mm"            },
-  { 222, "EMTER",     "EMTER",                                                          NULL           },
-  { 223, "ACLCAC",    "cloud cover",                                                   "fract."        },
-  { 224, "TKE",       "turbulent kinetic energy",                                       NULL           },
-  { 226, "FAO",       "FAO data set (soil data flags)",                                 NULL           },
-  { 227, "RGCGN",     "heat capacity of soil",                                          NULL           },
-  { 229, "WSMX",      "field capacity of soil",                                         NULL           },
-  { 230, "QVI",       "vertically integrated specific humidity",                       "kg/m**2"       },
-  { 231, "ALWCVI",    "vertically integrated liquid water cont.",                      "kg/m**2"       },
-  { 232, "GLAC",      "glacier mask",                                                   NULL           },
-  { 253, "PHI",       "latitude in real coordinates",                                  "degrees_north" },
-  { 254, "RLA",       "longitude in real coordinates",                                 "degrees_east"  },
-  { 259, "WINDSPEED", "windspeed (sqrt(u**2+v**2))",                                    NULL           },
-  { 260, "PRECIP",    "total precipitation",                                            NULL           },
+static const PAR remo[] = {
+  {  14, 0, "FTKVM",     "turbulent transfer coefficient of momentum in the atmosphere",   NULL           },
+  {  15, 0, "FTKVH",     "turbulent transfer coefficient of heat in the atmosphere",       NULL           },
+  {  38, 0, "U10ER",     "10m u-velocity",                                                "m/s"           },
+  {  39, 0, "V10ER",     "10m v-velocity",                                                "m/s"           },
+  {  40, 0, "CAPE",      "convetive available potential energy",                           NULL           },
+  {  41, 0, "GHPBL",     "height of the planetary boudary layer",                         "gpm"           },
+  {  42, 0, "BETA",      "BETA",                                                           NULL           },
+  {  43, 0, "WMINLOK",   "WMINLOK",                                                        NULL           },
+  {  44, 0, "WMAXLOK",   "WMAXLOK",                                                        NULL           },
+  {  45, 0, "VBM10M",    "maximum of the expected gust velocity near the surface",        "m/s"           },
+  {  46, 0, "BFLHS",     "surface sensible heat flux",                                    "W/m**2"        },
+  {  47, 0, "BFLQDS",    "surface latent heat flux",                                      "W/m**2"        },
+  {  48, 0, "TMCM",      "turbulent transfer coefficient of momentum at the surface",      NULL           },
+  {  49, 0, "TRSOL",     "TRSOL",                                                          NULL           },
+  {  50, 0, "TMCH",      "turbulent transfer coefficient of heat at the surface",          NULL           },
+  {  51, 0, "EMTEF",     "EMTEF",                                                          NULL           },
+  {  52, 0, "TRSOF",     "TRSOF",                                                          NULL           },
+  {  53, 0, "DRAIN",     "drainage",                                                      "mm"            },
+  {  54, 0, "TSL",       "surface temperature (land)",                                    "K"             },
+  {  55, 0, "TSW",       "surface temperature (water)",                                   "K"             },
+  {  56, 0, "TSI",       "surface temperature (ice)",                                     "K"             },
+  {  57, 0, "USTRL",     "surface u-stress (land)",                                       "Pa"            },
+  {  58, 0, "USTRW",     "surface u-stress (water)",                                      "Pa"            },
+  {  59, 0, "USTRI",     "surface u-stress (ice)",                                        "Pa"            },
+  {  60, 0, "VSTRL",     "surface v-stress (land)",                                       "Pa"            },
+  {  61, 0, "VSTRW",     "surface v-stress (water)",                                      "Pa"            },
+  {  62, 0, "VSTRI",     "surface v-stress (ice)",                                        "Pa"            },
+  {  63, 0, "EVAPL",     "surface evaporation (land)",                                    "mm"            },
+  {  64, 0, "EVAPW",     "surface evaporation (water)",                                   "mm"            },
+  {  65, 0, "EVAPI",     "surface evaporation (ice)",                                     "mm"            },
+  {  66, 0, "AHFLL",     "surface latent heat flux (land)",                               "W/m**2"        },
+  {  67, 0, "AHFLW",     "surface latent heat flux (water)",                              "W/m**2"        },
+  {  68, 0, "AHFLI",     "surface latent heat flux (ice)",                                "W/m**2"        },
+  {  69, 0, "AHFSL",     "surface sensible heat flux (land)",                             "W/m**2"        },
+  {  70, 0, "AHFSW",     "surface sensible heat flux (water)",                            "W/m**2"        },
+  {  71, 0, "AHFSI",     "surface sensible heat flux (ice)",                              "W/m**2"        },
+  {  72, 0, "AZ0L",      "surface roughness length (land)",                               "m"             },
+  {  73, 0, "AZ0W",      "surface roughness length (water)",                              "m"             },
+  {  74, 0, "AZ0I",      "surface roughness length (ice)",                                "m"             },
+  {  75, 0, "ALSOL",     "surface albedo (land)",                                         "fract."        },
+  {  76, 0, "ALSOW",     "surface albedo (water)",                                        "fract."        },
+  {  77, 0, "ALSOI",     "surface albedo (ice)",                                          "fract."        },
+  {  81, 0, "TMCHL",     "turbulent transfer coefficient of heat at the surface (land)",   NULL           },
+  {  82, 0, "TMCHW",     "turbulent transfer coefficient of heat at the surface (water)",  NULL           },
+  {  83, 0, "TMCHI",     "turbulent transfer coefficient of heat at the surface (ice)",    NULL           },
+  {  84, 0, "QDBL",      "specific humidity surface (land)",                              "kg/kg"         },
+  {  85, 0, "QDBW",      "specific humidity surface (water)",                             "kg/kg"         },
+  {  86, 0, "QDBI",      "specific humidity surface (ice)",                               "kg/kg"         },
+  {  87, 0, "BFLHSL",    "surface sensible heat flux (land)",                             "W/m**2"        },
+  {  88, 0, "BFLHSW",    "surface sensible heat flux (water)",                            "W/m**2"        },
+  {  89, 0, "BFLHSI",    "surface sensible heat flux (ice)",                              "W/m**2"        },
+  {  90, 0, "BFLQDSL",   "surface latent heat flux (land)",                               "W/m**2"        },
+  {  91, 0, "BFLQDSW",   "surface latent heat flux (water)",                              "W/m**2"        },
+  {  92, 0, "BFLQDSI",   "surface latent heat flux (ice)",                                "W/m**2"        },
+  {  93, 0, "AHFICE",    "sea-ice: conductive heat",                                      "W/m"           },
+  {  94, 0, "QRES",      "residual heat flux for melting sea ice",                        "W/m**2"        },
+  {  95, 0, "SRFL",      "SRFL",                                                           NULL           },
+  {  96, 0, "QDBOXS",    "horizontal transport of water vapour",                          "kg/m**2"       },
+  {  97, 0, "QWBOXS",    "horizontal transport of cloud water",                           "kg/m**2"       },
+  {  98, 0, "EKBOXS",    "horizontal transport of kinetic energy",                        "(3600*J)/m**2" },
+  {  99, 0, "FHBOXS",    "horizontal transport of sensible heat",                         "(3600*J)/m**2" },
+  { 100, 0, "FIBOXS",    "horizontal transport of potential energy",                      "(3600*J)/m**2" },
+  { 101, 0, "TLAMBDA",   "heat conductivity of dry soil",                                 "W/(K*m)"       },
+  { 103, 0, "DLAMBDA",   "parameter for increasing the heat conductivity of the soil",     NULL           },
+  { 104, 0, "PORVOL",    "pore volume",                                                    NULL           },
+  { 105, 0, "FCAP",      "field capacity of soil",                                         NULL           },
+  { 106, 0, "WI3",       "fraction of frozen soil",                                        NULL           },
+  { 107, 0, "WI4",       "fraction of frozen soil",                                        NULL           },
+  { 108, 0, "WI5",       "fraction of frozen soil",                                        NULL           },
+  { 109, 0, "WI",        "fraction of frozen soil",                                        NULL           },
+  { 110, 0, "WICL",      "fraction of frozen soil",                                        NULL           },
+  { 112, 0, "QDB",       "specific humidity surface",                                     "kg/kg"         },
+  { 129, 0, "FIB",       "surface geopotential (orography)",                              "m"             },
+  { 130, 0, "T",         "temperature",                                                   "K"             },
+  { 131, 0, "U",         "u-velocity",                                                    "m/s"           },
+  { 132, 0, "V",         "v-velocity",                                                    "m/s"           },
+  { 133, 0, "QD",        "specific humidity",                                             "kg/kg"         },
+  { 134, 0, "PS",        "Surface pressure",                                              "Pa"            },
+  { 135, 0, "VERVEL",    "Vertical velocity",                                             "Pa/s"          },
+  { 138, 0, "SVO",       "vorticity",                                                     "1/s"           },
+  { 139, 0, "TS",        "surface temperature",                                           "K"             },
+  { 140, 0, "WS",        "soil wetness",                                                  "m"             },
+  { 141, 0, "SN",        "snow depth",                                                    "m"             },
+  { 142, 0, "APRL",      "large scale precipitation",                                     "mm"            },
+  { 143, 0, "APRC",      "convective  precipitation",                                     "mm"            },
+  { 144, 0, "APRS",      "snow fall",                                                     "mm"            },
+  { 145, 0, "VDIS",      "boundary layer dissipation",                                    "W/m**2"        },
+  { 146, 0, "AHFS",      "surface sensible heat flux",                                    "W/m**2"        },
+  { 147, 0, "AHFL",      "surface latent heat flux",                                      "W/m**2"        },
+  { 148, 0, "STREAM",    "streamfunction",                                                "m**2/s"        },
+  { 149, 0, "VELOPOT",   "velocity potential",                                            "m**2/s"        },
+  { 151, 0, "PSRED",     "mean sea level pressure",                                       "Pa"            },
+  { 152, 0, "LSP",       "log surface pressure",                                           NULL           },
+  { 153, 0, "QW",        "liquid water content",                                          "kg/kg"         },
+  { 155, 0, "SD",        "divergence",                                                    "1/s"           },
+  { 156, 0, "FI",        "geopotential height",                                           "gpm"           },
+  { 159, 0, "USTAR3",    "ustar**3",                                                      "m**3/s**3"     },
+  { 160, 0, "RUNOFF",    "surface runoff",                                                "mm"            },
+  { 162, 0, "ACLC",      "cloud cover",                                                   "fract."        },
+  { 163, 0, "ACLCV",     "total cloud cover",                                             "fract."        },
+  { 164, 0, "ACLCOV",    "total cloud cover",                                             "fract."        },
+  { 165, 0, "U10",       "10m u-velocity",                                                "m/s"           },
+  { 166, 0, "V10",       "10m v-velocity",                                                "m/s"           },
+  { 167, 0, "TEMP2",     "2m temperature",                                                "K"             },
+  { 168, 0, "DEW2",      "2m dew point temperature",                                      "K"             },
+  { 169, 0, "TSURF",     "surface temperature (land)",                                    "K"             },
+  { 170, 0, "TD",        "deep soil temperature",                                         "K"             },
+  { 171, 0, "WIND10",    "10m windspeed",                                                 "m/s"           },
+  { 172, 0, "BLA",       "land sea mask",                                                 "fract."        },
+  { 173, 0, "AZ0",       "surface roughness length",                                      "m"             },
+  { 174, 0, "ALB",       "surface background albedo",                                     "fract."        },
+  { 175, 0, "ALBEDO",    "surface albedo",                                                "fract."        },
+  { 176, 0, "SRADS",     "net surface solar radiation",                                   "W/m**2"        },
+  { 177, 0, "TRADS",     "net surface thermal radiation",                                 "W/m**2"        },
+  { 178, 0, "SRAD0",     "net top solar radiation",                                       "W/m**2"        },
+  { 179, 0, "TRAD0",     "top thermal radiation (OLR)",                                   "W/m**2"        },
+  { 180, 0, "USTR",      "surface u-stress",                                              "Pa"            },
+  { 181, 0, "VSTR",      "surface v-stress",                                              "Pa"            },
+  { 182, 0, "EVAP",      "surface evaporation",                                           "mm"            },
+  { 183, 0, "TDCL",      "soil temperature",                                              "K"             },
+  { 185, 0, "SRAFS",     "net surf. solar radiation   (clear sky)",                       "W/m**2"        },
+  { 186, 0, "TRAFS",     "net surf. thermal radiation (clear sky)",                       "W/m**2"        },
+  { 187, 0, "SRAF0",     "net top solar radiation     (clear sky)",                       "W/m**2"        },
+  { 188, 0, "TRAF0",     "net top thermal radiation   (clear sky)",                       "W/m**2"        },
+  { 189, 0, "SCLFS",     "surface solar cloud forcing",                                   "W/m**2"        },
+  { 190, 0, "TCLFS",     "surface thermal cloud forcing",                                 "W/m**2"        },
+  { 191, 0, "SCLF0",     "top solar cloud forcing",                                       "W/m**2"        },
+  { 192, 0, "TCLF0",     "top thermal cloud forcing",                                     "W/m**2"        },
+  { 194, 0, "WL",        "skin reservoir content",                                        "m"             },
+  { 195, 0, "USTRGW",    "u-gravity wave stress",                                         "Pa"            },
+  { 196, 0, "VSTRGW",    "v-gravity wave stress",                                         "Pa"            },
+  { 197, 0, "VDISGW",    "gravity wave dissipation",                                      "W/m**2"        },
+  { 198, 0, "VGRAT",     "vegetation ratio",                                               NULL           },
+  { 199, 0, "VAROR",     "orographic variance (for surface runoff)",                       NULL           },
+  { 200, 0, "VLT",       "leaf area index",                                                NULL           },
+  { 201, 0, "T2MAX",     "maximum 2m-temperature",                                        "K"             },
+  { 202, 0, "T2MIN",     "minimum 2m-temperature",                                        "K"             },
+  { 203, 0, "SRAD0U",    "top solar radiation upward",                                    "W/m**2"        },
+  { 204, 0, "SRADSU",    "surface solar radiation upward",                                "W/m**2"        },
+  { 205, 0, "TRADSU",    "surface thermal radiation upward",                              "W/m**2"        },
+  { 206, 0, "TSN",       "snow temperature",                                              "K"             },
+  { 207, 0, "TD3",       "soil temperature",                                              "K"             },
+  { 208, 0, "TD4",       "soil temperature",                                              "K"             },
+  { 209, 0, "TD5",       "soil temperature",                                              "K"             },
+  { 210, 0, "SEAICE",    "sea ice cover",                                                 "fract."        },
+  { 211, 0, "SICED",     "sea ice depth",                                                 "m"             },
+  { 212, 0, "FOREST",    "vegetation type",                                                NULL           },
+  { 213, 0, "TEFF",      "(effective) sea-ice skin temperature",                          "K"             },
+  { 214, 0, "TSMAX",     "maximum surface temperature",                                   "K"             },
+  { 215, 0, "TSMIN",     "minimum surface temperature",                                   "K"             },
+  { 216, 0, "WIMAX",     "maximum 10m-wind speed",                                        "m/s"           },
+  { 217, 0, "TOPMAX",    "maximum height of convective cloud tops",                       "Pa"            },
+  { 218, 0, "SNMEL",     "snow melt",                                                     "mm"            },
+  { 220, 0, "TSLIN",     "land: residual surface heat budget",                            "W/m**2"        },
+  { 221, 0, "DSNAC",     "snow depth change",                                             "mm"            },
+  { 222, 0, "EMTER",     "EMTER",                                                          NULL           },
+  { 223, 0, "ACLCAC",    "cloud cover",                                                   "fract."        },
+  { 224, 0, "TKE",       "turbulent kinetic energy",                                       NULL           },
+  { 226, 0, "FAO",       "FAO data set (soil data flags)",                                 NULL           },
+  { 227, 0, "RGCGN",     "heat capacity of soil",                                          NULL           },
+  { 229, 0, "WSMX",      "field capacity of soil",                                         NULL           },
+  { 230, 0, "QVI",       "vertically integrated specific humidity",                       "kg/m**2"       },
+  { 231, 0, "ALWCVI",    "vertically integrated liquid water cont.",                      "kg/m**2"       },
+  { 232, 0, "GLAC",      "glacier mask",                                                   NULL           },
+  { 253, 0, "PHI",       "latitude in real coordinates",                                  "degrees_north" },
+  { 254, 0, "RLA",       "longitude in real coordinates",                                 "degrees_east"  },
+  { 259, 0, "WINDSPEED", "windspeed (sqrt(u**2+v**2))",                                    NULL           },
+  { 260, 0, "PRECIP",    "total precipitation",                                            NULL           },
 };
 
-static PAR cosmo002[] = {
-  {   1, "P",         "pressure",                                          "Pa"         },
-  {   2, "PMSL",      "mean sea level pressure",                           "Pa"         },
-  {   3, "DPSDT",     "surface pressure change",                           "Pa s-1"     },
-  {   6, "FI",        "geopotential",                                      "m2 s-2"     },
-  {   8, "HH",        "height",                                            "m"          },
-  {  10, "TO3",       "vertical integrated ozone content",                 "Dobson"     },
-  {  11, "T",         "temperature",                                       "K"          },
-  {  15, "TMAX",      "2m maximum temperature",                            "K"          },
-  {  16, "TMIN",      "2m minimum temperature",                            "K"          },
-  {  17, "TD",        "2m dew point temperature",                          "K"          },
-  {  31, "DD",        "undefined",                                         "undefined"  },
-  {  32, "FF",        "undefined",                                         "undefined"  },
-  {  33, "U",         "U-component of wind",                               "m s-1"      },
-  {  34, "V",         "V-component of wind",                               "m s-1"      },
-  {  39, "OMEGA",     "omega",                                             "Pa s-1"     },
-  {  40, "W",         "vertical wind velocity",                            "m s-1"      },
-  {  51, "QV",        "specific humidity",                                 "kg kg-1"    },
-  {  52, "RELHUM",    "relative humidity",                                 "%"          },
-  {  54, "TQV",       "precipitable water",                                "kg m-2"     },
-  {  57, "AEVAP",     "surface evaporation",                               "kg m-2"     },
-  {  58, "TQI",       "vertical integrated cloud ice",                     "kg m-2"     },
-  {  59, "TOT_PR",    "total precipitation rate",                          "kg m-2 s-1" },
-  {  61, "TOT_PREC",  "total precipitation amount",                        "kg m-2"     },
-  {  65, "W_SNOW",    "surface snow amount",                               "m"          },
-  {  66, "H_SNOW",    "thickness of snow",                                 "m"          },
-  {  71, "CLCT",      "total cloud cover",                                 "1"          },
-  {  72, "CLC_CON",   "convective cloud area fraction",                    "1"          },
-  {  73, "CLCL",      "low cloud cover",                                   "1"          },
-  {  74, "CLCM",      "medium cloud cover",                                "1"          },
-  {  75, "CLCH",      "high cloud cover",                                  "1"          },
-  {  76, "TQC",       "vertical integrated cloud water",                   "kg m-2"     },
-  {  78, "SNOW_CON",  "convective snowfall",                               "kg m-2"     },
-  {  79, "SNOW_GSP",  "large scale snowfall",                              "kg m-2"     },
-  {  81, "FR_LAND",   "land-sea fraction",                                 "1"          },
-  {  83, "Z0",        "surface roughness length",                          "m"          },
-  {  84, "ALB_RAD",   "surface albedo",                                    "1"          },
-  {  85, "TSOIL",     "soil surface temperature",                          "K"          },
-  {  86, "WSOIL",     "water content of 1. soil layer",                    "m"          },
-  {  87, "PLCOV",     "vegetation area fraction",                          "1"          },
-  {  90, "RUNOFF",    "subsurface runoff",                                 "kg m-2"     },
-  {  91, "FR_ICE",    "sea ice area fraction",                             "1"          },
-  {  92, "H_ICE",     "sea ice thickness",                                 "m"          },
-  { 111, "ASOB",      "averaged surface net downward shortwave radiation", "W m-2"      },
-  { 112, "ATHB",      "averaged surface net downward longwave radiation",  "W m-2"      },
-  { 113, "ASOB",      "averaged TOA net downward shortwave radiation",     "W m-2"      },
-  { 114, "ATHB",      "averaged TOA outgoing longwave radiation",          "W m-2"      },
-  { 115, "ASWDIR",    "direct downward sw radiation at the surface",       "W m-2"      },
-  { 116, "ASWDIFD",   "diffuse downward sw radiation at the surface",      "W m-2"      },
-  { 117, "ASWDIFU",   "diffuse upwnward sw radiation at the surface",      "W m-2"      },
-  { 118, "ALWD",      "downward lw radiation at the surface",              "W m-2"      },
-  { 119, "ALWU",      "upward lw radiation at the surface",                "W m-2"      },
-  { 121, "ALHFL",     "averaged surface latent heat flux",                 "W m-2"      },
-  { 122, "ASHFL",     "averaged surface sensible heat flux",               "W m-2"      },
-  { 124, "AUMFL",     "averaged eastward stress",                          "Pa"         },
-  { 125, "AVMFL",     "averaged northward stress",                         "Pa"         },
-  { 128, "SUNSH",     "undefined",                                         "undefined"  },
-  { 129, "SUNSH2",    "undefined",                                         "undefined"  },
-  { 130, "SUN_SUM",   "undefined",                                         "undefined"  },
-  { 131, "SUN_SUM2",  "undefined",                                         "undefined"  },
-  { 133, "FCOR",      "undefined",                                         "undefined"  },
-  { 134, "SKYVIEW",   "sky-view factor",                                   "1"          },
-  { 137, "SWDIR_COR", "topo correction of direct solar radiarion",         "1"          },
+static const PAR cosmo002[] = {
+  {   1, 0, "P",         "pressure",                                          "Pa"         },
+  {   2, 0, "PMSL",      "mean sea level pressure",                           "Pa"         },
+  {   3, 0, "DPSDT",     "surface pressure change",                           "Pa s-1"     },
+  {   6, 0, "FI",        "geopotential",                                      "m2 s-2"     },
+  {   8, 0, "HH",        "height",                                            "m"          },
+  {  10, 0, "TO3",       "vertical integrated ozone content",                 "Dobson"     },
+  {  11, 0, "T",         "temperature",                                       "K"          },
+  {  15, 0, "TMAX",      "2m maximum temperature",                            "K"          },
+  {  16, 0, "TMIN",      "2m minimum temperature",                            "K"          },
+  {  17, 0, "TD",        "2m dew point temperature",                          "K"          },
+  {  31, 0, "DD",        "undefined",                                         "undefined"  },
+  {  32, 0, "FF",        "undefined",                                         "undefined"  },
+  {  33, 0, "U",         "U-component of wind",                               "m s-1"      },
+  {  34, 0, "V",         "V-component of wind",                               "m s-1"      },
+  {  39, 0, "OMEGA",     "omega",                                             "Pa s-1"     },
+  {  40, 0, "W",         "vertical wind velocity",                            "m s-1"      },
+  {  51, 0, "QV",        "specific humidity",                                 "kg kg-1"    },
+  {  52, 0, "RELHUM",    "relative humidity",                                 "%"          },
+  {  54, 0, "TQV",       "precipitable water",                                "kg m-2"     },
+  {  57, 0, "AEVAP",     "surface evaporation",                               "kg m-2"     },
+  {  58, 0, "TQI",       "vertical integrated cloud ice",                     "kg m-2"     },
+  {  59, 0, "TOT_PR",    "total precipitation rate",                          "kg m-2 s-1" },
+  {  61, 0, "TOT_PREC",  "total precipitation amount",                        "kg m-2"     },
+  {  65, 0, "W_SNOW",    "surface snow amount",                               "m"          },
+  {  66, 0, "H_SNOW",    "thickness of snow",                                 "m"          },
+  {  71, 0, "CLCT",      "total cloud cover",                                 "1"          },
+  {  72, 0, "CLC_CON",   "convective cloud area fraction",                    "1"          },
+  {  73, 0, "CLCL",      "low cloud cover",                                   "1"          },
+  {  74, 0, "CLCM",      "medium cloud cover",                                "1"          },
+  {  75, 0, "CLCH",      "high cloud cover",                                  "1"          },
+  {  76, 0, "TQC",       "vertical integrated cloud water",                   "kg m-2"     },
+  {  78, 0, "SNOW_CON",  "convective snowfall",                               "kg m-2"     },
+  {  79, 0, "SNOW_GSP",  "large scale snowfall",                              "kg m-2"     },
+  {  81, 0, "FR_LAND",   "land-sea fraction",                                 "1"          },
+  {  83, 0, "Z0",        "surface roughness length",                          "m"          },
+  {  84, 0, "ALB_RAD",   "surface albedo",                                    "1"          },
+  {  85, 0, "TSOIL",     "soil surface temperature",                          "K"          },
+  {  86, 0, "WSOIL",     "water content of 1. soil layer",                    "m"          },
+  {  87, 0, "PLCOV",     "vegetation area fraction",                          "1"          },
+  {  90, 0, "RUNOFF",    "subsurface runoff",                                 "kg m-2"     },
+  {  91, 0, "FR_ICE",    "sea ice area fraction",                             "1"          },
+  {  92, 0, "H_ICE",     "sea ice thickness",                                 "m"          },
+  { 111, 0, "ASOB",      "averaged surface net downward shortwave radiation", "W m-2"      },
+  { 112, 0, "ATHB",      "averaged surface net downward longwave radiation",  "W m-2"      },
+  { 113, 0, "ASOB",      "averaged TOA net downward shortwave radiation",     "W m-2"      },
+  { 114, 0, "ATHB",      "averaged TOA outgoing longwave radiation",          "W m-2"      },
+  { 115, 0, "ASWDIR",    "direct downward sw radiation at the surface",       "W m-2"      },
+  { 116, 0, "ASWDIFD",   "diffuse downward sw radiation at the surface",      "W m-2"      },
+  { 117, 0, "ASWDIFU",   "diffuse upwnward sw radiation at the surface",      "W m-2"      },
+  { 118, 0, "ALWD",      "downward lw radiation at the surface",              "W m-2"      },
+  { 119, 0, "ALWU",      "upward lw radiation at the surface",                "W m-2"      },
+  { 121, 0, "ALHFL",     "averaged surface latent heat flux",                 "W m-2"      },
+  { 122, 0, "ASHFL",     "averaged surface sensible heat flux",               "W m-2"      },
+  { 124, 0, "AUMFL",     "averaged eastward stress",                          "Pa"         },
+  { 125, 0, "AVMFL",     "averaged northward stress",                         "Pa"         },
+  { 128, 0, "SUNSH",     "undefined",                                         "undefined"  },
+  { 129, 0, "SUNSH2",    "undefined",                                         "undefined"  },
+  { 130, 0, "SUN_SUM",   "undefined",                                         "undefined"  },
+  { 131, 0, "SUN_SUM2",  "undefined",                                         "undefined"  },
+  { 133, 0, "FCOR",      "undefined",                                         "undefined"  },
+  { 134, 0, "SKYVIEW",   "sky-view factor",                                   "1"          },
+  { 137, 0, "SWDIR_COR", "topo correction of direct solar radiarion",         "1"          },
 };
 
-static PAR cosmo201[] = {
-  {   5, "APAB",      "&",                                                         "W m-2"      },
-  {  13, "SOHR_RAD",  "&",                                                         "K s-1"      },
-  {  14, "THHR_RAD",  "&",                                                         "K s-1"      },
-  {  20, "DURSUN",    "duration of sunshine",                                      "s"          },
-  {  29, "CLC",       "cloud area fraction",                                       "1"          },
-  {  30, "CLC_SGS",   "grid scale cloud area fraction",                            "1"          },
-  {  31, "QC",        "specific cloud liquid water content",                       "kg kg-1"    },
-  {  33, "QI",        "specific cloud ice content",                                "kg kg-1"    },
-  {  35, "QR",        "specific rain content",                                     "kg kg-1"    },
-  {  36, "QS",        "specific snow content",                                     "kg kg-1"    },
-  {  37, "TQR",       "total rain water content vertically integrated",            "kg m-2"     },
-  {  38, "TQS",       "total snow content vertically integrated",                  "kg m-2"     },
-  {  39, "QG",        "specific graupel content",                                  "kg kg-1"    },
-  {  40, "TQG",       "total graupel content vertically integrated",               "kg m-2"     },
-  {  41, "TWATER",    "cloud condensed water content",                             "kg m-2"     },
-  {  42, "TDIV_HUM",  "atmosphere water divergence",                               "kg m-2"     },
-  {  43, "QC_RAD",    "sub scale specific cloud liquid water content",             "kg kg-1"    },
-  {  44, "QI_RAD",    "sub scale specific cloud ice content",                      "kg kg-1"    },
-  {  61, "CLW_CON",   "convective cloud liquid water",                             "1"          },
-  {  68, "HBAS_CON",  "height of convective cloud base",                           "m"          },
-  {  69, "HTOP_CON",  "height of convective cloud top",                            "m"          },
-  {  70, "HBAS_CONI", "height of convective cloud base",                           "m"          },
-  {  71, "HTOP_CONI", "height of convective cloud top",                            "m"          },
-  {  72, "BAS_CON",   "index of convective cloud base",                            "1"          },
-  {  73, "TOP_CON",   "index of convective cloud top",                             "1"          },
-  {  74, "DT_CON",    "convective tendency of temperature",                        "K s-1"      },
-  {  75, "DQV_CON",   "convective tendency of specific humidity",                  "s-1"        },
-  {  78, "DU_CON",    "convective tendency of u-wind component",                   "m s-2"      },
-  {  79, "DV_CON",    "convective tendency of v-wind component",                   "m s-2"      },
-  {  82, "HTOP_DC",   "height of dry convection top",                              "m"          },
-  {  84, "HZEROCL",   "height of freezing level",                                  "m"          },
-  {  85, "SNOWLMT",   "height of the snow fall limit in m above sea level",        "m"          },
-  {  86, "HCBAS",     "height of cloud base",                                      "m"          },
-  {  87, "HCTOP",     "height of cloud top",                                       "m"          },
-  {  91, "C_T_LK",    "&",                                                         "1"          },
-  {  92, "GAMSO_LK",  "&",                                                         "m-1"        },
-  {  93, "DP_BS_LK",  "&",                                                         "m"          },
-  {  94, "H_B1_LK",   "&",                                                         "m"          },
-  {  95, "H_ML_LK",   "&",                                                         "m"          },
-  {  96, "DEPTH_LK",  "lake depth",                                                "m"          },
-  {  97, "FETCH_LK",  "wind fetch over lake",                                      "m"          },
-  {  99, "QRS",       "precipitation water (water loading)",                       "1"          },
-  { 100, "PRR_GSP",   "mass flux density of large scale rainfall",                 "kg m-2 s-1" },
-  { 101, "PRS_GSP",   "mass flux density of large scale snowfall",                 "kg m-2 s-1" },
-  { 102, "RAIN_GSP",  "large scale rainfall",                                      "kg m-2"     },
-  { 111, "PRR_CON",   "mass flux density of convective rainfall",                  "kg m-2 s-1" },
-  { 112, "PRS_CON",   "mass flux density of convective snowfall",                  "kg m-2 s-1" },
-  { 113, "RAIN_CON",  "convective rainfall",                                       "kg m-2"     },
-  { 129, "FRESHSNW",  "freshness of snow",                                         "undefined"  },
-  { 131, "PRG_GSP",   "mass flux density of large scale graupel",                  "kg m-2 s-1" },
-  { 132, "GRAU_GSP",  "large scale graupel",                                       "kg m-2"     },
-  { 133, "RHO_SNOW",  "density of snow",                                           "kg m-3"     },
-  { 139, "PP",        "deviation from reference pressure",                         "Pa"         },
-  { 140, "RCLD",      "standard deviation of saturation deficit",                  "undefined"  },
-  { 143, "CAPE_MU",   "cape of most unstable parcel",                              "J kg-1"     },
-  { 144, "CIN_MU",    "convective inhibition of most unstable parcel",             "J kg-1"     },
-  { 145, "CAPE_ML",   "cape of mean surface layer parcel",                         "J kg-1"     },
-  { 146, "CIN_ML",    "convective inhibition of mean surface layer parcel",        "J kg-1"     },
-  { 147, "TKE_CON",   "convective turbulent kinetic energy",                       "undefined"  },
-  { 148, "TKETENS",   "tendency of turbulent kinetic energy",                      "undefined"  },
-  { 152, "TKE",       "turbulent kinetic energy",                                  "m2 s-2"     },
-  { 153, "TKVM",      "diffusion coefficient of momentum",                         "m2 s-1"     },
-  { 154, "TKVH",      "diffusion coefficient of heat",                             "m2 s-1"     },
-  { 170, "TCM",       "drag coefficient of momentum",                              "1"          },
-  { 171, "TCH",       "drag coefficient of heat",                                  "1"          },
-  { 187, "VMAX",      "maximum turbulent wind gust in 10m",                        "m s-1"      },
-  { 190, "TSOIL",     "&",                                                         "K"          },
-  { 191, "TSOIL",     "&",                                                         "K"          },
-  { 192, "TSOIL",     "&",                                                         "K"          },
-  { 193, "TSOIL",     "mixed layer temperature",                                   "K"          },
-  { 194, "TSOIL",     "mean temperature of water column",                          "K"          },
-  { 197, "TSOIL",     "soil temperature",                                          "K"          },
-  { 198, "W_SO",      "soil water content",                                        "m"          },
-  { 199, "W_SO_ICE",  "soil frozen water content",                                 "m"          },
-  { 200, "W_I",       "canopy water amount",                                       "m"          },
-  { 203, "TSOIL",     "snow surface temperature",                                  "K"          },
-  { 215, "TSOIL",     "temperature of ice upper surface",                          "K"          },
-  { 230, "dBZ",       "unattenuated radar reflectivity in Rayleigh approximation", "1"          },
-  { 240, "MFLX_CON",  "convective mass flux density",                              "kg m-2 s-1" },
-  { 241, "CAPE_CON",  "&",                                                         "J kg-1"     },
-  { 243, "QCVG_CON",  "&",                                                         "s-1"        },
+static const PAR cosmo201[] = {
+  {   5, 0, "APAB",      "&",                                                         "W m-2"      },
+  {  13, 0, "SOHR_RAD",  "&",                                                         "K s-1"      },
+  {  14, 0, "THHR_RAD",  "&",                                                         "K s-1"      },
+  {  20, 0, "DURSUN",    "duration of sunshine",                                      "s"          },
+  {  29, 0, "CLC",       "cloud area fraction",                                       "1"          },
+  {  30, 0, "CLC_SGS",   "grid scale cloud area fraction",                            "1"          },
+  {  31, 0, "QC",        "specific cloud liquid water content",                       "kg kg-1"    },
+  {  33, 0, "QI",        "specific cloud ice content",                                "kg kg-1"    },
+  {  35, 0, "QR",        "specific rain content",                                     "kg kg-1"    },
+  {  36, 0, "QS",        "specific snow content",                                     "kg kg-1"    },
+  {  37, 0, "TQR",       "total rain water content vertically integrated",            "kg m-2"     },
+  {  38, 0, "TQS",       "total snow content vertically integrated",                  "kg m-2"     },
+  {  39, 0, "QG",        "specific graupel content",                                  "kg kg-1"    },
+  {  40, 0, "TQG",       "total graupel content vertically integrated",               "kg m-2"     },
+  {  41, 0, "TWATER",    "cloud condensed water content",                             "kg m-2"     },
+  {  42, 0, "TDIV_HUM",  "atmosphere water divergence",                               "kg m-2"     },
+  {  43, 0, "QC_RAD",    "sub scale specific cloud liquid water content",             "kg kg-1"    },
+  {  44, 0, "QI_RAD",    "sub scale specific cloud ice content",                      "kg kg-1"    },
+  {  61, 0, "CLW_CON",   "convective cloud liquid water",                             "1"          },
+  {  68, 0, "HBAS_CON",  "height of convective cloud base",                           "m"          },
+  {  69, 0, "HTOP_CON",  "height of convective cloud top",                            "m"          },
+  {  70, 0, "HBAS_CONI", "height of convective cloud base",                           "m"          },
+  {  71, 0, "HTOP_CONI", "height of convective cloud top",                            "m"          },
+  {  72, 0, "BAS_CON",   "index of convective cloud base",                            "1"          },
+  {  73, 0, "TOP_CON",   "index of convective cloud top",                             "1"          },
+  {  74, 0, "DT_CON",    "convective tendency of temperature",                        "K s-1"      },
+  {  75, 0, "DQV_CON",   "convective tendency of specific humidity",                  "s-1"        },
+  {  78, 0, "DU_CON",    "convective tendency of u-wind component",                   "m s-2"      },
+  {  79, 0, "DV_CON",    "convective tendency of v-wind component",                   "m s-2"      },
+  {  82, 0, "HTOP_DC",   "height of dry convection top",                              "m"          },
+  {  84, 0, "HZEROCL",   "height of freezing level",                                  "m"          },
+  {  85, 0, "SNOWLMT",   "height of the snow fall limit in m above sea level",        "m"          },
+  {  86, 0, "HCBAS",     "height of cloud base",                                      "m"          },
+  {  87, 0, "HCTOP",     "height of cloud top",                                       "m"          },
+  {  91, 0, "C_T_LK",    "&",                                                         "1"          },
+  {  92, 0, "GAMSO_LK",  "&",                                                         "m-1"        },
+  {  93, 0, "DP_BS_LK",  "&",                                                         "m"          },
+  {  94, 0, "H_B1_LK",   "&",                                                         "m"          },
+  {  95, 0, "H_ML_LK",   "&",                                                         "m"          },
+  {  96, 0, "DEPTH_LK",  "lake depth",                                                "m"          },
+  {  97, 0, "FETCH_LK",  "wind fetch over lake",                                      "m"          },
+  {  99, 0, "QRS",       "precipitation water (water loading)",                       "1"          },
+  { 100, 0, "PRR_GSP",   "mass flux density of large scale rainfall",                 "kg m-2 s-1" },
+  { 101, 0, "PRS_GSP",   "mass flux density of large scale snowfall",                 "kg m-2 s-1" },
+  { 102, 0, "RAIN_GSP",  "large scale rainfall",                                      "kg m-2"     },
+  { 111, 0, "PRR_CON",   "mass flux density of convective rainfall",                  "kg m-2 s-1" },
+  { 112, 0, "PRS_CON",   "mass flux density of convective snowfall",                  "kg m-2 s-1" },
+  { 113, 0, "RAIN_CON",  "convective rainfall",                                       "kg m-2"     },
+  { 129, 0, "FRESHSNW",  "freshness of snow",                                         "undefined"  },
+  { 131, 0, "PRG_GSP",   "mass flux density of large scale graupel",                  "kg m-2 s-1" },
+  { 132, 0, "GRAU_GSP",  "large scale graupel",                                       "kg m-2"     },
+  { 133, 0, "RHO_SNOW",  "density of snow",                                           "kg m-3"     },
+  { 139, 0, "PP",        "deviation from reference pressure",                         "Pa"         },
+  { 140, 0, "RCLD",      "standard deviation of saturation deficit",                  "undefined"  },
+  { 143, 0, "CAPE_MU",   "cape of most unstable parcel",                              "J kg-1"     },
+  { 144, 0, "CIN_MU",    "convective inhibition of most unstable parcel",             "J kg-1"     },
+  { 145, 0, "CAPE_ML",   "cape of mean surface layer parcel",                         "J kg-1"     },
+  { 146, 0, "CIN_ML",    "convective inhibition of mean surface layer parcel",        "J kg-1"     },
+  { 147, 0, "TKE_CON",   "convective turbulent kinetic energy",                       "undefined"  },
+  { 148, 0, "TKETENS",   "tendency of turbulent kinetic energy",                      "undefined"  },
+  { 152, 0, "TKE",       "turbulent kinetic energy",                                  "m2 s-2"     },
+  { 153, 0, "TKVM",      "diffusion coefficient of momentum",                         "m2 s-1"     },
+  { 154, 0, "TKVH",      "diffusion coefficient of heat",                             "m2 s-1"     },
+  { 170, 0, "TCM",       "drag coefficient of momentum",                              "1"          },
+  { 171, 0, "TCH",       "drag coefficient of heat",                                  "1"          },
+  { 187, 0, "VMAX",      "maximum turbulent wind gust in 10m",                        "m s-1"      },
+  { 190, 0, "TSOIL",     "&",                                                         "K"          },
+  { 191, 0, "TSOIL",     "&",                                                         "K"          },
+  { 192, 0, "TSOIL",     "&",                                                         "K"          },
+  { 193, 0, "TSOIL",     "mixed layer temperature",                                   "K"          },
+  { 194, 0, "TSOIL",     "mean temperature of water column",                          "K"          },
+  { 197, 0, "TSOIL",     "soil temperature",                                          "K"          },
+  { 198, 0, "W_SO",      "soil water content",                                        "m"          },
+  { 199, 0, "W_SO_ICE",  "soil frozen water content",                                 "m"          },
+  { 200, 0, "W_I",       "canopy water amount",                                       "m"          },
+  { 203, 0, "TSOIL",     "snow surface temperature",                                  "K"          },
+  { 215, 0, "TSOIL",     "temperature of ice upper surface",                          "K"          },
+  { 230, 0, "dBZ",       "unattenuated radar reflectivity in Rayleigh approximation", "1"          },
+  { 240, 0, "MFLX_CON",  "convective mass flux density",                              "kg m-2 s-1" },
+  { 241, 0, "CAPE_CON",  "&",                                                         "J kg-1"     },
+  { 243, 0, "QCVG_CON",  "&",                                                         "s-1"        },
 };
 
-static PAR cosmo202[] = {
-  {  46, "SSO_STDH",  "standard deviation of subgrid scale height",                "m"         },
-  {  47, "SSO_GAMMA", "anisotropy of topography",                                  "-"         },
-  {  48, "SSO_THETA", "angle between principal axis of orography and global east", "-"         },
-  {  49, "SSO_SIGMA", "mean slope of subgrid scale orography",                     "-"         },
-  {  55, "FR_LAKE",   "fraction of inland lake water",                             "1"         },
-  {  57, "SOILTYP",   "soil type",                                                 "1"         },
-  {  61, "LAI",       "leaf area index",                                           "1"         },
-  {  62, "ROOTDP",    "root depth",                                                "m"         },
-  {  64, "HMO3",      "air pressure at ozone maximum",                             "Pa"        },
-  {  65, "VIO3",      "vertical integrated ozone amount",                          "Pa"        },
-  {  67, "PLCOV_MX",  "vegetation area fraction maximum",                          "1"         },
-  {  68, "PLCOV_MN",  "vegetation area fraction minimum",                          "1"         },
-  {  69, "LAI_MX",    "leaf area index maximum",                                   "1"         },
-  {  70, "LAI_MN",    "leaf area index minimum",                                   "1"         },
-  {  75, "FOR_E",     "ground fraction covered by evergreen forest",               "-"         },
-  {  76, "FOR_D",     "ground fraction covered by deciduous forest",               "-"         },
-  { 104, "DQVDT",     "tendency of water vapor",                                   "s-1"       },
-  { 105, "QVSFLX",    "surface flux of water vapour",                              "s-1m-2"    },
-  { 113, "FC",        "coriolis parameter",                                        "s-1"       },
-  { 114, "RLAT",      "latitude",                                                  "radian"    },
-  { 115, "RLON",      "longitude",                                                 "radian"    },
-  { 121, "ZTD",       "integrated total atmospheric refractivity",                 "undefined" },
-  { 122, "ZWD",       "integrated wet atmospheric refractivity",                   "undefined" },
-  { 123, "ZHD",       "integrated dry atmospheric refractivity",                   "undefined" },
-  { 180, "O3",        "ozone mass mixing ratio",                                   "kg kg-1"   },
-  { 200, "I131a",     "undefined",                                                 "undefined" },
-  { 201, "I131a_DD",  "undefined",                                                 "undefined" },
-  { 202, "I131a_WD",  "undefined",                                                 "undefined" },
-  { 203, "Cs137",     "undefined",                                                 "undefined" },
-  { 204, "Cs137_DD",  "undefined",                                                 "undefined" },
-  { 205, "Cs137_WD",  "undefined",                                                 "undefined" },
-  { 206, "Te132",     "undefined",                                                 "undefined" },
-  { 207, "Te132_DD",  "undefined",                                                 "undefined" },
-  { 208, "Te132_WD",  "undefined",                                                 "undefined" },
-  { 209, "Zr95",      "undefined",                                                 "undefined" },
-  { 210, "Zr95_DD",   "undefined",                                                 "undefined" },
-  { 211, "Zr95_WD",   "undefined",                                                 "undefined" },
-  { 212, "Kr85",      "undefined",                                                 "undefined" },
-  { 213, "Kr85_DD",   "undefined",                                                 "undefined" },
-  { 214, "Kr85_WD",   "undefined",                                                 "undefined" },
-  { 215, "TRACER",    "undefined",                                                 "undefined" },
-  { 216, "TRACER_DD", "undefined",                                                 "undefined" },
-  { 217, "TRACER_WD", "undefined",                                                 "undefined" },
-  { 218, "Xe133",     "undefined",                                                 "undefined" },
-  { 219, "Xe133_DD",  "undefined",                                                 "undefined" },
-  { 220, "Xe133_WD",  "undefined",                                                 "undefined" },
-  { 221, "I131g",     "undefined",                                                 "undefined" },
-  { 222, "I131g_DD",  "undefined",                                                 "undefined" },
-  { 223, "I131g_WD",  "undefined",                                                 "undefined" },
-  { 224, "I131o",     "undefined",                                                 "undefined" },
-  { 225, "I131o_DD",  "undefined",                                                 "undefined" },
-  { 226, "I131o_WD",  "undefined",                                                 "undefined" },
-  { 227, "Ba140",     "undefined",                                                 "undefined" },
-  { 228, "Ba140_DD",  "undefined",                                                 "undefined" },
-  { 229, "Ba140_WD",  "undefined",                                                 "undefined" },
-  { 230, "Sr90",      "undefined",                                                 "undefined" },
-  { 231, "Sr90_DD",   "undefined",                                                 "undefined" },
-  { 232, "Sr90_WD",   "undefined",                                                 "undefined" },
-  { 233, "Ru103",     "undefined",                                                 "undefined" },
-  { 234, "Ru103_DD",  "undefined",                                                 "undefined" },
-  { 235, "Ru103_WD",  "undefined",                                                 "undefined" },
+static const PAR cosmo202[] = {
+  {  46, 0, "SSO_STDH",  "standard deviation of subgrid scale height",                "m"         },
+  {  47, 0, "SSO_GAMMA", "anisotropy of topography",                                  "-"         },
+  {  48, 0, "SSO_THETA", "angle between principal axis of orography and global east", "-"         },
+  {  49, 0, "SSO_SIGMA", "mean slope of subgrid scale orography",                     "-"         },
+  {  55, 0, "FR_LAKE",   "fraction of inland lake water",                             "1"         },
+  {  57, 0, "SOILTYP",   "soil type",                                                 "1"         },
+  {  61, 0, "LAI",       "leaf area index",                                           "1"         },
+  {  62, 0, "ROOTDP",    "root depth",                                                "m"         },
+  {  64, 0, "HMO3",      "air pressure at ozone maximum",                             "Pa"        },
+  {  65, 0, "VIO3",      "vertical integrated ozone amount",                          "Pa"        },
+  {  67, 0, "PLCOV_MX",  "vegetation area fraction maximum",                          "1"         },
+  {  68, 0, "PLCOV_MN",  "vegetation area fraction minimum",                          "1"         },
+  {  69, 0, "LAI_MX",    "leaf area index maximum",                                   "1"         },
+  {  70, 0, "LAI_MN",    "leaf area index minimum",                                   "1"         },
+  {  75, 0, "FOR_E",     "ground fraction covered by evergreen forest",               "-"         },
+  {  76, 0, "FOR_D",     "ground fraction covered by deciduous forest",               "-"         },
+  { 104, 0, "DQVDT",     "tendency of water vapor",                                   "s-1"       },
+  { 105, 0, "QVSFLX",    "surface flux of water vapour",                              "s-1m-2"    },
+  { 113, 0, "FC",        "coriolis parameter",                                        "s-1"       },
+  { 114, 0, "RLAT",      "latitude",                                                  "radian"    },
+  { 115, 0, "RLON",      "longitude",                                                 "radian"    },
+  { 121, 0, "ZTD",       "integrated total atmospheric refractivity",                 "undefined" },
+  { 122, 0, "ZWD",       "integrated wet atmospheric refractivity",                   "undefined" },
+  { 123, 0, "ZHD",       "integrated dry atmospheric refractivity",                   "undefined" },
+  { 180, 0, "O3",        "ozone mass mixing ratio",                                   "kg kg-1"   },
+  { 200, 0, "I131a",     "undefined",                                                 "undefined" },
+  { 201, 0, "I131a_DD",  "undefined",                                                 "undefined" },
+  { 202, 0, "I131a_WD",  "undefined",                                                 "undefined" },
+  { 203, 0, "Cs137",     "undefined",                                                 "undefined" },
+  { 204, 0, "Cs137_DD",  "undefined",                                                 "undefined" },
+  { 205, 0, "Cs137_WD",  "undefined",                                                 "undefined" },
+  { 206, 0, "Te132",     "undefined",                                                 "undefined" },
+  { 207, 0, "Te132_DD",  "undefined",                                                 "undefined" },
+  { 208, 0, "Te132_WD",  "undefined",                                                 "undefined" },
+  { 209, 0, "Zr95",      "undefined",                                                 "undefined" },
+  { 210, 0, "Zr95_DD",   "undefined",                                                 "undefined" },
+  { 211, 0, "Zr95_WD",   "undefined",                                                 "undefined" },
+  { 212, 0, "Kr85",      "undefined",                                                 "undefined" },
+  { 213, 0, "Kr85_DD",   "undefined",                                                 "undefined" },
+  { 214, 0, "Kr85_WD",   "undefined",                                                 "undefined" },
+  { 215, 0, "TRACER",    "undefined",                                                 "undefined" },
+  { 216, 0, "TRACER_DD", "undefined",                                                 "undefined" },
+  { 217, 0, "TRACER_WD", "undefined",                                                 "undefined" },
+  { 218, 0, "Xe133",     "undefined",                                                 "undefined" },
+  { 219, 0, "Xe133_DD",  "undefined",                                                 "undefined" },
+  { 220, 0, "Xe133_WD",  "undefined",                                                 "undefined" },
+  { 221, 0, "I131g",     "undefined",                                                 "undefined" },
+  { 222, 0, "I131g_DD",  "undefined",                                                 "undefined" },
+  { 223, 0, "I131g_WD",  "undefined",                                                 "undefined" },
+  { 224, 0, "I131o",     "undefined",                                                 "undefined" },
+  { 225, 0, "I131o_DD",  "undefined",                                                 "undefined" },
+  { 226, 0, "I131o_WD",  "undefined",                                                 "undefined" },
+  { 227, 0, "Ba140",     "undefined",                                                 "undefined" },
+  { 228, 0, "Ba140_DD",  "undefined",                                                 "undefined" },
+  { 229, 0, "Ba140_WD",  "undefined",                                                 "undefined" },
+  { 230, 0, "Sr90",      "undefined",                                                 "undefined" },
+  { 231, 0, "Sr90_DD",   "undefined",                                                 "undefined" },
+  { 232, 0, "Sr90_WD",   "undefined",                                                 "undefined" },
+  { 233, 0, "Ru103",     "undefined",                                                 "undefined" },
+  { 234, 0, "Ru103_DD",  "undefined",                                                 "undefined" },
+  { 235, 0, "Ru103_WD",  "undefined",                                                 "undefined" },
 };
 
-static PAR cosmo203[] = {
-  { 135, "LCL_ML",   "undefined",                  "undefined" },
-  { 136, "LFC_ML",   "undefined",                  "undefined" },
-  { 137, "CAPE_3KM", "undefined",                  "undefined" },
-  { 138, "SWISS00",  "swiss00 index",              "1"         },
-  { 139, "SWISS12",  "swiss12 index",              "1"         },
-  { 147, "SLI",      "surface lifted index",       "K"         },
-  { 149, "SI",       "showalter index",            "K"         },
-  { 155, "BRN",      "undefined",                  "undefined" },
-  { 156, "HPBL",     "undefined",                  "undefined" },
-  { 203, "CLDEPTH",  "normalized cloud depth",     "1"         },
-  { 204, "CLCT_MOD", "modified_total_cloud_cover", "1"         },
+static const PAR cosmo203[] = {
+  { 135, 0, "LCL_ML",   "undefined",                  "undefined" },
+  { 136, 0, "LFC_ML",   "undefined",                  "undefined" },
+  { 137, 0, "CAPE_3KM", "undefined",                  "undefined" },
+  { 138, 0, "SWISS00",  "swiss00 index",              "1"         },
+  { 139, 0, "SWISS12",  "swiss12 index",              "1"         },
+  { 147, 0, "SLI",      "surface lifted index",       "K"         },
+  { 149, 0, "SI",       "showalter index",            "K"         },
+  { 155, 0, "BRN",      "undefined",                  "undefined" },
+  { 156, 0, "HPBL",     "undefined",                  "undefined" },
+  { 203, 0, "CLDEPTH",  "normalized cloud depth",     "1"         },
+  { 204, 0, "CLCT_MOD", "modified_total_cloud_cover", "1"         },
 };
 
-static PAR cosmo205[] = {
-  {   1, "SYNME5", "synthetic satellite images Meteosat5", "-" },
-  {   2, "SYNME6", "synthetic satellite images Meteosat6", "-" },
-  {   3, "SYNME7", "synthetic satellite images Meteosat7", "-" },
-  {   4, "SYNMSG", "synthetic satellite images MSG",       "-" },
+static const PAR cosmo205[] = {
+  {   1, 0, "SYNME5", "synthetic satellite images Meteosat5", "-" },
+  {   2, 0, "SYNME6", "synthetic satellite images Meteosat6", "-" },
+  {   3, 0, "SYNME7", "synthetic satellite images Meteosat7", "-" },
+  {   4, 0, "SYNMSG", "synthetic satellite images MSG",       "-" },
 };
 
-static PAR cosmo250[] = {
-  {   1, "QNH",       "sea level air pressure",                                         "hPa"                                },
-  {  11, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  12, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  13, "D_T_2M_K",  "kalman correction to 2m temperature",                            "K"                                  },
-  {  14, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  15, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  16, "RH_ICE",    "relative humidity over ice",                                     "%"                                  },
-  {  17, "TD",        "dew point temperature",                                          "K"                                  },
-  {  18, "D_TD",      "dew point depression",                                           "K"                                  },
-  {  19, "THETAE",    "equivalent potential temperature",                               "K"                                  },
-  {  20, "TD_2M_K",   "2m dew point temperature",                                       "K"                                  },
-  {  21, "D_TD_2M_K", "kalman correction to 2m dew point temperature",                  "K"                                  },
-  {  22, "TD_2M_OLD", "2m dew point temperature",                                       "K"                                  },
-  {  23, "TD_2M_BUZ", "2m dew point temperature",                                       "K"                                  },
-  {  24, "HI",        "heat index",                                                     "Fahrenheit"                         },
-  {  25, "DURSUN_M",  "maximum duration of sunshine",                                   "s"                                  },
-  {  26, "DURSUN_R",  "relative duration of sunshine",                                  "%"                                  },
-  {  52, "RH_2M_K",   "2m relative humidity",                                           "%"                                  },
-  {  53, "D_RH_2M_K", "kalman correction to 2m relative humidity",                      "%"                                  },
-  {  58, "CLI_RATIO", "cloud ice ratio (Qi/Qc+Qi)",                                     "%"                                  },
-  {  61, "TOT_SNOW",  "total precipitation in snow",                                    "kg/m**2"                            },
-  {  62, "TOT_RAIN",  "total precipitation in rain",                                    "kg/m**2"                            },
-  {  63, "TOT_CON",   "total convective precipitation",                                 "kg/m**2"                            },
-  {  64, "TOT_GSP",   "total large scale precipitation",                                "kg/m**2"                            },
-  {  65, "SNOW_%",    "percentage of precipitation in snow",                            "%"                                  },
-  {  66, "CONV_%",    "percentage of convective precipitation",                         "%"                                  },
-  {  67, "VORTP_ABS", "absolute",                                                       "VORTP_ABS 67 -1 absolute vorticity" },
-  {  68, "VORTP_REL", "relative",                                                       "VORTP_REL 68 -1 relative vorticity" },
-  {  70, "PDIFF_CON", "pressure difference between cloud base and cloud top",           "Pa"                                 },
-  {  71, "TTOP_CON",  "temperature at cloud top",                                       "K"                                  },
-  {  80, "GEM",       "emissivity of the ground",                                       "%"                                  },
-  {  82, "Z0LOC",     "local surface roughness length",                                 "m"                                  },
-  { 110, "LUM",       "luminosity",                                                     "klux"                               },
-  { 111, "GLOB",      "global shortwave radiation at surface",                          "W/m**2"                             },
-  { 112, "LW_IN_TG",  "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 113, "LW_IN_TS",  "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 114, "LW_IN_T2M", "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 115, "SWISS_WE",  "Swiss",                                                          "SWISS_WE 115 1 Swiss coordinates"   },
-  { 116, "SWISS_SN",  "Swiss",                                                          "SWISS_SN 116 1 Swiss coordinates"   },
-  { 150, "KOINDEX",   "KO index",                                                       "K"                                  },
-  { 151, "TTINDEX",   "total-totals index",                                             "K"                                  },
-  { 152, "DCI",       "deep convection index",                                          "K"                                  },
-  { 153, "SWEAT",     "severe weather thread index",                                    "undefined"                          },
-  { 154, "ADEDO2",    "adedokun 2 index",                                               "K"                                  },
-  { 160, "C_TSTORM",  "thunderstorm index using AdaBoost classifier",                   "undefined"                          },
-  { 161, "CN_TSTORM", "thunderstorm probabilty using AdaBoost classifier",              "%"                                  },
-  { 200, "WSHEARL",   "wind shear between surface and 3 km asl",                        "1/s"                                },
-  { 201, "WSHEARM",   "wind shear between surface and 6 km asl",                        "1/s"                                },
-  { 202, "WSHEARU",   "wind shear between 3 km (or surface) and 6 km asl",              "1/s"                                },
-  { 211, "VWIN",      "maximum OLD turbulent wind gust in 10m",                         "m s-1"                              },
-  { 212, "VW10M_20",  "maximum 10m wind speed",                                         "m s-1"                              },
-  { 213, "VW10M_25",  "duration of VWIN_10M above 25 knots",                            "s"                                  },
-  { 214, "VW10M_30",  "duration of VWIN_10M above 30 knots",                            "s"                                  },
-  { 215, "VW10M_35",  "duration of VWIN_10M above 35 knots",                            "s"                                  },
-  { 216, "VW10M_40",  "duration of VWIN_10M above 40 knots",                            "s"                                  },
-  { 217, "VW10M_45",  "duration of VWIN_10M above 45 knots",                            "s"                                  },
-  { 218, "VW10M_50",  "duration of VWIN_10M above 50 knots",                            "s"                                  },
-  { 219, "VOLD",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
-  { 220, "VJPS",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
-  { 221, "VBRA",      "maximum Brasseur turbulent wind gust in 10m",                    "m s-1"                              },
-  { 222, "VB10M_20",  "duration of VBRA_10M above 20 knots",                            "s"                                  },
-  { 223, "VB10M_25",  "duration of VBRA_10M above 25 knots",                            "s"                                  },
-  { 224, "VB10M_30",  "duration of VBRA_10M above 30 knots",                            "s"                                  },
-  { 225, "VB10M_35",  "duration of VBRA_10M above 35 knots",                            "s"                                  },
-  { 226, "VB10M_40",  "duration of VBRA_10M above 40 knots",                            "s"                                  },
-  { 227, "VB10M_45",  "duration of VBRA_10M above 45 knots",                            "s"                                  },
-  { 228, "VB10M_50",  "duration of VBRA_10M above 50 knots",                            "s"                                  },
-  { 231, "VCON",      "maximum convective wind gust in 10m",                            "m s-1"                              },
-  { 232, "VC10M_20",  "duration of VCON_10M above 20 knots",                            "s"                                  },
-  { 233, "VC10M_25",  "duration of VCON_10M above 25 knots",                            "s"                                  },
-  { 234, "VC10M_30",  "duration of VCON_10M above 30 knots",                            "s"                                  },
-  { 235, "VC10M_35",  "duration of VCON_10M above 35 knots",                            "s"                                  },
-  { 236, "VC10M_40",  "duration of VCON_10M above 40 knots",                            "s"                                  },
-  { 237, "VC10M_45",  "duration of VCON_10M above 45 knots",                            "s"                                  },
-  { 238, "VC10M_50",  "duration of VCON_10M above 50 knots",                            "s"                                  },
-  { 241, "FMAX",      "maximum wind speed at k=ke",                                     "m s-1"                              },
-  { 242, "USTARMAX",  "maximal u*=SQRT(Drag_coef)*fmax_10m",                            "m s-1"                              },
-  { 243, "GLOB_DIF",  "global diffuse shortwave radiation at the surface",              "W/m**2"                             },
-  { 244, "GLOB_DIR",  "global direct (beam) shortwave radiation at the surface",        "W/m**2"                             },
-  { 245, "GLOB_vE",   "global shortwave radiation on a vertical surface facing east",   "W/m**2"                             },
-  { 246, "GLOB_vS",   "global shortwave radiation on a vertical surface facing south",  "W/m**2"                             },
-  { 247, "GLOB_vW",   "global shortwave radiation on a vertical surface facing west",   "W/m**2"                             },
-  { 248, "GLOB_vN",   "global shortwave radiation on a vertical surface facing north",  "W/m**2"                             },
-  { 249, "LW_TG_vS",  "incoming longwave radiation on a vertical surface facing south", "W/m**2"                             },
-  { 250, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
-  { 251, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
-  { 252, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
-  { 253, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
-  { 254, "TW",        "wet bulb temperature",                                           "degC"                               },
-  { 255, "TW",        "wet bulb temperature",                                           "degC"                               },
+static const PAR cosmo250[] = {
+  {   1, 0, "QNH",       "sea level air pressure",                                         "hPa"                                },
+  {  11, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  12, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  13, 0, "D_T_2M_K",  "kalman correction to 2m temperature",                            "K"                                  },
+  {  14, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  15, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  16, 0, "RH_ICE",    "relative humidity over ice",                                     "%"                                  },
+  {  17, 0, "TD",        "dew point temperature",                                          "K"                                  },
+  {  18, 0, "D_TD",      "dew point depression",                                           "K"                                  },
+  {  19, 0, "THETAE",    "equivalent potential temperature",                               "K"                                  },
+  {  20, 0, "TD_2M_K",   "2m dew point temperature",                                       "K"                                  },
+  {  21, 0, "D_TD_2M_K", "kalman correction to 2m dew point temperature",                  "K"                                  },
+  {  22, 0, "TD_2M_OLD", "2m dew point temperature",                                       "K"                                  },
+  {  23, 0, "TD_2M_BUZ", "2m dew point temperature",                                       "K"                                  },
+  {  24, 0, "HI",        "heat index",                                                     "Fahrenheit"                         },
+  {  25, 0, "DURSUN_M",  "maximum duration of sunshine",                                   "s"                                  },
+  {  26, 0, "DURSUN_R",  "relative duration of sunshine",                                  "%"                                  },
+  {  52, 0, "RH_2M_K",   "2m relative humidity",                                           "%"                                  },
+  {  53, 0, "D_RH_2M_K", "kalman correction to 2m relative humidity",                      "%"                                  },
+  {  58, 0, "CLI_RATIO", "cloud ice ratio (Qi/Qc+Qi)",                                     "%"                                  },
+  {  61, 0, "TOT_SNOW",  "total precipitation in snow",                                    "kg/m**2"                            },
+  {  62, 0, "TOT_RAIN",  "total precipitation in rain",                                    "kg/m**2"                            },
+  {  63, 0, "TOT_CON",   "total convective precipitation",                                 "kg/m**2"                            },
+  {  64, 0, "TOT_GSP",   "total large scale precipitation",                                "kg/m**2"                            },
+  {  65, 0, "SNOW_%",    "percentage of precipitation in snow",                            "%"                                  },
+  {  66, 0, "CONV_%",    "percentage of convective precipitation",                         "%"                                  },
+  {  67, 0, "VORTP_ABS", "absolute",                                                       "VORTP_ABS 67 -1 absolute vorticity" },
+  {  68, 0, "VORTP_REL", "relative",                                                       "VORTP_REL 68 -1 relative vorticity" },
+  {  70, 0, "PDIFF_CON", "pressure difference between cloud base and cloud top",           "Pa"                                 },
+  {  71, 0, "TTOP_CON",  "temperature at cloud top",                                       "K"                                  },
+  {  80, 0, "GEM",       "emissivity of the ground",                                       "%"                                  },
+  {  82, 0, "Z0LOC",     "local surface roughness length",                                 "m"                                  },
+  { 110, 0, "LUM",       "luminosity",                                                     "klux"                               },
+  { 111, 0, "GLOB",      "global shortwave radiation at surface",                          "W/m**2"                             },
+  { 112, 0, "LW_IN_TG",  "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 113, 0, "LW_IN_TS",  "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 114, 0, "LW_IN_T2M", "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 115, 0, "SWISS_WE",  "Swiss",                                                          "SWISS_WE 115 1 Swiss coordinates"   },
+  { 116, 0, "SWISS_SN",  "Swiss",                                                          "SWISS_SN 116 1 Swiss coordinates"   },
+  { 150, 0, "KOINDEX",   "KO index",                                                       "K"                                  },
+  { 151, 0, "TTINDEX",   "total-totals index",                                             "K"                                  },
+  { 152, 0, "DCI",       "deep convection index",                                          "K"                                  },
+  { 153, 0, "SWEAT",     "severe weather thread index",                                    "undefined"                          },
+  { 154, 0, "ADEDO2",    "adedokun 2 index",                                               "K"                                  },
+  { 160, 0, "C_TSTORM",  "thunderstorm index using AdaBoost classifier",                   "undefined"                          },
+  { 161, 0, "CN_TSTORM", "thunderstorm probabilty using AdaBoost classifier",              "%"                                  },
+  { 200, 0, "WSHEARL",   "wind shear between surface and 3 km asl",                        "1/s"                                },
+  { 201, 0, "WSHEARM",   "wind shear between surface and 6 km asl",                        "1/s"                                },
+  { 202, 0, "WSHEARU",   "wind shear between 3 km (or surface) and 6 km asl",              "1/s"                                },
+  { 211, 0, "VWIN",      "maximum OLD turbulent wind gust in 10m",                         "m s-1"                              },
+  { 212, 0, "VW10M_20",  "maximum 10m wind speed",                                         "m s-1"                              },
+  { 213, 0, "VW10M_25",  "duration of VWIN_10M above 25 knots",                            "s"                                  },
+  { 214, 0, "VW10M_30",  "duration of VWIN_10M above 30 knots",                            "s"                                  },
+  { 215, 0, "VW10M_35",  "duration of VWIN_10M above 35 knots",                            "s"                                  },
+  { 216, 0, "VW10M_40",  "duration of VWIN_10M above 40 knots",                            "s"                                  },
+  { 217, 0, "VW10M_45",  "duration of VWIN_10M above 45 knots",                            "s"                                  },
+  { 218, 0, "VW10M_50",  "duration of VWIN_10M above 50 knots",                            "s"                                  },
+  { 219, 0, "VOLD",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
+  { 220, 0, "VJPS",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
+  { 221, 0, "VBRA",      "maximum Brasseur turbulent wind gust in 10m",                    "m s-1"                              },
+  { 222, 0, "VB10M_20",  "duration of VBRA_10M above 20 knots",                            "s"                                  },
+  { 223, 0, "VB10M_25",  "duration of VBRA_10M above 25 knots",                            "s"                                  },
+  { 224, 0, "VB10M_30",  "duration of VBRA_10M above 30 knots",                            "s"                                  },
+  { 225, 0, "VB10M_35",  "duration of VBRA_10M above 35 knots",                            "s"                                  },
+  { 226, 0, "VB10M_40",  "duration of VBRA_10M above 40 knots",                            "s"                                  },
+  { 227, 0, "VB10M_45",  "duration of VBRA_10M above 45 knots",                            "s"                                  },
+  { 228, 0, "VB10M_50",  "duration of VBRA_10M above 50 knots",                            "s"                                  },
+  { 231, 0, "VCON",      "maximum convective wind gust in 10m",                            "m s-1"                              },
+  { 232, 0, "VC10M_20",  "duration of VCON_10M above 20 knots",                            "s"                                  },
+  { 233, 0, "VC10M_25",  "duration of VCON_10M above 25 knots",                            "s"                                  },
+  { 234, 0, "VC10M_30",  "duration of VCON_10M above 30 knots",                            "s"                                  },
+  { 235, 0, "VC10M_35",  "duration of VCON_10M above 35 knots",                            "s"                                  },
+  { 236, 0, "VC10M_40",  "duration of VCON_10M above 40 knots",                            "s"                                  },
+  { 237, 0, "VC10M_45",  "duration of VCON_10M above 45 knots",                            "s"                                  },
+  { 238, 0, "VC10M_50",  "duration of VCON_10M above 50 knots",                            "s"                                  },
+  { 241, 0, "FMAX",      "maximum wind speed at k=ke",                                     "m s-1"                              },
+  { 242, 0, "USTARMAX",  "maximal u*=SQRT(Drag_coef)*fmax_10m",                            "m s-1"                              },
+  { 243, 0, "GLOB_DIF",  "global diffuse shortwave radiation at the surface",              "W/m**2"                             },
+  { 244, 0, "GLOB_DIR",  "global direct (beam) shortwave radiation at the surface",        "W/m**2"                             },
+  { 245, 0, "GLOB_vE",   "global shortwave radiation on a vertical surface facing east",   "W/m**2"                             },
+  { 246, 0, "GLOB_vS",   "global shortwave radiation on a vertical surface facing south",  "W/m**2"                             },
+  { 247, 0, "GLOB_vW",   "global shortwave radiation on a vertical surface facing west",   "W/m**2"                             },
+  { 248, 0, "GLOB_vN",   "global shortwave radiation on a vertical surface facing north",  "W/m**2"                             },
+  { 249, 0, "LW_TG_vS",  "incoming longwave radiation on a vertical surface facing south", "W/m**2"                             },
+  { 250, 0, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
+  { 251, 0, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
+  { 252, 0, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
+  { 253, 0, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
+  { 254, 0, "TW",        "wet bulb temperature",                                           "degC"                               },
+  { 255, 0, "TW",        "wet bulb temperature",                                           "degC"                               },
 };
 
 
-void
+static void
 tableDefault(void)
 {
   int tableID, instID, modelID;
@@ -4276,7 +4335,7 @@ tableDefault(void)
 #ifndef _GAUSSGRID_H
 #define _GAUSSGRID_H
 
-void   gaussaw(double *restrict pa, double *restrict pw, int nlat);
+void   gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
 
 #endif  /* _GAUSSGRID_H */
 /*
@@ -4414,7 +4473,7 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
 void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
 		  int level1, int level2, int level_sf, int level_unit, int prec,
-		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype,
+		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
 		  const char *name, const char *stdname, const char *longname, const char *units);
 
 void varDefVCT(size_t vctsize, double *vctptr);
@@ -4436,6 +4495,7 @@ int  varInqTable(int varID);
 void varDefEnsembleInfo(int varID, int ens_idx, int ens_count, int forecast_type);
 
 void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess);
+void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate);
 
 
 void varDefOptGribInt(int varID, long lval, const char *keyword);
@@ -4534,7 +4594,7 @@ srvrec_t *srvNew(void);
 void srvDelete(srvrec_t *srvp);
 
 int  srvRead(int fileID, srvrec_t *srvp);
-int  srvWrite(int fileID, srvrec_t *srvp);
+void srvWrite(int fileID, srvrec_t *srvp);
 
 int  srvInqHeader(srvrec_t *srvp, int *header);
 int  srvInqDataSP(srvrec_t *srvp, float *data);
@@ -4566,10 +4626,10 @@ int    srvInqContents(stream_t *streamptr);
 int    srvInqTimestep(stream_t *streamptr, int tsID);
 
 int    srvInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    srvDefRecord(stream_t *streamptr);
-int    srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    srvReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    srvWriteRecord(stream_t *streamptr, const double *data);
+void   srvDefRecord(stream_t *streamptr);
+void   srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   srvReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   srvWriteRecord(stream_t *streamptr, const double *data);
 
 void   srvReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   srvWriteVarDP(stream_t *streamptr, int varID, const double *data);
@@ -4598,10 +4658,10 @@ int    extInqContents(stream_t *streamptr);
 int    extInqTimestep(stream_t *streamptr, int tsID);
 
 int    extInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    extDefRecord(stream_t *streamptr);
-int    extCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    extReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    extWriteRecord(stream_t *streamptr, const double *data);
+void   extDefRecord(stream_t *streamptr);
+void   extCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   extReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   extWriteRecord(stream_t *streamptr, const double *data);
 
 void   extReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   extWriteVarDP(stream_t *streamptr, int varID, const double *data);
@@ -4630,10 +4690,10 @@ int    iegInqContents(stream_t *streamptr);
 int    iegInqTimestep(stream_t *streamptr, int tsID);
 
 int    iegInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    iegDefRecord(stream_t *streamptr);
-int    iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    iegReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    iegWriteRecord(stream_t *streamptr, const double *data);
+void   iegDefRecord(stream_t *streamptr);
+void   iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   iegReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   iegWriteRecord(stream_t *streamptr, const double *data);
 
 void   iegReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   iegWriteVarDP(stream_t *streamptr, int varID, const double *data);
@@ -4675,14 +4735,11 @@ void cdf_inq_dimid (int ncid, const char *name, int *dimidp);
 void cdf_inq_dim (int ncid, int dimid, char *name, size_t * lengthp);
 void cdf_inq_dimname (int ncid, int dimid, char *name);
 void cdf_inq_dimlen (int ncid, int dimid, size_t * lengthp);
-void cdf_def_var (int ncid, const char *name, nc_type xtype, int ndims,
-		 const int dimids[], int *varidp);
-void cdf_def_var_serial(int ncid, const char *name, nc_type xtype, int ndims,
-                        const int dimids[], int *varidp);
-void cdf_inq_varid (int ncid, const char *name, int *varidp);
-void cdf_inq_nvars (int ncid, int *nvarsp);
-void cdf_inq_var (int ncid, int varid, char *name, nc_type *xtypep,
-		 int *ndimsp, int dimids[], int *nattsp);
+void cdf_def_var (int ncid, const char *name, nc_type xtype, int ndims, const int dimids[], int *varidp);
+void cdf_def_var_serial(int ncid, const char *name, nc_type xtype, int ndims, const int dimids[], int *varidp);
+void cdf_inq_varid(int ncid, const char *name, int *varidp);
+void cdf_inq_nvars(int ncid, int *nvarsp);
+void cdf_inq_var(int ncid, int varid, char *name, nc_type *xtypep, int *ndimsp, int dimids[], int *nattsp);
 void cdf_inq_varname (int ncid, int varid, char *name);
 void cdf_inq_vartype (int ncid, int varid, nc_type *xtypep);
 void cdf_inq_varndims (int ncid, int varid, int *ndimsp);
@@ -4713,36 +4770,29 @@ void cdf_get_var1_text(int ncid, int varid, const size_t index[], char *tp);
 void cdf_get_var1_double(int ncid, int varid, const size_t index[], double *dp);
 void cdf_put_var1_double(int ncid, int varid, const size_t index[], const double *dp);
 
-void cdf_get_vara_text(int ncid, int varid, const size_t start[],
-		       const size_t count[], char *tp);
+void cdf_get_vara_uchar(int ncid, int varid, const size_t start[], const size_t count[], unsigned char *tp);
+void cdf_get_vara_text(int ncid, int varid, const size_t start[], const size_t count[], char *tp);
 
-void cdf_get_vara_double(int ncid, int varid, const size_t start[],
-                         const size_t count[], double *dp);
-void cdf_put_vara_double(int ncid, int varid, const size_t start[],
-                         const size_t count[], const double *dp);
-
-void cdf_get_vara_float(int ncid, int varid, const size_t start[],
-                        const size_t count[], float *fp);
-void cdf_put_vara_float(int ncid, int varid, const size_t start[],
-                        const size_t count[], const float *fp);
-
-void cdf_put_att_text (int ncid, int varid, const char *name, size_t len,
-		      const char *tp);
-void cdf_put_att_int (int ncid, int varid, const char *name, nc_type xtype,
-		     size_t len, const int *ip);
-void cdf_put_att_double (int ncid, int varid, const char *name, nc_type xtype,
-			size_t len, const double *dp);
-
-void cdf_get_att_text (int ncid, int varid, char *name, char *tp);
-void cdf_get_att_int (int ncid, int varid, char *name, int *ip);
-void cdf_get_att_double (int ncid, int varid, char *name, double *dp);
-
-void cdf_inq_att (int ncid, int varid, const char *name, nc_type * xtypep,
-		 size_t * lenp);
-void cdf_inq_atttype (int ncid, int varid, const char *name, nc_type *xtypep);
+void cdf_get_vara_double(int ncid, int varid, const size_t start[], const size_t count[], double *dp);
+void cdf_put_vara_double(int ncid, int varid, const size_t start[], const size_t count[], const double *dp);
+
+void cdf_get_vara_float(int ncid, int varid, const size_t start[], const size_t count[], float *fp);
+void cdf_put_vara_float(int ncid, int varid, const size_t start[], const size_t count[], const float *fp);
+
+void cdf_put_att_text(int ncid, int varid, const char *name, size_t len, const char *tp);
+void cdf_put_att_int(int ncid, int varid, const char *name, nc_type xtype, size_t len, const int *ip);
+void cdf_put_att_double(int ncid, int varid, const char *name, nc_type xtype, size_t len, const double *dp);
+
+void cdf_get_att_string(int ncid, int varid, const char *name, char **tp);
+void cdf_get_att_text  (int ncid, int varid, const char *name, char *tp);
+void cdf_get_att_int   (int ncid, int varid, const char *name, int *ip);
+void cdf_get_att_double(int ncid, int varid, const char *name, double *dp);
+
+void cdf_inq_att    (int ncid, int varid, const char *name, nc_type * xtypep, size_t * lenp);
+void cdf_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep);
 void cdf_inq_attlen (int ncid, int varid, const char *name, size_t *lenp);
-void cdf_inq_attname (int ncid, int varid, int attnum, char *name);
-void cdf_inq_attid (int ncid, int varid, const char *name, int *attnump);
+void cdf_inq_attname(int ncid, int varid, int attnum, char *name);
+void cdf_inq_attid  (int ncid, int varid, const char *name, int *attnump);
 
 typedef int (*cdi_nc__create_funcp)(const char *path, int cmode,
                                     size_t initialsz, size_t *chunksizehintp,
@@ -4875,6 +4925,7 @@ typedef struct
   int         timave;
   int         timaccu;
   int         typeOfGeneratingProcess;
+  int         productDefinitionTemplate;
   int         chunktype;
   int         xyz;
   int         missvalused; /* TRUE if missval is defined */
@@ -4902,10 +4953,12 @@ typedef struct
   /* (Optional) list of keyword/double value pairs */
   int    opt_grib_dbl_nentries;
   char*  opt_grib_dbl_keyword[MAX_OPT_GRIB_ENTRIES];
+  int    opt_grib_dbl_update[MAX_OPT_GRIB_ENTRIES];
   double opt_grib_dbl_val[MAX_OPT_GRIB_ENTRIES];
   /* (Optional) list of keyword/integer value pairs */
   int    opt_grib_int_nentries;
   char*  opt_grib_int_keyword[MAX_OPT_GRIB_ENTRIES];
+  int    opt_grib_int_update[MAX_OPT_GRIB_ENTRIES];
   int    opt_grib_int_val[MAX_OPT_GRIB_ENTRIES];
 #endif
 }
@@ -4914,6 +4967,7 @@ var_t;
 
 typedef struct
 {
+  int         locked;
   int         self;
   int         nvars;        /* number of variables                */
   int         ngrids;
@@ -4956,8 +5010,42 @@ void    vlistDefVarValidrange(int vlistID, int varID, const double *validrange);
 /*      vlistInqVarValidrange: Get the valid range of a Variable */
 int     vlistInqVarValidrange(int vlistID, int varID, double *validrange);
 
-int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB,
-                      int attnum);
+int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
+
+void vlist_lock(int vlistID);
+void vlist_unlock(int vlistID);
+
+static inline void
+vlistAdd2GridIDs(vlist_t *vlistptr, int gridID)
+{
+  int index, ngrids = vlistptr->ngrids;
+  for ( index = 0; index < ngrids; index++ )
+    if (vlistptr->gridIDs[index] == gridID ) break;
+  if ( index == ngrids )
+    {
+      if (ngrids >= MAX_GRIDS_PS)
+        Error("Internal limit exceeded: more than %d grids.", MAX_GRIDS_PS);
+      ++(vlistptr->ngrids);
+      vlistptr->gridIDs[ngrids] = gridID;
+    }
+}
+
+static inline void
+vlistAdd2ZaxisIDs(vlist_t *vlistptr, int zaxisID)
+{
+  int index, nzaxis = vlistptr->nzaxis;
+  for ( index = 0; index < nzaxis; index++ )
+    if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
+
+  if ( index == nzaxis )
+    {
+      if ( nzaxis >= MAX_ZAXES_PS )
+	Error("Internal limit exceeded: more than %d zaxis.", MAX_ZAXES_PS);
+      vlistptr->zaxisIDs[nzaxis] = zaxisID;
+      vlistptr->nzaxis++;
+    }
+}
+
 
 #if  defined  (HAVE_LIBGRIB_API)
 extern int   cdiNAdditionalGRIBKeys;
@@ -5090,6 +5178,7 @@ enum
   MODEL     = 5,
   STREAM    = 6,
   VLIST     = 7,
+  RESH_DELETE,
   START     = 55555555,
   SEPARATOR = 66666666,
   END       = 99999999
@@ -5129,6 +5218,29 @@ void serializeUnpackInCore(void *buf, int buf_size, int *position,
                             void *data, int count, int datatype, void *context);
 
 #endif
+#ifndef STREAM_FCOMMON_H
+#define STREAM_FCOMMON_H
+
+#include "cdi_int.h"
+
+enum {
+  SINGLE_PRECISION = 4,
+  DOUBLE_PRECISION = 8,
+};
+
+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:
+ */
 #if  defined  (HAVE_CONFIG_H)
 #endif
 
@@ -5178,8 +5290,8 @@ typedef struct
 }
 MemTable_t;
 
-static MemTable_t* memTable;
-static int     memTableSize  = 0;
+static MemTable_t *memTable;
+static size_t  memTableSize  = 0;
 static long    memAccess     = 0;
 
 static size_t  MemObjs       = 0;
@@ -5259,23 +5371,23 @@ void memListPrintEntry(int mtype, int item, size_t size, void *ptr,
 static
 void memListPrintTable(void)
 {
-  int memID, item, item1, item2 = 0;
+  int item, item1, item2 = 0;
 
   if ( MemObjs ) fprintf(stderr, "\nMemory table:\n");
 
   /* find maximum item */
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (size_t memID = 0; memID < memTableSize; memID++)
     if ( memTable[memID].item != UNDEFID )
       if ( memTable[memID].item > item2 ) item2 = memTable[memID].item;
 
   /* find minimum item */
   item1 = item2;
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (size_t memID = 0; memID < memTableSize; memID++)
     if ( memTable[memID].item != UNDEFID )
       if ( memTable[memID].item < item1 ) item1 = memTable[memID].item;
 
   for ( item = item1; item <= item2; item++ )
-    for ( memID = 0; memID < memTableSize; memID++ )
+    for (size_t memID = 0; memID < memTableSize; memID++)
       {
 	if ( memTable[memID].item == item )
 	  memListPrintEntry(memTable[memID].mtype, memTable[memID].item,
@@ -5287,7 +5399,7 @@ void memListPrintTable(void)
   if ( MemObjs )
     {
       fprintf(stderr, "  Memory access             : %6u\n", (unsigned) memAccess);
-      fprintf(stderr, "  Maximum objects           : %6u\n", (unsigned) memTableSize);
+      fprintf(stderr, "  Maximum objects           : %6zu\n", memTableSize);
       fprintf(stderr, "  Objects used              : %6u\n", (unsigned) MaxMemObjs);
       fprintf(stderr, "  Objects in use            : %6u\n", (unsigned) MemObjs);
       fprintf(stderr, "  Memory allocated          : ");
@@ -5347,10 +5459,10 @@ void memInit(void)
 static
 int memListDeleteEntry(void *ptr, size_t *size)
 {
-  int memID = 0;
   int item = UNDEFID;
+  size_t memID;
 
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (memID = 0; memID < memTableSize; memID++ )
     {
       if ( memTable[memID].item == UNDEFID ) continue;
       if ( memTable[memID].ptr == ptr ) break;
@@ -5369,9 +5481,9 @@ int memListDeleteEntry(void *ptr, size_t *size)
 }
 
 static
-void memTableInitEntry(int memID)
+void memTableInitEntry(size_t memID)
 {
-  if ( memID < 0 || memID >= memTableSize )
+  if ( memID >= memTableSize )
     memInternalProblem(__func__, "memID %d undefined!", memID);
 
   memTable[memID].ptr    = NULL;
@@ -5388,9 +5500,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 {
   static int item = 0;
   size_t memSize = 0;
-  int memID = 0;
-  size_t len;
-  int i;
+  size_t memID = 0;
 
   /*
     Look for a free slot in memTable.
@@ -5399,11 +5509,11 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
   if ( memTableSize == 0 )
     {
       memTableSize = 8;
-      memSize  = memTableSize*sizeof(MemTable_t);
-      memTable = (MemTable_t*) malloc(memSize);
+      memSize  = memTableSize * sizeof(MemTable_t);
+      memTable = (MemTable_t *) malloc(memSize);
       if( memTable == NULL ) memError(__func__, __FILE__, __LINE__, memSize);
 
-      for( i = 0; i < memTableSize; i++ )
+      for(size_t i = 0; i < memTableSize; i++)
 	memTableInitEntry(i);
     }
   else
@@ -5424,7 +5534,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
       memTable = (MemTable_t*) realloc(memTable, memSize);
       if( memTable == NULL ) memError(__func__, __FILE__, __LINE__, memSize);
 
-      for( i = memID; i < memTableSize; i++ )
+      for (size_t i = memID; i < memTableSize; i++)
 	memTableInitEntry(i);
     }
 
@@ -5437,7 +5547,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 
   if ( file )
     {
-      len = strlen(file);
+      size_t len = strlen(file);
       if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
       (void) memcpy(memTable[memID].file, file, len);
@@ -5450,7 +5560,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 
   if ( caller )
     {
-      len = strlen(caller);
+      size_t len = strlen(caller);
       if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
       (void) memcpy(memTable[memID].caller, caller, len);
@@ -5475,7 +5585,6 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 {
   int item = UNDEFID;
   int memID = 0;
-  size_t len;
   size_t sizeold;
 
   while( memID < memTableSize )
@@ -5504,7 +5613,7 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 
       if ( file )
 	{
-	  len = strlen(file);
+	  size_t len = strlen(file);
 	  if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
 	  (void) memcpy(memTable[memID].file, file, len);
@@ -5517,7 +5626,7 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 
       if ( caller )
 	{
-	  len = strlen(caller);
+	  size_t len = strlen(caller);
 	  if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
 	  (void) memcpy(memTable[memID].caller, caller, len);
@@ -5693,21 +5802,21 @@ size_t memTotal(void)
   struct mallinfo meminfo = mallinfo();
   if ( MEM_Debug )
     {
-      fprintf(stderr, "arena      %8ld (non-mmapped space allocated from system)\n", (unsigned long) meminfo.arena);
-      fprintf(stderr, "ordblks    %8ld (number of free chunks)\n", (unsigned long) meminfo.ordblks);
-      fprintf(stderr, "smblks     %8ld (number of fastbin blocks)\n", (unsigned long) meminfo.smblks);
-      fprintf(stderr, "hblks      %8ld (number of mmapped regions)\n", (unsigned long) meminfo.hblks);
-      fprintf(stderr, "hblkhd     %8ld (space in mmapped regions)\n", (unsigned long) meminfo.hblkhd);
-      fprintf(stderr, "usmblks    %8ld (maximum total allocated space)\n", (unsigned long) meminfo.usmblks);
-      fprintf(stderr, "fsmblks    %8ld (maximum total allocated space)\n", (unsigned long) meminfo.fsmblks);
-      fprintf(stderr, "uordblks   %8ld (total allocated space)\n", (unsigned long) meminfo.uordblks);
-      fprintf(stderr, "fordblks   %8ld (total free space)\n", (unsigned long) meminfo.fordblks);
-      fprintf(stderr, "Memory in use:   %8ld bytes\n", (unsigned long) meminfo.usmblks + meminfo.uordblks);
-      fprintf(stderr, "Total heap size: %8ld bytes\n", (unsigned long) meminfo.arena);
+      fprintf(stderr, "arena      %8zu (non-mmapped space allocated from system)\n", (size_t)meminfo.arena);
+      fprintf(stderr, "ordblks    %8zu (number of free chunks)\n", (size_t)meminfo.ordblks);
+      fprintf(stderr, "smblks     %8zu (number of fastbin blocks)\n", (size_t) meminfo.smblks);
+      fprintf(stderr, "hblks      %8zu (number of mmapped regions)\n", (size_t) meminfo.hblks);
+      fprintf(stderr, "hblkhd     %8zu (space in mmapped regions)\n", (size_t) meminfo.hblkhd);
+      fprintf(stderr, "usmblks    %8zu (maximum total allocated space)\n", (size_t) meminfo.usmblks);
+      fprintf(stderr, "fsmblks    %8zu (maximum total allocated space)\n", (size_t) meminfo.fsmblks);
+      fprintf(stderr, "uordblks   %8zu (total allocated space)\n", (size_t) meminfo.uordblks);
+      fprintf(stderr, "fordblks   %8zu (total free space)\n", (size_t) meminfo.fordblks);
+      fprintf(stderr, "Memory in use:   %8zu bytes\n", (size_t) meminfo.usmblks + (size_t)meminfo.uordblks);
+      fprintf(stderr, "Total heap size: %8zu bytes\n", (size_t) meminfo.arena);
 
       /* malloc_stats(); */
     }
-  memtotal = meminfo.arena;
+  memtotal = (size_t)meminfo.arena;
 #endif
 
   return (memtotal);
@@ -5790,12 +5899,16 @@ void *cdiXrealloc(void *, size_t, const char *, const char *, int);
  * require-trailing-newline: t
  * End:
  */
-#include <inttypes.h>
 #ifdef HAVE_CONFIG_H
 #endif
 
+#include <inttypes.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#ifdef WORDS_BIGENDIAN
+#include <limits.h>
+#endif
+
 
 static const uint32_t crctab[] = {
   0x00000000,
@@ -5862,18 +5975,13 @@ memcrc(const unsigned char *b, size_t n)
  */
 
 
-  register uint32_t i, c, s = 0;
-
-
-  for (i = n; i > 0; --i) {
-    c = (uint32_t)(*b++);
-    s = (s << 8) ^ crctab[(s >> 24) ^ c];
-  }
+  uint32_t s = 0;
 
+  memcrc_r(&s, b, n);
 
   /* Extend with the length of the string. */
   while (n != 0) {
-    c = n & 0377;
+    register uint32_t c = n & 0377;
     n >>= 8;
     s = (s << 8) ^ crctab[(s >> 24) ^ c];
   }
@@ -5891,11 +5999,11 @@ memcrc_r(uint32_t *state, const unsigned char *block, size_t block_len)
  */
 
 
-  register uint32_t i, c, s = *state;
+  register uint32_t c, s = *state;
   register size_t n = block_len;
   register const unsigned char *b = block;
 
-  for (i = n; i > 0; --i) {
+  for (; n > 0; --n) {
     c = (uint32_t)(*b++);
     s = (s << 8) ^ crctab[(s >> 24) ^ c];
   }
@@ -5963,7 +6071,7 @@ uint32_t
 memcrc_finish(uint32_t *state, off_t total_size)
 {
   register uint32_t c, s = *state;
-  register off_t n = total_size;
+  register uint64_t n = (uint64_t)total_size;
 
   /* Extend with the length of the string. */
   while (n != 0) {
@@ -5984,7 +6092,12 @@ memcrc_finish(uint32_t *state, off_t total_size)
  * require-trailing-newline: t
  * End:
  */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <inttypes.h>
+#include <sys/types.h>
 #include <stdlib.h>
 
 
@@ -5993,13 +6106,14 @@ uint32_t cdiCheckSum(int type, int count, void *buffer)
   uint32_t s = 0U;
   xassert(count >= 0);
   size_t elemSize = (size_t)serializeGetSizeInCore(1, type, NULL);
-  memcrc_r_eswap(&s, (const unsigned char*) buffer, count, elemSize);
-  s = memcrc_finish(&s, elemSize * (size_t)count);
+  memcrc_r_eswap(&s, (const unsigned char *)buffer, (size_t)count, elemSize);
+  s = memcrc_finish(&s, (off_t)(elemSize * (size_t)count));
   return s;
 }
 #if defined (HAVE_CONFIG_H)
 #endif
 
+#include <stddef.h>
 #include <string.h>
 
 
@@ -6014,14 +6128,15 @@ char *Timeunits[] = {
   "undefined",
   "seconds",
   "minutes",
-  "hours",
-  "days",
-  "months",
-  "years",
   "quarters",
+  "30minutes",
+  "hours",
   "3hours",
   "6hours",
   "12hours",
+  "days",
+  "months",
+  "years",
 };
 
 
@@ -6042,6 +6157,50 @@ const resOps taxisOps = {
   taxisTxCode
 };
 
+#define container_of(ptr, type, member) \
+  ((type *)((unsigned char *)ptr - offsetof(type,member)))
+
+struct refcount_string
+{
+  int ref_count;
+  char string[];
+};
+
+static char *
+new_refcount_string(size_t len)
+{
+  struct refcount_string *container
+    = xmalloc(sizeof (*container) + len + 1);
+  container->ref_count = 1;
+  return container->string;
+}
+
+static void
+delete_refcount_string(void *p)
+{
+  if (p)
+    {
+      struct refcount_string *container
+        = container_of(p, struct refcount_string, string);
+      if (!--(container->ref_count))
+        free(container);
+    }
+}
+
+static char *
+dup_refcount_string(char *p)
+{
+  if (p)
+    {
+      struct refcount_string *container
+        = container_of(p, struct refcount_string, string);
+      ++(container->ref_count);
+    }
+  return p;
+}
+
+
+#undef container_of
 
 static int  TAXIS_Debug = 0;   /* If set to 1, debugging */
 
@@ -6214,16 +6373,14 @@ int taxisCreate(int taxistype)
   return (taxisID);
 }
 
-static
-void taxisDestroyKernel( taxis_t * taxisptr )
+void taxisDestroyKernel(taxis_t *taxisptr)
 {
   taxis_check_ptr(__func__, taxisptr);
-
   int id = taxisptr->self;
-
-  free ( taxisptr );
-
-  reshRemove ( id, &taxisOps );
+  delete_refcount_string(taxisptr->name);
+  delete_refcount_string(taxisptr->longname);
+  if (id != CDI_UNDEFID)
+    reshRemove(id, &taxisOps);
 }
 
 /*
@@ -6238,27 +6395,23 @@ void taxisDestroyKernel( taxis_t * taxisptr )
 */
 void taxisDestroy(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
-
-  if ( taxisptr->name     ) free(taxisptr->name);
-  if ( taxisptr->longname ) free(taxisptr->longname);
-
-  taxisDestroyKernel ( taxisptr );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
+  taxisDestroyKernel(taxisptr);
+  free(taxisptr);
 }
 
 
 void taxisDestroyP( void * taxisptr )
 {
-  taxisDestroyKernel (( taxis_t * ) taxisptr );
+  taxisDestroyKernel((taxis_t *)taxisptr);
+  free(taxisptr);
 }
 
 
 int taxisDuplicate(int taxisID1)
 {
-  taxis_t *taxisptr1 = ( taxis_t * ) reshGetVal ( taxisID1, &taxisOps );
-
+  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps);
   taxis_t *taxisptr2 = taxisNewEntry(CDI_UNDEFID);
-  if ( ! taxisptr2 ) Error("No memory");
 
   int taxisID2 = taxisptr2->self;
 
@@ -6266,28 +6419,21 @@ int taxisDuplicate(int taxisID1)
     Message("taxisID2: %d", taxisID2);
 
   ptaxisCopy(taxisptr2, taxisptr1);
-  if ( taxisptr1->name     ) taxisptr2->name = strdup(taxisptr1->name);
-  if ( taxisptr1->longname ) taxisptr2->longname = strdup(taxisptr1->longname);
-
-  // taxisptr2->has_bounds = FALSE;
-
   return (taxisID2);
 }
 
 
 void taxisDefType(int taxisID, int type)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->type = type;
+  if (taxisptr->type != type)
+    {
+      taxisptr->type = type;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6306,11 +6452,15 @@ The function @func{taxisDefVdate} defines the verification date of a Time axis.
 */
 void taxisDefVdate(int taxisID, int vdate)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->vdate = vdate;
+  if (taxisptr->vdate != vdate)
+    {
+      taxisptr->vdate = vdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6329,11 +6479,15 @@ The function @func{taxisDefVtime} defines the verification time of a Time axis.
 */
 void taxisDefVtime(int taxisID, int vtime)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->vtime = vtime;
+  if (taxisptr->vtime != vtime)
+    {
+      taxisptr->vtime = vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6352,17 +6506,15 @@ The function @func{taxisDefRdate} defines the reference date of a Time axis.
 */
 void taxisDefRdate(int taxisID, int rdate)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->rdate = rdate;
+  if (taxisptr->rdate != rdate)
+    {
+      taxisptr->rdate = rdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6381,17 +6533,15 @@ The function @func{taxisDefRtime} defines the reference time of a Time axis.
 */
 void taxisDefRtime(int taxisID, int rtime)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->rtime = rtime;
+  if (taxisptr->rtime != rtime)
+    {
+      taxisptr->rtime = rtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6410,17 +6560,15 @@ The function @func{taxisDefFdate} defines the forecast reference date of a Time
 */
 void taxisDefFdate(int taxisID, int fdate)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fdate = fdate;
+  if (taxisptr->fdate != fdate)
+    {
+      taxisptr->fdate = fdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6439,17 +6587,15 @@ The function @func{taxisDefFtime} defines the forecast reference time of a Time
 */
 void taxisDefFtime(int taxisID, int ftime)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->ftime = ftime;
+  if (taxisptr->ftime != ftime)
+    {
+      taxisptr->ftime = ftime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6470,81 +6616,71 @@ The function @func{taxisDefCalendar} defines the calendar of a Time axis.
 */
 void taxisDefCalendar(int taxisID, int calendar)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->calendar = calendar;
+  if (taxisptr->calendar != calendar)
+    {
+      taxisptr->calendar = calendar;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefTunit(int taxisID, int unit)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->unit = unit;
+  if (taxisptr->unit != unit)
+    {
+      taxisptr->unit = unit;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefForecastTunit(int taxisID, int unit)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fc_unit = unit;
+  if (taxisptr->fc_unit != unit)
+    {
+      taxisptr->fc_unit = unit;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefForecastPeriod(int taxisID, double fc_period)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fc_period = fc_period;
+  if (taxisptr->fc_period != fc_period)
+    {
+      taxisptr->fc_period = fc_period;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefNumavg(int taxisID, int numavg)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->numavg = numavg;
+  if (taxisptr->numavg != numavg)
+    {
+      taxisptr->numavg = numavg;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6553,7 +6689,7 @@ The valid CDI time types are TAXIS_ABSOLUTE and TAXIS_RELATIVE.
 */
 int taxisInqType(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6563,7 +6699,7 @@ int taxisInqType(int taxisID)
 
 int taxisHasBounds(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6573,29 +6709,27 @@ int taxisHasBounds(int taxisID)
 
 void taxisDeleteBounds(int taxisID)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->has_bounds = FALSE;
+  if (taxisptr->has_bounds != FALSE)
+    {
+      taxisptr->has_bounds = FALSE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisCopyTimestep(int taxisID2, int taxisID1)
 {
-  taxis_t *taxisptr1 = ( taxis_t * ) reshGetVal ( taxisID1, &taxisOps );
-  taxis_t *taxisptr2 = ( taxis_t * ) reshGetVal ( taxisID2, &taxisOps );
+  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps),
+    *taxisptr2 = (taxis_t *)reshGetVal(taxisID2, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr1);
   taxis_check_ptr(__func__, taxisptr2);
 
-  reshLock ();
+  reshLock();
 
   taxisptr2->rdate = taxisptr1->rdate;
   taxisptr2->rtime = taxisptr1->rtime;
@@ -6617,7 +6751,8 @@ void taxisCopyTimestep(int taxisID2, int taxisID1)
   taxisptr2->fc_unit   = taxisptr1->fc_unit;
   taxisptr2->fc_period = taxisptr1->fc_period;
 
-  reshUnlock ();
+  reshSetStatus(taxisID2, &taxisOps, RESH_DESYNC_IN_USE);
+  reshUnlock();
 }
 
 /*
@@ -6638,7 +6773,7 @@ The function @func{taxisInqVdate} returns the verification date of a Time axis.
 */
 int taxisInqVdate(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6648,7 +6783,7 @@ int taxisInqVdate(int taxisID)
 
 void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6659,20 +6794,19 @@ void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
 
 void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  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 != TRUE)
+    {
+      taxisptr->vdate_lb = vdate_lb;
+      taxisptr->vdate_ub = vdate_ub;
+      taxisptr->has_bounds = TRUE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6693,7 +6827,7 @@ The function @func{taxisInqVtime} returns the verification time of a Time axis.
 */
 int taxisInqVtime(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6703,7 +6837,7 @@ int taxisInqVtime(int taxisID)
 
 void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -6714,20 +6848,19 @@ void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
 
 void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  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 != TRUE)
+    {
+      taxisptr->vtime_lb = vtime_lb;
+      taxisptr->vtime_ub = vtime_ub;
+      taxisptr->has_bounds = TRUE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -6756,6 +6889,7 @@ int taxisInqRdate(int taxisID)
     {
       taxisptr->rdate = taxisptr->vdate;
       taxisptr->rtime = taxisptr->vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
   return (taxisptr->rdate);
@@ -6787,6 +6921,7 @@ int taxisInqRtime(int taxisID)
     {
       taxisptr->rdate = taxisptr->vdate;
       taxisptr->rtime = taxisptr->vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
   return (taxisptr->rtime);
@@ -6925,13 +7060,38 @@ int taxisInqNumavg(int taxisID)
 
 taxis_t *taxisPtr(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
   return (taxisptr);
 }
 
+void
+ptaxisDefName(taxis_t *taxisptr, const char *name)
+{
+  if (name)
+    {
+      taxis_check_ptr(__func__, taxisptr);
+      size_t len = strlen(name);
+      delete_refcount_string(taxisptr->name);
+      char *taxisname = taxisptr->name = new_refcount_string(len);
+      strcpy(taxisname, name);
+    }
+}
+
+void
+ptaxisDefLongname(taxis_t *taxisptr, const char *longname)
+{
+  if (longname)
+    {
+      taxis_check_ptr(__func__, taxisptr);
+      size_t len = strlen(longname);
+      delete_refcount_string(taxisptr->longname);
+      char *taxislongname = taxisptr->longname = new_refcount_string(len);
+      strcpy(taxislongname, longname);
+    }
+}
 
 void cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
 {
@@ -6993,8 +7153,9 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
     {
       *timevalue = days*86400. + secs;
     }
-  else if ( timeunit == TUNIT_MINUTE ||
-	    timeunit == TUNIT_QUARTER )
+  else if ( timeunit == TUNIT_MINUTE  ||
+	    timeunit == TUNIT_QUARTER ||
+	    timeunit == TUNIT_30MINUTES )
     {
       *timevalue = days*1440. + secs/60.;
     }
@@ -7251,8 +7412,12 @@ void splitTimevalue(double timevalue, int timeunit, int *date, int *time)
       vdate = cdiEncodeDate(year, month, day);
       vtime = cdiEncodeTime(hour, minute, second);
 
-      Warning("Reset wrong date/time to %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d!",
-	      year, month, day, hour, minute, second);
+      if ( lwarn )
+        {
+          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);
+        }
     }
 
   *date = vdate;
@@ -7399,6 +7564,13 @@ void ptaxisCopy(taxis_t *dest, taxis_t *source)
   dest->fc_unit     = source->fc_unit;
   dest->fc_period   = source->fc_period;
 
+  dest->climatology = source->climatology;
+  delete_refcount_string(dest->name);
+  delete_refcount_string(dest->longname);
+  dest->name = dup_refcount_string(source->name);
+  dest->longname = dup_refcount_string(source->longname);
+  if (dest->self != CDI_UNDEFID)
+    reshSetStatus(dest->self, &taxisOps, RESH_DESYNC_IN_USE);
   reshUnlock ();
 }
 
@@ -7496,9 +7668,9 @@ taxisGetPackSize(void *p, void *context)
     = serializeGetSize(taxisNint, DATATYPE_INT, context)
     + serializeGetSize(1, DATATYPE_UINT32, context)
     + (taxisptr->name ?
-       serializeGetSize(strlen(taxisptr->name), DATATYPE_TXT, context) : 0)
+       serializeGetSize((int)strlen(taxisptr->name), DATATYPE_TXT, context) : 0)
     + (taxisptr->longname ?
-       serializeGetSize(strlen(taxisptr->longname), DATATYPE_TXT,
+       serializeGetSize((int)strlen(taxisptr->longname), DATATYPE_TXT,
                         context) : 0);
   return packBufferSize;
 }
@@ -7547,8 +7719,8 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
 
   if (intBuffer[idx])
     {
-      size_t len = intBuffer[idx];
-      char *name = (char*) xmalloc(len + 1);
+      int len = intBuffer[idx];
+      char *name = new_refcount_string((size_t)len);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       name, len, DATATYPE_TXT, context);
       name[len] = '\0';
@@ -7557,8 +7729,8 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
   idx++;
   if (intBuffer[idx])
     {
-      size_t len = intBuffer[idx];
-      char *longname = (char*) xmalloc(len + 1);
+      int len = intBuffer[idx];
+      char *longname = new_refcount_string((size_t)len);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       longname, len, DATATYPE_TXT, context);
       longname[len] = '\0';
@@ -7817,9 +7989,9 @@ double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *d
 
   *secs = (int) sec_of_day;
 
-  seconds = *days*86400. + sec_of_day;
+  seconds = *days * 86400 + sec_of_day;
 
-  return (seconds);
+  return (double)seconds;
 }
 
 
@@ -7966,6 +8138,7 @@ int main(void)
   return (0);
 }
 #endif
+#include <limits.h>
 #include <stdio.h>
 
 
@@ -8078,17 +8251,17 @@ static int encode_day(int dpy, int year, int month, int day)
 {
   int i;
   int *dpm = NULL;
-  double rval;
-
-  rval = dpy * year + day;
+  long rval = (long)dpy * year + day;
 
   if      ( dpy == 360 ) dpm = month_360;
   else if ( dpy == 365 ) dpm = month_365;
   else if ( dpy == 366 ) dpm = month_366;
-  
+
   if ( dpm ) for ( i = 0; i < month-1; i++ ) rval += dpm[i];
+  if (rval > INT_MAX || rval < INT_MIN)
+    Error("Unhandled date: %ld", rval);
 
-  return (rval);
+  return (int)rval;
 }
 
 
@@ -8304,6 +8477,8 @@ int main(void)
 #if defined (HAVE_CONFIG_H)
 #endif
 
+#include <limits.h>
+
 
 #undef  UNDEFID
 #define UNDEFID -1
@@ -8328,7 +8503,7 @@ static int  MODEL_Debug = 0;   /* If set to 1, debugging */
 static void modelInit(void);
 
 
-static int    modelCompareP ( void * modelptr1, void * modelptr2 );
+static int modelCompareP(void *modelptr1, void *modelptr2);
 static void   modelDestroyP ( void * modelptr );
 static void   modelPrintP   ( void * modelptr, FILE * fp );
 static int    modelGetSizeP ( void * modelptr, void *context);
@@ -8408,8 +8583,9 @@ void modelDefaultEntries ( void )
   instID  = institutInq(  0,   1, "NCEP", NULL);
   resH[9] = modelDef(instID,  80, "T62L28MRF");
 
+  /* pre-defined models are not synchronized */
   for ( i = 0; i < nDefModels ; i++ )
-    reshSetStatus(resH[i], &modelOps, RESH_PRE_ASSIGNED);
+    reshSetStatus(resH[i], &modelOps, RESH_IN_USE);
 }
 
 static
@@ -8542,9 +8718,15 @@ char *modelInqNamePtr(int modelID)
 }
 
 
-int  modelCompareP ( void * modelptr1, void * modelptr2 )
+static int
+modelCompareP(void *modelptr1, void *modelptr2)
 {
-  return 0;
+  model_t *model1 = modelptr1, *model2 = modelptr2;
+  int diff = (namespaceResHDecode(model1->instID).idx
+              != namespaceResHDecode(model2->instID).idx)
+    | (model1->modelgribID != model2->modelgribID)
+    | (strcmp(model1->name, model2->name) != 0);
+  return diff;
 }
 
 
@@ -8587,10 +8769,11 @@ enum {
 
 static int modelGetSizeP(void * modelptr, void *context)
 {
-  model_t *p = (model_t*) modelptr;
-  int txsize = serializeGetSize(model_nints, DATATYPE_INT, context)
-    + serializeGetSize(p->name?strlen(p->name) + 1:0, DATATYPE_TXT, context);
-  return txsize;
+  model_t *p = (model_t*)modelptr;
+  size_t txsize = (size_t)serializeGetSize(model_nints, DATATYPE_INT, context)
+    + (size_t)serializeGetSize(p->name?(int)strlen(p->name) + 1:0, DATATYPE_TXT, context);
+  xassert(txsize <= INT_MAX);
+  return (int)txsize;
 }
 
 
@@ -8616,8 +8799,9 @@ modelUnpack(void *buf, int size, int *position, int originNamespace, void *conte
   serializeUnpack(buf, size, position, tempbuf, model_nints, DATATYPE_INT, context);
   if (tempbuf[3] != 0)
     {
-      name = (char*) xmalloc(tempbuf[3]);
-      serializeUnpack(buf, size, position, name, tempbuf[3], DATATYPE_TXT, context);
+      name = (char *)xmalloc((size_t)tempbuf[3]);
+      serializeUnpack(buf, size, position,
+                      name, tempbuf[3], DATATYPE_TXT, context);
     }
   else
     {
@@ -8646,6 +8830,9 @@ modelUnpack(void *buf, int size, int *position, int originNamespace, void *conte
 #if defined (HAVE_CONFIG_H)
 #endif
 
+#include <assert.h>
+#include <limits.h>
+
 
 #undef  UNDEFID
 #define UNDEFID  -1
@@ -8696,26 +8883,27 @@ void instituteDefaultValue ( institute_t * instituteptr )
 
 void instituteDefaultEntries ( void )
 {
-  cdiResH resH[64];
-  int i, n=0;
-
-  resH[n++]  = ECMWF   = institutDef( 98,   0, "ECMWF",     "European Centre for Medium-Range Weather Forecasts");
-  resH[n++]  = MPIMET  = institutDef( 98, 232, "MPIMET",    "Max-Planck-Institute for Meteorology");
-  resH[n++]  =           institutDef( 98, 255, "MPIMET",    "Max-Planck-Institute for Meteorology");
-  resH[n++]  =           institutDef( 98, 232, "MPIMET",    "Max-Planck Institute for Meteorology");
-  resH[n++]  =           institutDef( 78,   0, "DWD",       "Deutscher Wetterdienst");
-  resH[n++]  =           institutDef( 78, 255, "DWD",       "Deutscher Wetterdienst");
-  resH[n++]  = MCH     = institutDef(215, 255, "MCH",       "MeteoSwiss");
-  resH[n++]  =           institutDef(  7,   0, "NCEP",      "National Centers for Environmental Prediction");
-  resH[n++]  =           institutDef(  7,   1, "NCEP",      "National Centers for Environmental Prediction");
-  resH[n++]  =           institutDef( 60,   0, "NCAR",      "National Center for Atmospheric Research");
-  resH[n++]  =           institutDef( 74,   0, "METOFFICE", "U.K. Met Office");
-  resH[n++]  =           institutDef( 97,   0, "ESA",       "European Space Agency");
-  resH[n++]  =           institutDef( 99,   0, "KNMI",      "Royal Netherlands Meteorological Institute");
+  cdiResH resH[]
+    = { ECMWF   = institutDef( 98,   0, "ECMWF",     "European Centre for Medium-Range Weather Forecasts"),
+        MPIMET  = institutDef( 98, 232, "MPIMET",    "Max-Planck-Institute for Meteorology"),
+        institutDef( 98, 255, "MPIMET",    "Max-Planck-Institute for Meteorology"),
+        institutDef( 98, 232, "MPIMET",    "Max-Planck Institute for Meteorology"),
+        institutDef( 78,   0, "DWD",       "Deutscher Wetterdienst"),
+        institutDef( 78, 255, "DWD",       "Deutscher Wetterdienst"),
+        MCH     = institutDef(215, 255, "MCH",       "MeteoSwiss"),
+        institutDef(  7,   0, "NCEP",      "National Centers for Environmental Prediction"),
+        institutDef(  7,   1, "NCEP",      "National Centers for Environmental Prediction"),
+        institutDef( 60,   0, "NCAR",      "National Center for Atmospheric Research"),
+        institutDef( 74,   0, "METOFFICE", "U.K. Met Office"),
+        institutDef( 97,   0, "ESA",       "European Space Agency"),
+        institutDef( 99,   0, "KNMI",      "Royal Netherlands Meteorological Institute"),
+  };
   /*     (void) institutDef(  0,   0, "IPSL", "IPSL (Institut Pierre Simon Laplace, Paris, France)"); */
 
-  for ( i = 0; i < n ; i++ )
-    reshSetStatus(resH[i], &instituteOps, RESH_PRE_ASSIGNED);
+  size_t n = sizeof(resH)/sizeof(*resH);
+
+  for (size_t i = 0; i < n ; i++ )
+    reshSetStatus(resH[i], &instituteOps, RESH_IN_USE);
 }
 
 
@@ -8939,10 +9127,13 @@ enum {
 
 static int instituteGetPackSize(institute_t *ip, void *context)
 {
-  int txsize = serializeGetSize(institute_nints, DATATYPE_INT, context)
-    + serializeGetSize(strlen(ip->name) + 1, DATATYPE_TXT, context)
-    + serializeGetSize(strlen(ip->longname) + 1, DATATYPE_TXT, context);
-  return txsize;
+  size_t namelen = strlen(ip->name), longnamelen = strlen(ip->longname);
+  xassert(namelen < INT_MAX && longnamelen < INT_MAX);
+  size_t txsize = (size_t)serializeGetSize(institute_nints, DATATYPE_INT, context)
+    + (size_t)serializeGetSize((int)namelen + 1, DATATYPE_TXT, context)
+    + (size_t)serializeGetSize((int)longnamelen + 1, DATATYPE_TXT, context);
+  xassert(txsize <= INT_MAX);
+  return (int)txsize;
 }
 
 static void institutePackP(void * instituteptr, void *buf, int size, int *position, void *context)
@@ -8966,7 +9157,7 @@ int instituteUnpack(void *buf, int size, int *position, int originNamespace,
   int instituteID;
   char *name, *longname;
   serializeUnpack(buf, size, position, tempbuf, institute_nints, DATATYPE_INT, context);
-  name = (char *)xmalloc(tempbuf[3] + tempbuf[4]);
+  name = (char *)xmalloc((size_t)tempbuf[3] + (size_t)tempbuf[4]);
   longname = name + tempbuf[3];
   serializeUnpack(buf, size, position, name, tempbuf[3], DATATYPE_TXT, context);
   serializeUnpack(buf, size, position, longname, tempbuf[4], DATATYPE_TXT, context);
@@ -8992,6 +9183,8 @@ int instituteUnpack(void *buf, int size, int *position, int originNamespace,
 #endif
 
 #include <ctype.h>
+#include <stddef.h>
+#include <string.h>
 
 
 #undef  UNDEFID
@@ -9006,13 +9199,13 @@ int instituteUnpack(void *buf, int size, int *position, int originNamespace,
 
 typedef struct
 {
-  int    used;  
+  int    used;
   PAR   *pars;
   int    npars;
   int    modelID;
   int    number;
   char  *name;
-} 
+}
 PARTAB;
 
 static PARTAB parTable[MAX_TABLE];
@@ -9022,8 +9215,8 @@ static int  ParTableInit = 0;
 
 static char *tablePath = NULL;
 
-void tableDefModelID(int tableID, int modelID);
-void tableDefNum(int tableID, int tablenum);
+static void tableDefModelID(int tableID, int modelID);
+static void tableDefNum(int tableID, int tablenum);
 
 
 void tableDefEntry(int tableID, int id, const char *name,
@@ -9031,30 +9224,40 @@ void tableDefEntry(int tableID, int id, const char *name,
 {
   int item;
 
+  if ( tableID >= 0 && tableID < MAX_TABLE && parTable[tableID].used) { } else
+    Error("Invalid table ID %d", tableID);
   item = parTable[tableID].npars++;
   parTable[tableID].pars[item].id       = id;
+  parTable[tableID].pars[item].dupflags = 0;
   parTable[tableID].pars[item].name     = NULL;
   parTable[tableID].pars[item].longname = NULL;
   parTable[tableID].pars[item].units    = NULL;
 
-  if ( name )
-    if ( strlen(name) > 0 )
+  if ( name && strlen(name) > 0 )
+    {
       parTable[tableID].pars[item].name     = strdupx(name);
-  if ( longname )
-    if ( strlen(longname) > 0 )
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_NAME;
+    }
+  if ( longname && strlen(longname) > 0 )
+    {
       parTable[tableID].pars[item].longname = strdupx(longname);
-  if ( units )
-    if ( strlen(units) > 0 )
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_LONGNAME;
+    }
+  if ( units && strlen(units) > 0 )
+    {
       parTable[tableID].pars[item].units    = strdupx(units);
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_UNITS;
+    }
 }
 
-void tableLink(int tableID, PAR *pars, int npars)
+static void tableLink(int tableID, const PAR *pars, int npars)
 {
   int item;
 
   for ( item = 0; item < npars; item++ )
     {
       parTable[tableID].pars[item].id       = pars[item].id;
+      parTable[tableID].pars[item].dupflags = 0;
       parTable[tableID].pars[item].name     = pars[item].name;
       parTable[tableID].pars[item].longname = pars[item].longname;
       parTable[tableID].pars[item].units    = pars[item].units;
@@ -9063,7 +9266,7 @@ void tableLink(int tableID, PAR *pars, int npars)
   parTable[tableID].npars = npars;
 }
 
-void parTableInitEntry(int tableID)
+static void parTableInitEntry(int tableID)
 {
   parTable[tableID].used    = 0;
   parTable[tableID].pars    = NULL;
@@ -9073,7 +9276,7 @@ void parTableInitEntry(int tableID)
   parTable[tableID].name    = NULL;
 }
 
-void tableGetPath(void)
+static void tableGetPath(void)
 {
   char *path;
 
@@ -9085,17 +9288,38 @@ void tableGetPath(void)
   */
 }
 
-void parTableInit(void)
+static void parTableFinalize(void)
+{
+  for (int tableID = 0; tableID < MAX_TABLE; ++tableID)
+    if (parTable[tableID].used)
+      {
+        int npars = parTable[tableID].npars;
+        for (int item = 0; item < npars; ++item)
+          {
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_NAME)
+              free((void *)parTable[tableID].pars[item].name);
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_LONGNAME)
+              free((void *)parTable[tableID].pars[item].longname);
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_UNITS)
+              free((void *)parTable[tableID].pars[item].units);
+          }
+        free(parTable[tableID].pars);
+        free(parTable[tableID].name);
+      }
+}
+
+static void parTableInit(void)
 {
   ParTableInit = 1;
 
+  atexit(parTableFinalize);
   if ( cdiPartabIntern )
     tableDefault();
 
   tableGetPath();
 }
 
-int tableNewEntry()
+static int tableNewEntry()
 {
   int tableID = 0;
   static int init = 0;
@@ -9124,21 +9348,18 @@ int tableNewEntry()
   return (tableID);
 }
 
-int decodeForm1(char *pline, char *name, char *longname, char *units)
+static int
+decodeForm1(char *pline, char *name, char *longname, char *units)
 {
-  /* Format 1 : code name add mult longname [units] */
-  double add, mult;
-  int level;
   char *pstart, *pend;
-  long len;
 
   /* FIXME: parse success isn't verified */
-  level = strtol(pline, &pline, 10);
+  /* long level =  */strtol(pline, &pline, 10);
   while ( isspace((int) *pline) ) pline++;
 
   pstart = pline;
   while ( ! (isspace((int) *pline) || *pline == 0) ) pline++;
-  len = pline - pstart;
+  size_t len = (size_t)(pline - pstart);
   if ( len > 0 )
     {
       memcpy(name, pstart, len);
@@ -9150,10 +9371,11 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
   len = strlen(pline);
   if ( len == 0 ) return (0);
 
+  /* Format 1 : code name add mult longname [units] */
   /* FIXME: successful parse isn't verified */
-  add  = strtod(pline, &pline);
+  /* double add  =  */strtod(pline, &pline);
   /* FIXME: successful parse isn't verified */
-  mult = strtod(pline, &pline);
+  /* double mult =  */strtod(pline, &pline);
 
   while ( isspace((int) *pline) ) pline++;
 
@@ -9167,7 +9389,7 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
       else
 	pend = pstart + len;
       while ( isspace((int) *pend) ) pend--;
-      len = pend - pstart + 1;
+      len = (size_t)(pend - pstart + 1);
       if ( len > 0 )
 	{
 	  memcpy(longname, pstart, len);
@@ -9182,7 +9404,7 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
 	  if ( ! pend ) return (0);
 	  pend--;
 	  while ( isspace((int) *pend) ) pend--;
-	  len = pend - pstart + 1;
+	  len = (size_t)(pend - pstart + 1);
 	  if ( len > 0 )
 	    {
 	      memcpy(units, pstart, len);
@@ -9194,40 +9416,46 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
   return (0);
 }
 
-int decodeForm2(char *pline, char *name, char *longname, char *units)
+static int
+decodeForm2(char *pline, char *name, char *longname, char *units)
 {
   /* Format 2 : code | name | longname | units */
   char *pend;
-  long len;
+  size_t len;
 
   pline = strchr(pline, '|');
   pline++;
 
   while ( isspace((int) *pline) ) pline++;
-  pend = strchr(pline, '|');
-  if ( ! pend )
+  if (*pline != '|')
     {
-      pend = pline;
-      while ( ! isspace((int) *pend) ) pend++;
-      len = pend - pline;
-      if ( len > 0 )
-	{
-	  memcpy(name, pline, len);
-	  name[len] = 0;
-	}
-      return (0);
+      pend = strchr(pline, '|');
+      if ( ! pend )
+        {
+          pend = pline;
+          while ( ! isspace((int) *pend) ) pend++;
+          len = (size_t)(pend - pline);
+          if ( len > 0 )
+            {
+              memcpy(name, pline, len);
+              name[len] = 0;
+            }
+          return (0);
+        }
+      else
+        {
+          pend--;
+          while ( isspace((int) *pend) ) pend--;
+          len = (size_t)(pend - pline + 1);
+          if ( len > 0 )
+            {
+              memcpy(name, pline, len);
+              name[len] = 0;
+            }
+        }
     }
   else
-    {
-      pend--;
-      while ( isspace((int) *pend) ) pend--;
-      len = pend - pline + 1;
-      if ( len > 0 )
-	{
-	  memcpy(name, pline, len);
-	  name[len] = 0;
-	}
-    }
+    name[0] = '\0';
 
   pline = strchr(pline, '|');
   pline++;
@@ -9236,7 +9464,7 @@ int decodeForm2(char *pline, char *name, char *longname, char *units)
   if ( !pend ) pend = strchr(pline, 0);
   pend--;
   while ( isspace((int) *pend) ) pend--;
-  len = pend - pline + 1;
+  len = (size_t)(pend - pline + 1);
   if ( len > 0 )
     {
       memcpy(longname, pline, len);
@@ -9252,9 +9480,9 @@ int decodeForm2(char *pline, char *name, char *longname, char *units)
       if ( !pend ) pend = strchr(pline, 0);
       pend--;
       while ( isspace((int) *pend) ) pend--;
-      len = pend - pline + 1;
+      ptrdiff_t len = pend - pline + 1;
       if ( len < 0 ) len = 0;
-      memcpy(units, pline, len);
+      memcpy(units, pline, (size_t)len);
       units[len] = 0;
     }
 
@@ -9265,7 +9493,6 @@ int tableRead(const char *tablefile)
 {
   char line[1024], *pline;
   int lnr = 0;
-  long len;
   int id;
   char name[256], longname[256], units[256];
   int tableID = UNDEFID;
@@ -9284,7 +9511,7 @@ int tableRead(const char *tablefile)
 
   while ( fgets(line, 1023, tablefp) )
     {
-      len = strlen(line);
+      size_t len = strlen(line);
       if ( line[len-1] == '\n' ) line[len-1] = '\0';
       lnr++;
       id       = CDI_UNDEFID;
@@ -9320,7 +9547,7 @@ int tableRead(const char *tablefile)
   return (tableID);
 }
 
-int tableFromEnv(int modelID, int tablenum)
+static int tableFromEnv(int modelID, int tablenum)
 {
   int tableID = UNDEFID;
   char tablename[256] = {'\0'};
@@ -9331,7 +9558,7 @@ int tableFromEnv(int modelID, int tablenum)
       strcpy(tablename, modelInqNamePtr(modelID));
       if ( tablenum )
 	{
-	  int len = strlen(tablename);
+	  size_t len = strlen(tablename);
 	  sprintf(tablename+len, "_%03d", tablenum);
 	}
       tablenamefound = 1;
@@ -9346,7 +9573,7 @@ int tableFromEnv(int modelID, int tablenum)
 	      strcpy(tablename, institutInqNamePtr(instID));
 	      if ( tablenum )
 		{
-		  int len = strlen(tablename);
+		  size_t len = strlen(tablename);
 		  sprintf(tablename+len, "_%03d", tablenum);
 		}
 	      tablenamefound = 1;
@@ -9356,7 +9583,7 @@ int tableFromEnv(int modelID, int tablenum)
 
   if ( tablenamefound )
     {
-      int lenp = 0, lenf;
+      size_t lenp = 0, lenf;
       char *tablefile = NULL;
       if ( tablePath )
 	lenp = strlen(tablePath);
@@ -9391,7 +9618,7 @@ int tableFromEnv(int modelID, int tablenum)
 int tableInq(int modelID, int tablenum, const char *tablename)
 {
   int tableID = UNDEFID;
-  int modelID2 = UNDEFID, i, len;
+  int modelID2 = UNDEFID;
   char tablefile[256] = {'\0'};
 
   if ( ! ParTableInit ) parTableInit();
@@ -9422,12 +9649,12 @@ int tableInq(int modelID, int tablenum, const char *tablename)
       for ( tableID = 0; tableID < MAX_TABLE; tableID++ )
 	{
 	  if ( parTable[tableID].used )
-	    {	  
+	    {
 	      if ( parTable[tableID].modelID == modelID &&
 		   parTable[tableID].number  == tablenum ) break;
 	    }
 	}
-  
+
       if ( tableID == MAX_TABLE ) tableID = UNDEFID;
 
       if ( tableID == UNDEFID )
@@ -9437,8 +9664,8 @@ int tableInq(int modelID, int tablenum, const char *tablename)
 	      if ( modelInqNamePtr(modelID) )
 		{
 		  strcpy(tablefile, modelInqNamePtr(modelID));
-		  len = strlen(tablefile);
-		  for ( i = 0; i < len; i++)
+		  size_t len = strlen(tablefile);
+		  for ( size_t i = 0; i < len; i++)
 		    if ( tablefile[i] == '.' ) tablefile[i] = '\0';
 		  modelID2 = modelInq(-1, 0, tablefile);
 		}
@@ -9482,7 +9709,7 @@ int tableDef(int modelID, int tablenum, const char *tablename)
 
       parTable[tableID].modelID = modelID;
       parTable[tableID].number  = tablenum;
-      if ( tablename ) 
+      if ( tablename )
 	parTable[tableID].name = strdupx(tablename);
 
       parTable[tableID].pars = (PAR *) malloc(MAX_PARS * sizeof(PAR));
@@ -9491,12 +9718,12 @@ int tableDef(int modelID, int tablenum, const char *tablename)
   return (tableID);
 }
 
-void tableDefModelID(int tableID, int modelID)
+static void tableDefModelID(int tableID, int modelID)
 {
   parTable[tableID].modelID = modelID;
 }
 
-void tableDefNum(int tableID, int tablenum)
+static void tableDefNum(int tableID, int tablenum)
 {
   parTable[tableID].number  = tablenum;
 }
@@ -9521,7 +9748,7 @@ int tableInqModel(int tableID)
   return (modelID);
 }
 
-void partabCheckID(int item)
+static void partabCheckID(int item)
 {
   if ( item < 0 || item >= parTableSize )
     Error("item %d undefined!", item);
@@ -9549,12 +9776,10 @@ char *tableInqNamePtr(int tableID)
 void tableWrite(const char *ptfile, int tableID)
 {
   int item, npars;
-  int lenname, lenlname, lenunits;
-  int maxname = 4, maxlname = 10, maxunits = 2;
+  size_t maxname = 4, maxlname = 10, maxunits = 2;
   FILE *ptfp;
   int tablenum, modelID, instID = CDI_UNDEFID;
   int center = 0, subcenter = 0;
-  char *name, *longname, *units;
   char *instnameptr = NULL, *modelnameptr = NULL;
 
   if ( CDI_Debug )
@@ -9576,19 +9801,19 @@ void tableWrite(const char *ptfile, int tableID)
     {
       if ( parTable[tableID].pars[item].name )
 	{
-	  lenname  = strlen(parTable[tableID].pars[item].name);
+	  size_t lenname = strlen(parTable[tableID].pars[item].name);
 	  if ( lenname  > maxname )  maxname  = lenname;
 	}
 
       if ( parTable[tableID].pars[item].longname )
 	{
-	  lenlname = strlen(parTable[tableID].pars[item].longname);
+	  size_t lenlname = strlen(parTable[tableID].pars[item].longname);
 	  if ( lenlname > maxlname ) maxlname = lenlname;
 	}
 
       if ( parTable[tableID].pars[item].units )
 	{
-	  lenunits = strlen(parTable[tableID].pars[item].units);
+	  size_t lenunits = strlen(parTable[tableID].pars[item].units);
 	  if ( lenunits > maxunits ) maxunits = lenunits;
 	}
     }
@@ -9630,23 +9855,23 @@ void tableWrite(const char *ptfile, int tableID)
   fprintf(ptfp, "# The format of each record is:\n");
   fprintf(ptfp, "#\n");
   fprintf(ptfp, "# id | %-*s | %-*s | %-*s\n",
-	  maxname,  "name",
-	  maxlname, "title",
-	  maxunits, "units");
+	  (int)maxname,  "name",
+	  (int)maxlname, "title",
+	  (int)maxunits, "units");
 	  
   for ( item = 0; item < npars; item++)
     {
-      name = parTable[tableID].pars[item].name;
-      longname = parTable[tableID].pars[item].longname;
-      units = parTable[tableID].pars[item].units;
+      const char *name = parTable[tableID].pars[item].name,
+        *longname = parTable[tableID].pars[item].longname,
+        *units = parTable[tableID].pars[item].units;
       if ( name == NULL ) name = " ";
       if ( longname == NULL ) longname = " ";
       if ( units == NULL ) units = " ";
       fprintf(ptfp, "%4d | %-*s | %-*s | %-*s\n",
 	      parTable[tableID].pars[item].id,
-	      maxname, name,
-	      maxlname, longname,
-	      maxunits, units);
+	      (int)maxname, name,
+	      (int)maxlname, longname,
+	      (int)maxunits, units);
     }
 
   fclose(ptfp);
@@ -9655,16 +9880,22 @@ void tableWrite(const char *ptfile, int tableID)
 
 void tableWriteC(const char *filename, int tableID)
 {
-  char chelp[] = "";
+  FILE *ptfp = fopen(filename, "w");
+  if (!ptfp)
+    Error("failed to open file \"%s\"!", filename);
+  if ( CDI_Debug )
+    Message("write parameter table %d to %s", tableID, filename);
+  tableFWriteC(ptfp, tableID);
+  fclose(ptfp);
+}
+
+void tableFWriteC(FILE *ptfp, int tableID)
+{
+  const char chelp[] = "";
   int item, npars;
-  int lenname, lenlname, lenunits;
-  int maxname = 0, maxlname = 0, maxunits = 0;
+  size_t maxname = 0, maxlname = 0, maxunits = 0;
   char tablename[256];
-  int len, i;
-  FILE *ptfp;
 
-  if ( CDI_Debug )
-    Message("write parameter table %d to %s", tableID, filename);
 
   if ( tableID == UNDEFID )
     {
@@ -9674,73 +9905,59 @@ void tableWriteC(const char *filename, int tableID)
 
   partabCheckID(tableID);
 
-  ptfp = fopen(filename, "w");
-
   npars = parTable[tableID].npars;
 
   for ( item = 0; item < npars; item++)
     {
       if ( parTable[tableID].pars[item].name )
 	{
-	  lenname  = strlen(parTable[tableID].pars[item].name);
+	  size_t lenname = strlen(parTable[tableID].pars[item].name);
 	  if ( lenname  > maxname )  maxname  = lenname;
 	}
 
       if ( parTable[tableID].pars[item].longname )
 	{
-	  lenlname = strlen(parTable[tableID].pars[item].longname);
+	  size_t lenlname = strlen(parTable[tableID].pars[item].longname);
 	  if ( lenlname > maxlname ) maxlname = lenlname;
 	}
 
       if ( parTable[tableID].pars[item].units )
 	{
-	  lenunits = strlen(parTable[tableID].pars[item].units);
+	  size_t lenunits = strlen(parTable[tableID].pars[item].units);
 	  if ( lenunits > maxunits ) maxunits = lenunits;
 	}
     }
 
-  strcpy(tablename, parTable[tableID].name);
-  len = strlen(tablename);
-
-  for ( i = 0; i < len; i++ )
-    if ( tablename[i] == '.' ) tablename[i] = '_';
+  strncpy(tablename, parTable[tableID].name, sizeof (tablename));
+  tablename[sizeof (tablename) - 1] = '\0';
+  {
+    size_t len = strlen(tablename);
+    for (size_t i = 0; i < len; i++ )
+      if ( tablename[i] == '.' ) tablename[i] = '_';
+  }
+  fprintf(ptfp, "static const PAR %s[] = {\n", tablename);
 
-  fprintf(ptfp, "static PAR %s[] = {\n", tablename);
-	  
   for ( item = 0; item < npars; item++ )
     {
-      len = strlen(parTable[tableID].pars[item].name);
-      fprintf(ptfp, "  {%4d, \"%s\", %-*s",
+      size_t len = strlen(parTable[tableID].pars[item].name),
+        llen = parTable[tableID].pars[item].longname
+        ? strlen(parTable[tableID].pars[item].longname) : 0,
+        ulen = parTable[tableID].pars[item].units
+        ? strlen(parTable[tableID].pars[item].units) : 0;
+      fprintf(ptfp, "  {%4d, 0, \"%s\", %-*s%c%s%s, %-*s%c%s%s %-*s},\n",
 	      parTable[tableID].pars[item].id,
-	      parTable[tableID].pars[item].name, maxname-len, chelp);
-
-      if ( parTable[tableID].pars[item].longname )
-	len = strlen(parTable[tableID].pars[item].longname);
-      else
-	len = 0;
-
-      if ( len == 0 )
-	fprintf(ptfp, " NULL, %-*s", maxlname-3, chelp);
-      else
-	fprintf(ptfp, "\"%s\", %-*s",
-		parTable[tableID].pars[item].longname, maxlname-len, chelp);
-
-      if ( parTable[tableID].pars[item].units )
-	len = strlen(parTable[tableID].pars[item].units);
-      else
-	len = 0;
-
-      if ( len == 0 )
-	fprintf(ptfp, " NULL %-*s},\n", maxunits-3, chelp);
-      else
-	fprintf(ptfp, "\"%s\" %-*s},\n",
-		parTable[tableID].pars[item].units,
-		maxunits-len, chelp);
+	      parTable[tableID].pars[item].name, (int)(maxname-len), chelp,
+              llen?'"':' ',
+              llen?parTable[tableID].pars[item].longname:"NULL",
+              llen?"\"":"",
+              (int)(maxlname-(llen?llen:3)), chelp,
+              ulen?'"':' ',
+              ulen?parTable[tableID].pars[item].units:"NULL",
+              ulen?"\"":"",
+              (int)(maxunits-(ulen?ulen:3)), chelp);
     }
 
   fprintf(ptfp, "};\n\n");
-
-  fclose(ptfp);
 }
 
 
@@ -9802,9 +10019,9 @@ int tableInqParName(int tableID, int code, char *varname)
 }
 
 
-char *tableInqParNamePtr(int tableID, int code)
+const char *tableInqParNamePtr(int tableID, int code)
 {
-  char *name = NULL;
+  const char *name = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -9824,9 +10041,9 @@ char *tableInqParNamePtr(int tableID, int code)
 }
 
 
-char *tableInqParLongnamePtr(int tableID, int code)
+const char *tableInqParLongnamePtr(int tableID, int code)
 {
-  char *longname = NULL;
+  const char *longname = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -9846,9 +10063,9 @@ char *tableInqParLongnamePtr(int tableID, int code)
 }
 
 
-char *tableInqParUnitsPtr(int tableID, int code)
+const char *tableInqParUnitsPtr(int tableID, int code)
 {
-  char *units = NULL;
+  const char *units = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -9875,6 +10092,9 @@ int tableInqParLongname(int tableID, int code, char *longname)
 
   npars = parTable[tableID].npars;
 
+  if ( ((tableID >= 0) & (tableID < MAX_TABLE)) | (tableID == UNDEFID) ) { } else
+    Error("Invalid table ID %d", tableID);
+
   if ( tableID == UNDEFID )
     {
       err = 1;
@@ -9904,6 +10124,9 @@ int tableInqParUnits(int tableID, int code, char *units)
 
   npars = parTable[tableID].npars;
 
+  if ( ((tableID >= 0) & (tableID < MAX_TABLE)) | (tableID == UNDEFID) ) { } else
+    Error("Invalid table ID %d", tableID);
+
   if ( tableID == UNDEFID )
     {
       err = 1;
@@ -9947,23 +10170,6 @@ void tableInqPar(int tableID, int code, char *name, char *longname, char *units)
     }
 }
 
-
-int parInqID(int tableID, int code)
-{
-  int item, npars;
-
-  npars = parTable[tableID].npars;
-
-  for ( item = 0; item < npars; item++ )
-    {
-      if ( parTable[tableID].pars[item].id == code ) break;
-    }
-
-  if ( item == npars ) item = -1;
-
-  return (item);
-}
-
 int tableInqNumber(void)
 {
   if ( ! ParTableInit ) parTableInit();
@@ -10099,7 +10305,7 @@ void str2uuid(const char *uuidstr, char *uuid)
 
 
 static
-void cpledn(int kn, int 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;
@@ -10108,7 +10314,7 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
   double zdlmod;
   double zdlxn;
 
-  int ik, jn;
+  size_t ik, jn;
 
   /* 1.0 Newton iteration step */
 
@@ -10125,7 +10331,7 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
 
   if (kflag == 0) 
     {
-      for(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);
@@ -10157,9 +10363,8 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
 }
 
 static
-void gawl(double *pfn, double *pl, double *pw, int kn)
+void gawl(double *pfn, double *pl, double *pw, size_t kn)
 {
-  int iodd;
   double pmod = 0;
   int iflag;
   int itemax;
@@ -10172,7 +10377,7 @@ void gawl(double *pfn, double *pl, double *pw, int kn)
   iflag  =  0;
   itemax = 20;
 
-  iodd   = (kn % 2);
+  size_t iodd   = (kn % 2);
 
   zdlx   =  *pl;
 
@@ -10193,7 +10398,7 @@ void gawl(double *pfn, double *pl, double *pw, int kn)
 }
 
 static
-void gauaw(int 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
@@ -10205,24 +10410,22 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   double z, zfnn;
 
-  int ik, ins2, isym, jgl, jglm1, jn, iodd;
-
-  zfn    = (double *) malloc((kn+1)*(kn+1)*sizeof(double));
-  zfnlat = (double *) malloc((kn/2+1+1)*sizeof(double));  
+  zfn    = (double *) malloc((kn+1) * (kn+1) * sizeof(double));
+  zfnlat = (double *) malloc((kn/2+1+1)*sizeof(double));
 
   zfn[0] = M_SQRT2;
-  for (jn = 1; jn <= kn; jn++)
+  for (size_t jn = 1; jn <= kn; jn++)
     {
       zfnn = zfn[0];
-      for (jgl = 1; jgl <= jn; jgl++)
+      for (size_t jgl = 1; jgl <= jn; jgl++)
 	{
 	  zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl))); 
 	}
 
       zfn[jn*(kn+1)+jn] = zfnn;
 
-      iodd = jn % 2;
-      for (jgl = 2; jgl <= jn-iodd; jgl += 2) 
+      size_t iodd = jn % 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)));
@@ -10232,9 +10435,9 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   /* 2.0 Gaussian latitudes and weights */
 
-  iodd = kn % 2;
-  ik = iodd;
-  for (jgl = iodd; jgl <= kn; jgl += 2)
+  size_t iodd = kn % 2;
+  size_t ik = iodd;
+  for (size_t jgl = iodd; jgl <= kn; jgl += 2)
     {
       zfnlat[ik] = zfn[kn*(kn+1)+jgl];
       ik++;
@@ -10245,9 +10448,9 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
    *     Legendre polynomial of degree kn.
    */
 
-  ins2 = kn/2+(kn % 2);
+  size_t ins2 = kn/2+(kn % 2);
 
-  for (jgl = 1; jgl <= ins2; jgl++) 
+  for (size_t jgl = 1; jgl <= ins2; jgl++) 
     {
       z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2)); 
       pl[jgl-1] = z+1.0/(tan(z)*((double)(8*kn*kn)));
@@ -10255,23 +10458,23 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   /* 2.2 Computes roots and weights for transformed theta */
 
-  for (jgl = ins2; jgl >= 1 ; jgl--) 
+  for (size_t jgl = ins2; jgl >= 1 ; jgl--) 
     {
-      jglm1 = jgl-1;
+      size_t jglm1 = jgl-1;
       gawl(zfnlat, &(pl[jglm1]), &(pw[jglm1]), kn);
     }
 
   /* convert to physical latitude */
 
-  for (jgl = 0; jgl < ins2; jgl++) 
+  for (size_t jgl = 0; jgl < ins2; jgl++) 
     {
       pl[jgl] = cos(pl[jgl]);
     }
 
-  for (jgl = 1; jgl <= kn/2; jgl++) 
+  for (size_t jgl = 1; jgl <= kn/2; jgl++) 
     {
-      jglm1 = jgl-1;
-      isym =  kn-jgl;
+      size_t jglm1 = jgl-1;
+      size_t isym =  kn-jgl;
       pl[isym] =  -pl[jglm1];
       pw[isym] =  pw[jglm1];
     }
@@ -10375,7 +10578,7 @@ void gauaw_old(double *pa, double *pw, int nlat)
 }
 #endif
 
-void gaussaw(double *restrict pa, double *restrict pw, int nlat)
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat)
 {
   //gauaw_old(pa, pw, nlat);
   gauaw(nlat, pa, pw);
@@ -10425,7 +10628,8 @@ int main (int rgc, char *argv[])
 
 
 
-extern void zaxisGetIndexList ( int, int * );
+extern void zaxisGetIndexList(int, int *);
+extern void zaxisDefLtype2(int zaxisID, int ltype2);
 
 
 #undef  UNDEFID
@@ -10456,7 +10660,8 @@ typedef struct
   int           timaccu;
   int           gridID;
   int           zaxistype;
-  int           ltype;     /* GRIB level type */
+  int           ltype1;     /* GRIB first level type */
+  int           ltype2;     /* GRIB second level type */
   int           lbounds;
   int           level_sf;
   int           level_unit;
@@ -10477,6 +10682,7 @@ typedef struct
   char         *units;
   ensinfo_t    *ensdata;
   int           typeOfGeneratingProcess;
+  int           productDefinitionTemplate;
 #if  defined  (HAVE_LIBGRIB_API)
   /* (Optional) list of keyword/double value pairs */
   int           opt_grib_dbl_nentries;
@@ -10491,10 +10697,9 @@ typedef struct
 vartable_t;
 
 
-int vartableInit = 0;
-vartable_t *vartable;
+static vartable_t *vartable;
 static int varTablesize = 0;
-int nvars = 0;
+static int nvars = 0;
 
 
 static
@@ -10507,7 +10712,8 @@ void paramInitEntry(int varID, int param)
   vartable[varID].timaccu        = 0;
   vartable[varID].gridID         = UNDEFID;
   vartable[varID].zaxistype      = 0;
-  vartable[varID].ltype          = 0;
+  vartable[varID].ltype1         = 0;
+  vartable[varID].ltype2         = -1;
   vartable[varID].lbounds        = 0;
   vartable[varID].level_sf       = 0;
   vartable[varID].level_unit     = 0;
@@ -10517,7 +10723,8 @@ void paramInitEntry(int varID, int param)
   vartable[varID].instID         = UNDEFID;
   vartable[varID].modelID        = UNDEFID;
   vartable[varID].tableID        = UNDEFID;
-  vartable[varID].typeOfGeneratingProcess  = UNDEFID;
+  vartable[varID].typeOfGeneratingProcess   = UNDEFID;
+  vartable[varID].productDefinitionTemplate = UNDEFID;
   vartable[varID].comptype       = COMPRESS_NONE;
   vartable[varID].complevel      = 1;
   vartable[varID].lmissval       = 0;
@@ -10530,15 +10737,16 @@ void paramInitEntry(int varID, int param)
 }
 
 static
-int varGetEntry(int param, int zaxistype, int ltype, const char *name)
+int varGetEntry(int param, int zaxistype, int ltype1, int tsteptype, const char *name)
 {
   int varID;
 
   for ( varID = 0; varID < varTablesize; varID++ )
     {
-      if ( vartable[varID].param     == param     &&
-	   vartable[varID].zaxistype == zaxistype &&
-	   vartable[varID].ltype     == ltype )
+      if ( vartable[varID].param      == param       &&
+	   vartable[varID].zaxistype  == zaxistype   &&
+	   vartable[varID].ltype1     == ltype1      &&
+	   vartable[varID].tsteptype  == tsteptype )
         {
           if ( name && name[0] && vartable[varID].name && vartable[varID].name[0] )
             {
@@ -10604,7 +10812,8 @@ int levelNewEntry(int varID, int level1, int level2)
       int i;
 
       levelTableSize = 2;
-      levelTable = (leveltable_t *) malloc(levelTableSize*sizeof(leveltable_t));
+      levelTable = (leveltable_t *)xmalloc((size_t)levelTableSize
+                                           * sizeof (leveltable_t));
       if( levelTable == NULL )
 	{
           Message("levelTableSize = %d", levelTableSize);
@@ -10630,7 +10839,8 @@ int levelNewEntry(int varID, int level1, int level2)
       int i;
 
       levelTableSize = 2*levelTableSize;
-      levelTable = (leveltable_t *) realloc(levelTable, levelTableSize*sizeof(leveltable_t));
+      levelTable = (leveltable_t *)xrealloc(levelTable, (size_t)levelTableSize
+                                            * sizeof (leveltable_t));
       if( levelTable == NULL )
 	{
           Message("levelTableSize = %d", levelTableSize);
@@ -10669,7 +10879,8 @@ int paramNewEntry(int param)
       int i;
 
       varTablesize = 2;
-      vartable = (vartable_t *) malloc(varTablesize*sizeof(vartable_t));
+      vartable = (vartable_t *)xmalloc((size_t)varTablesize
+                                       * sizeof (vartable_t));
       if( vartable == NULL )
 	{
           Message("varTablesize = %d", varTablesize);
@@ -10700,8 +10911,9 @@ int paramNewEntry(int param)
     {
       int i;
 
-      varTablesize = 2*varTablesize;
-      vartable = (vartable_t *) realloc(vartable, varTablesize*sizeof(vartable_t));
+      varTablesize = 2 * varTablesize;
+      vartable = (vartable_t *)xrealloc(vartable, (size_t)varTablesize
+                                        * sizeof (vartable_t));
       if( vartable == NULL )
 	{
           Message("varTablesize = %d", varTablesize);
@@ -10727,26 +10939,27 @@ int paramNewEntry(int param)
 
 void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
 		  int level1, int level2, int level_sf, int level_unit, int prec,
-		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype,
+		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
 		  const char *name, const char *stdname, const char *longname, const char *units)
 {
   int varID = UNDEFID;
   int levelID = -1;
 
   if ( ! (cdiSplitLtype105 == 1 && zaxistype == ZAXIS_HEIGHT) )
-    varID = varGetEntry(param, zaxistype, ltype, name);
+    varID = varGetEntry(param, zaxistype, ltype1, tsteptype, name);
 
   if ( varID == UNDEFID )
     {
       nvars++;
       varID = paramNewEntry(param);
-      vartable[varID].gridID    = gridID;
-      vartable[varID].zaxistype = zaxistype;
-      vartable[varID].ltype     = ltype;
-      vartable[varID].lbounds   = lbounds;
-      vartable[varID].level_sf  = level_sf;
+      vartable[varID].gridID     = gridID;
+      vartable[varID].zaxistype  = zaxistype;
+      vartable[varID].ltype1     = ltype1;
+      vartable[varID].ltype2     = ltype2;
+      vartable[varID].lbounds    = lbounds;
+      vartable[varID].level_sf   = level_sf;
       vartable[varID].level_unit = level_unit;
-      if ( tsteptype != UNDEFID ) vartable[varID].tsteptype = tsteptype;
+      vartable[varID].tsteptype  = tsteptype;
       if ( numavg ) vartable[varID].timave = 1;
 
       if ( name )     if ( name[0] )     vartable[varID].name     = strdup(name);
@@ -10762,12 +10975,12 @@ void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
       if ( vartable[varID].gridID != gridID )
 	{
 	  Message("param = %s gridID = %d", paramstr, gridID);
-	  Error("horizontal grid must not change for same param!");
+	  Error("horizontal grid must not change for same parameter!");
 	}
       if ( vartable[varID].zaxistype != zaxistype )
 	{
 	  Message("param = %s zaxistype = %d", paramstr, zaxistype);
-	  Error("zaxistype must not change for same param!");
+	  Error("zaxistype must not change for same parameter!");
 	}
     }
 
@@ -10848,7 +11061,7 @@ void cdi_generate_vars(stream_t *streamptr)
 {
   int varID, gridID, zaxisID, levelID;
   int instID, modelID, tableID;
-  int param, nlevels, zaxistype, lindex, ltype;
+  int param, nlevels, zaxistype, ltype1, ltype2, lindex;
   int prec;
   int tsteptype;
   int timave, timaccu;
@@ -10858,32 +11071,29 @@ void cdi_generate_vars(stream_t *streamptr)
   double *dlevels = NULL;
   double *dlevels1 = NULL;
   double *dlevels2 = NULL;
-  int vlistID;
-  int *varids, index, varid;
+  int index, varid;
   double level_sf = 1;
+  int vlistID = streamptr->vlistID;
 
-  vlistID =  streamptr->vlistID;
-
-  varids = (int *) malloc(nvars*sizeof(int));
+  int *varids = (int *)xmalloc((size_t)nvars*sizeof(int));
   for ( varID = 0; varID < nvars; varID++ ) varids[varID] = varID;
 
   if ( streamptr->sortname )
     {
-      int index;
       param_t **varInfo;
-      varInfo    = (param_t **) malloc(nvars*sizeof(param_t *));
-      varInfo[0] = (param_t *)  malloc(nvars*sizeof(param_t));
+      varInfo    = (param_t **)xmalloc((size_t)nvars * sizeof (param_t *));
+      varInfo[0] = (param_t *)xmalloc((size_t)nvars * sizeof (param_t));
 
-      for ( index = 1; index < nvars; index++ )
+      for ( int index = 1; index < nvars; index++ )
 	varInfo[index] = varInfo[0] + index;
 
       for ( varid = 0; varid < nvars; varid++ )
 	{
 	  varInfo[varid]->varid = varids[varid];
 	  varInfo[varid]->param = vartable[varid].param;
-	  varInfo[varid]->ltype = vartable[varid].ltype;
+	  varInfo[varid]->ltype = vartable[varid].ltype1;
 	}
-      qsort(varInfo[0], nvars, sizeof(param_t), cmpparam);
+      qsort(varInfo[0], (size_t)nvars, sizeof(param_t), cmpparam);
       for ( varid = 0; varid < nvars; varid++ )
 	{
 	  varids[varid] = varInfo[varid]->varid;
@@ -10894,32 +11104,33 @@ void cdi_generate_vars(stream_t *streamptr)
 
   for ( index = 0; index < nvars; index++ )
     {
-      varid     = varids[index];
+      varid      = varids[index];
 
-      gridID    = vartable[varid].gridID;
-      param     = vartable[varid].param;
-      nlevels   = vartable[varid].nlevels;
-      ltype     = vartable[varid].ltype;
+      gridID     = vartable[varid].gridID;
+      param      = vartable[varid].param;
+      nlevels    = vartable[varid].nlevels;
+      ltype1     = vartable[varid].ltype1;
+      ltype2     = vartable[varid].ltype2;
       zaxistype = vartable[varid].zaxistype;
-      if ( ltype == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
+      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
 	zaxistype = cdiDefaultLeveltype;
-      lbounds   = vartable[varid].lbounds;
-      prec      = vartable[varid].prec;
-      instID    = vartable[varid].instID;
-      modelID   = vartable[varid].modelID;
-      tableID   = vartable[varid].tableID;
-      tsteptype = vartable[varid].tsteptype;
-      timave    = vartable[varid].timave;
-      timaccu   = vartable[varid].timaccu;
-      comptype  = vartable[varid].comptype;
+      lbounds    = vartable[varid].lbounds;
+      prec       = vartable[varid].prec;
+      instID     = vartable[varid].instID;
+      modelID    = vartable[varid].modelID;
+      tableID    = vartable[varid].tableID;
+      tsteptype  = vartable[varid].tsteptype;
+      timave     = vartable[varid].timave;
+      timaccu    = vartable[varid].timaccu;
+      comptype   = vartable[varid].comptype;
 
       level_sf  = 1;
       if ( vartable[varid].level_sf != 0 ) level_sf = 1./vartable[varid].level_sf;
 
       zaxisID = UNDEFID;
 
-      if ( ltype == 0 && zaxistype == ZAXIS_GENERIC && nlevels == 1 &&
-	   ! (fabs(vartable[varid].levelTable[0].level1)>0) )
+      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && nlevels == 1 &&
+	   vartable[varid].levelTable[0].level1 == 0 )
 	zaxistype = ZAXIS_SURFACE;
 
       dlevels = (double *) malloc(nlevels*sizeof(double));
@@ -10989,7 +11200,12 @@ void cdi_generate_vars(stream_t *streamptr)
 
       char *unitptr = cdiUnitNamePtr(vartable[varid].level_unit);
       zaxisID = varDefZaxis(vlistID, zaxistype, nlevels, dlevels, lbounds, dlevels1, dlevels2,
-                            Vctsize, Vct, NULL, NULL, unitptr, 0, 0, ltype);
+                            (int)Vctsize, Vct, NULL, NULL, unitptr, 0, 0, ltype1);
+
+      if ( ltype1 != ltype2 && ltype2 != -1 )
+        {
+          zaxisDefLtype2(zaxisID, ltype2);
+        }
 
       if ( zaxisInqType(zaxisID) == ZAXIS_REFERENCE )
         {
@@ -11014,6 +11230,9 @@ void cdi_generate_vars(stream_t *streamptr)
       if ( vartable[varid].typeOfGeneratingProcess != UNDEFID )
         vlistDefVarTypeOfGeneratingProcess(vlistID, varID, vartable[varid].typeOfGeneratingProcess);
 
+      if ( vartable[varid].productDefinitionTemplate != UNDEFID )
+        vlistDefVarProductDefinitionTemplate(vlistID, varID, vartable[varid].productDefinitionTemplate);
+
       if ( vartable[varid].lmissval ) vlistDefVarMissval(vlistID, varID, vartable[varid].missval);
 
       if ( vartable[varid].name )     vlistDefVarName(vlistID, varID, vartable[varid].name);
@@ -11038,6 +11257,7 @@ void cdi_generate_vars(stream_t *streamptr)
           int idx = vlistptr->vars[varID].opt_grib_int_nentries;
           vlistptr->vars[varID].opt_grib_int_nentries++;
           if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
+          vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
           vlistptr->vars[varID].opt_grib_int_val[idx] = vartable[varid].opt_grib_int_val[idx];
           vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(vartable[varid].opt_grib_int_keyword[idx]);
         }
@@ -11046,6 +11266,7 @@ void cdi_generate_vars(stream_t *streamptr)
           int idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
           vlistptr->vars[varID].opt_grib_dbl_nentries++;
           if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
+          vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
           vlistptr->vars[varID].opt_grib_dbl_val[idx] = vartable[varid].opt_grib_dbl_val[idx];
           vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(vartable[varid].opt_grib_dbl_keyword[idx]);
         }
@@ -11213,14 +11434,14 @@ int varDefGrid(int vlistID, grid_t grid, int mode)
 }
 
 
-int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *levels, char *longname, char *units, int ltype)
+int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *levels, char *longname, char *units, int ltype1)
 {
   int differ = 1;
   int levelID;
   int zlbounds = 0;
   int ltype_is_equal = FALSE;
 
-  if ( ltype == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
+  if ( ltype1 == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
 
   if ( ltype_is_equal && (zaxistype == zaxisInqType(zaxisID) || zaxistype == ZAXIS_GENERIC) )
     {
@@ -11262,7 +11483,7 @@ int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *l
 
 int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
 		double *levels1, double *levels2, int vctsize, double *vct, char *name,
-		char *longname, char *units, int prec, int mode, int ltype)
+		char *longname, char *units, int prec, int mode, int ltype1)
 {
   /*
     mode: 0 search in vlist and zaxis table
@@ -11286,7 +11507,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
       {
 	zaxisID = vlistptr->zaxisIDs[index];
 
-	if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype) == 0 )
+	if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype1) == 0 )
 	  {
 	    zaxisdefined = 1;
 	    break;
@@ -11304,7 +11525,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
           for ( i = 0; i < nzaxis; i++ )
             {
               zaxisID = zaxisIndexList[i];
-              if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype) == 0 )
+              if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype1) == 0 )
                 {
                   zaxisglobdefined = 1;
                   break;
@@ -11349,7 +11570,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
 	  zaxisDefLongname(zaxisID, longname);
 	  zaxisDefUnits(zaxisID, units);
 	  zaxisDefPrec(zaxisID, prec);
-	  zaxisDefLtype(zaxisID, ltype);
+	  zaxisDefLtype(zaxisID, ltype1);
 	}
 
       nzaxis = vlistptr->nzaxis;
@@ -11434,6 +11655,12 @@ void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess)
 }
 
 
+void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate)
+{
+  vartable[varID].productDefinitionTemplate = productDefinitionTemplate;
+}
+
+
 void varDefOptGribInt(int varID, long lval, const char *keyword)
 {
 #if  defined  (HAVE_LIBGRIB_API)
@@ -11521,9 +11748,9 @@ vlist_compare(vlist_t *a, vlist_t *b)
   int nvars = a->nvars;
   for (int varID = 0; varID < nvars; ++varID)
     diff |= vlistVarCompare(a, varID, b, varID);
-  int natts = a->atts.nelems;
-  for (int attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, attID);
+  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);
   return diff;
 }
 
@@ -11550,15 +11777,16 @@ resOps vlist_ops = {
 };
 
 
-vlist_t *vlist_to_pointer(int code)
+vlist_t *vlist_to_pointer(int vlistID)
 {
   VLIST_INIT();
-  return (vlist_t*) reshGetVal(code, &vlist_ops );
+  return (vlist_t*) reshGetVal(vlistID, &vlist_ops );
 }
 
 static
 void vlist_init_entry(vlist_t *vlistptr)
 {
+  vlistptr->locked         = 0;
   vlistptr->self           = CDI_UNDEFID;
   vlistptr->nvars          = 0;
   vlistptr->vars           = NULL;
@@ -11619,9 +11847,7 @@ void vlist_initialize(void)
 static
 void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
 {
-  int vlistID2;
-
-  vlistID2 = vlistptr2->self;
+  int vlistID2 = vlistptr2->self;
   memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
   vlistptr2->atts.nelems = 0;
   vlistptr2->self = vlistID2;
@@ -11634,6 +11860,34 @@ void vlist_check_ptr(const char *caller, vlist_t *vlistptr)
     Errorc("vlist undefined!");
 }
 
+
+void vlist_lock(int vlistID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlist_check_ptr(__func__, vlistptr);
+
+  if ( !vlistptr->locked )
+    {
+      vlistptr->locked = 1;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
+}
+
+
+void vlist_unlock(int vlistID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlist_check_ptr(__func__, vlistptr);
+
+  if ( vlistptr->locked )
+    {
+      vlistptr->locked = 0;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
+}
+
 /*
 @Function  vlistCreate
 @Title     Create a variable list
@@ -11660,18 +11914,12 @@ vlistDestroy(vlistID);
 */
 int vlistCreate(void)
 {
-  int vlistID = 0;
-  vlist_t *vlistptr;
-
   cdiInitialize();
 
   VLIST_INIT();
 
-  vlistptr = vlist_new_entry(CDI_UNDEFID);
-
-  vlistID = vlistptr->self;
-
-  return (vlistID);
+  vlist_t *vlistptr = vlist_new_entry(CDI_UNDEFID);
+  return (vlistptr->self);
 }
 
 static void
@@ -11696,12 +11944,11 @@ vlist_delete(vlist_t *vlistptr)
       if ( vlistptr->vars[varID].ensdata )  free(vlistptr->vars[varID].ensdata);
 
 #if  defined  (HAVE_LIBGRIB_API)
-      int i;
-      for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
+      for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
 	if ( vlistptr->vars[varID].opt_grib_int_keyword[i] )
 	  free(vlistptr->vars[varID].opt_grib_int_keyword[i]);
       }
-      for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
+      for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
 	if ( vlistptr->vars[varID].opt_grib_dbl_keyword[i] )
 	  free(vlistptr->vars[varID].opt_grib_dbl_keyword[i]);
       }
@@ -11728,11 +11975,12 @@ vlist_delete(vlist_t *vlistptr)
 */
 void vlistDestroy(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  vlist_delete(vlistptr);
+  if ( vlistptr->locked )
+    Warning("Destroying of a locked object (vlistID=%d) failed!", vlistID);
+  else
+    vlist_delete(vlistptr);
 }
 
 /*
@@ -11759,6 +12007,7 @@ void vlistCopy(int vlistID2, int vlistID1)
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
+  var_t *vlist2vars = vlistptr2->vars;
   vlist_copy(vlistptr2, vlistptr1);
 
   vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
@@ -11766,13 +12015,15 @@ void vlistCopy(int vlistID2, int vlistID1)
   if ( vlistptr1->vars )
     {
       int nvars = vlistptr1->nvars;
-      int varID;
 
       //vlistptr2->varsAllocated = nvars;
-      vlistptr2->vars = (var_t *) malloc(vlistptr2->varsAllocated*sizeof(var_t));
-      memcpy(vlistptr2->vars, vlistptr1->vars, vlistptr2->varsAllocated*sizeof(var_t));
+      vlistptr2->vars
+        = xrealloc(vlist2vars,
+                   (size_t)vlistptr2->varsAllocated * sizeof (var_t));
+      memcpy(vlistptr2->vars, vlistptr1->vars,
+             (size_t)vlistptr2->varsAllocated * sizeof (var_t));
 
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
         {
           if ( vlistptr1->vars[varID].name )
             vlistptr2->vars[varID].name = strdupx(vlistptr1->vars[varID].name);
@@ -11797,19 +12048,20 @@ void vlistCopy(int vlistID2, int vlistID1)
           /* Local change: 2013-01-28, FP (DWD) */
           /* ---------------------------------- */
 
-	  int i;
 	  vlistptr2->vars[varID].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
-	  for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
+	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
 	    if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 	      vlistptr2->vars[varID].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 	      vlistptr2->vars[varID].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+	      vlistptr2->vars[varID].opt_grib_int_update[i]  = TRUE;
 	    }
 	  }
 	  vlistptr2->vars[varID].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
-	  for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
+	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
 	    if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 	      vlistptr2->vars[varID].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 	      vlistptr2->vars[varID].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+	      vlistptr2->vars[varID].opt_grib_dbl_update[i]  = TRUE;
 	    }
 	  }
 #endif
@@ -11819,10 +12071,13 @@ void vlistCopy(int vlistID2, int vlistID1)
 
           if ( vlistptr1->vars[varID].levinfo )
             {
-              int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-              vlistptr2->vars[varID].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
+              size_t nlevs
+                = (size_t)zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+              vlistptr2->vars[varID].levinfo
+                = xmalloc(nlevs * sizeof (levinfo_t));
               memcpy(vlistptr2->vars[varID].levinfo,
-                     vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+                     vlistptr1->vars[varID].levinfo,
+                     nlevs * sizeof (levinfo_t));
             }
 	}
     }
@@ -11847,9 +12102,7 @@ The function @func{vlistDuplicate} duplicates the variable list from vlistID1.
 int vlistDuplicate(int vlistID)
 {
   int vlistIDnew;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -11864,9 +12117,7 @@ int vlistDuplicate(int vlistID)
 void vlistClearFlag(int vlistID)
 {
   int varID, levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   for ( varID = 0; varID < vlistptr->nvars; varID++ )
     {
@@ -11886,24 +12137,19 @@ static
 int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels,
                          double *lbounds, double *ubounds, int vctsize, const double *vct)
 {
-  int zaxisdefined;
-  int nzaxis;
   int zaxisID = CDI_UNDEFID;
-  int index;
   int zaxisglobdefined = 0;
   int has_bounds = FALSE;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  zaxisdefined = 0;
-  nzaxis = vlistptr->nzaxis;
+  int zaxisdefined = 0;
+  int nzaxis = vlistptr->nzaxis;
 
   if ( lbounds && ubounds ) has_bounds = TRUE;
 
-  for ( index = 0; index < nzaxis; ++index )
+  for ( int index = 0; index < nzaxis; ++index )
     {
       zaxisID = vlistptr->zaxisIDs[index];
 
@@ -11919,10 +12165,10 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels
       nzaxis = zaxisSize();
       if ( nzaxis > 0 )
         {
-          int *zaxisIndexList;
-          zaxisIndexList = (int *) malloc ( nzaxis * sizeof ( int ));
+          int *zaxisIndexList = (int *)xmalloc((size_t)nzaxis * sizeof (int));
+          reshLock();
           zaxisGetIndexList ( nzaxis, zaxisIndexList );
-          for ( index = 0; index < nzaxis; ++index )
+          for ( int index = 0; index < nzaxis; ++index )
             {
               zaxisID = zaxisIndexList[index];
               if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
@@ -11931,7 +12177,8 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels
                   break;
                 }
             }
-          if ( zaxisIndexList ) free ( zaxisIndexList );
+          reshUnlock();
+          free(zaxisIndexList);
         }
     }
 
@@ -11980,10 +12227,8 @@ The function @func{vlistCopyFlag} copies all entries with a flag from vlistID1 t
 */
 void vlistCopyFlag(int vlistID2, int vlistID1)
 {
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
@@ -11995,31 +12240,29 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
   if ( vlistptr1->vars )
     {
       int nvars = vlistptr1->nvars;
-      int nvars2 = 0, levID2;
-      int nlevs, nlevs2, levID, varID, varID2;
-      int gridID, zaxisID;
-      int index;
+      int nvars2 = 0;
+      int varID2;
 
       vlistptr2->ngrids = 0;
       vlistptr2->nzaxis = 0;
 
-      for ( varID = 0; varID < nvars; varID++ )
-        if ( vlistptr1->vars[varID].flag ) nvars2++;
+      for ( int varID = 0; varID < nvars; varID++ )
+        nvars2 += (vlistptr1->vars[varID].flag != 0);
 
       vlistptr2->nvars = nvars2;
       vlistptr2->varsAllocated = nvars2;
       if ( nvars2 > 0 )
-        vlistptr2->vars  = (var_t *) malloc(nvars2*sizeof(var_t));
+        vlistptr2->vars  = (var_t *)xmalloc((size_t)nvars2*sizeof(var_t));
       else
         vlistptr2->vars  = NULL;
 
       varID2 = 0;
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
 	if ( vlistptr1->vars[varID].flag )
 	  {
 	    vlistptr2->vars[varID2].flag = FALSE;
-	    zaxisID = vlistptr1->vars[varID].zaxisID;
-	    gridID  = vlistptr1->vars[varID].gridID;
+	    int zaxisID = vlistptr1->vars[varID].zaxisID;
+	    int gridID  = vlistptr1->vars[varID].gridID;
 
 	    memcpy(&vlistptr2->vars[varID2], &vlistptr1->vars[varID], sizeof(var_t));
 
@@ -12042,7 +12285,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 
             if ( vlistptr1->vars[varID].ensdata )
               {
-                vlistptr2->vars[varID2].ensdata = (ensinfo_t *) malloc(sizeof(ensinfo_t));
+                vlistptr2->vars[varID2].ensdata = (ensinfo_t *)xmalloc(sizeof(ensinfo_t));
                 memcpy(vlistptr2->vars[varID2].ensdata,
                        vlistptr1->vars[varID].ensdata, sizeof(ensinfo_t));
               }
@@ -12058,6 +12301,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	      if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 		vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 		vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+                vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
 	      }
 	    }
 	    vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
@@ -12065,6 +12309,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	      if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 		vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 		vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+                vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
 	      }
 	    }
 #endif
@@ -12072,38 +12317,34 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	    vlistptr2->vars[varID2].atts.nelems = 0;
 	    vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
-	    nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-	    nlevs2 = 0;
+	    int nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+	    int nlevs2 = 0;
             if ( vlistptr1->vars[varID].levinfo )
-              for ( levID = 0; levID < nlevs; levID++ )
-                if ( vlistptr1->vars[varID].levinfo[levID].flag ) nlevs2++;
+              for ( int levID = 0; levID < nlevs; levID++ )
+                nlevs2 += (vlistptr1->vars[varID].levinfo[levID].flag != 0);
 
-	    vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs2*sizeof(levinfo_t));
+	    vlistptr2->vars[varID2].levinfo = (levinfo_t *)xmalloc((size_t)nlevs2 * sizeof (levinfo_t));
 
 	    if ( nlevs != nlevs2 )
 	      {
-		int zaxisType;
-		int zaxisID2;
 		int nvct = 0;
-		double *levels;
 		double *lbounds = NULL, *ubounds = NULL;
 		const double *vct = NULL;
                 char ctemp[CDI_MAX_NAME];
 
 		zaxisID = vlistptr1->vars[varID].zaxisID;
-		levels = (double *) malloc(nlevs2*sizeof(double));
-		levID2 = 0;
+		double *levels = (double *)xmalloc((size_t)nlevs2 * sizeof (double));
+                int levID2 = 0;
                 if (!vlistptr1->vars[varID].levinfo)
                   cdiVlistCreateVarLevInfo(vlistptr1, varID);
-		for ( levID = 0; levID < nlevs; ++levID )
-		  if ( vlistptr1->vars[varID].levinfo[levID].flag )
-		    {
-		      vlistptr1->vars[varID].levinfo[levID].flevelID = levID2;
-		      vlistptr1->vars[varID].levinfo[levID].mlevelID = levID2;
-		      levels[levID2++] = zaxisInqLevel(zaxisID, levID);
-		    }
-
-		zaxisType = zaxisInqType(zaxisID);
+                for ( int levID = 0; levID < nlevs; ++levID )
+                  if ( vlistptr1->vars[varID].levinfo[levID].flag )
+                    {
+                      vlistptr1->vars[varID].levinfo[levID].flevelID = levID2;
+                      vlistptr1->vars[varID].levinfo[levID].mlevelID = levID2;
+                      levels[levID2++] = zaxisInqLevel(zaxisID, levID);
+                    }
+		int zaxisType = zaxisInqType(zaxisID);
 
 		if ( zaxisType == ZAXIS_HYBRID )
 		  {
@@ -12113,18 +12354,17 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 
                 if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
                   {
-                    double *lbounds1, *ubounds1;
-                    lbounds1 = (double *) malloc(nlevs*sizeof(double));
-                    ubounds1 = (double *) malloc(nlevs*sizeof(double));
+                    lbounds = (double *)xmalloc(2 * (size_t)nlevs2 * sizeof (double));
+                    ubounds = lbounds + nlevs2;
+
+                    double *lbounds1 = (double *)xmalloc(2 * (size_t)nlevs * sizeof (double)),
+                      *ubounds1 = lbounds1 + nlevs;
 
                     zaxisInqLbounds(zaxisID, lbounds1);
                     zaxisInqUbounds(zaxisID, ubounds1);
 
-                    lbounds = (double *) malloc(nlevs2*sizeof(double));
-                    ubounds = (double *) malloc(nlevs2*sizeof(double));
-
-                    levID2 = 0;
-                    for ( levID = 0; levID < nlevs; ++levID )
+                    int levID2 = 0;
+                    for ( int levID = 0; levID < nlevs; ++levID )
                       if ( vlistptr1->vars[varID].levinfo[levID].flag )
                         {
                           lbounds[levID2] = lbounds1[levID];
@@ -12133,13 +12373,11 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
                         }
 
                     free(lbounds1);
-                    free(ubounds1);
                   }
 
-		zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
+		int zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
 		free(levels);
-                if ( lbounds ) free(lbounds);
-                if ( ubounds ) free(ubounds);
+                free(lbounds);
 
                 zaxisInqName(zaxisID, ctemp);
                 zaxisDefName(zaxisID2, ctemp);
@@ -12152,14 +12390,14 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 		vlistptr2->vars[varID2].zaxisID = zaxisID2;
 	      }
 
-	    for ( levID = 0; levID < nlevs2; levID++ )
+	    for ( int levID = 0; levID < nlevs2; levID++ )
 	      {
 		vlistptr2->vars[varID2].levinfo[levID].flag  = FALSE;
 		vlistptr2->vars[varID2].levinfo[levID].index = -1;
 	      }
 
-	    levID2 = 0;
-	    for ( levID = 0; levID < nlevs; levID++ )
+	    int levID2 = 0;
+	    for ( int levID = 0; levID < nlevs; levID++ )
 	      if ( vlistptr1->vars[varID].levinfo[levID].flag )
 		{
 		  vlistptr2->vars[varID2].levinfo[levID2].flevelID = levID;
@@ -12167,25 +12405,8 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 		  levID2++;
 		}
 
-	    for ( index = 0; index <vlistptr2->ngrids; index++ )
-	      if (vlistptr2->gridIDs[index] == gridID ) break;
-
-	    if ( index == vlistptr2->ngrids )
-	      {
-		vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
-		if (vlistptr2->ngrids >= MAX_GRIDS_PS )
-		  Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
-	      }
-
-	    for ( index = 0; index < vlistptr2->nzaxis; index++ )
-	      if ( vlistptr2->zaxisIDs[index] == zaxisID ) break;
-
-	    if ( index == vlistptr2->nzaxis )
-	      {
-		vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
-		if (vlistptr2->nzaxis >= MAX_ZAXES_PS )
-		  Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
-	      }
+            vlistAdd2GridIDs(vlistptr2, gridID);
+            vlistAdd2ZaxisIDs(vlistptr2, zaxisID);
 
 	    varID2++;
 	  }
@@ -12208,32 +12429,29 @@ Concatenate the variable list vlistID1 at the end of vlistID2.
 */
 void vlistCat(int vlistID2, int vlistID1)
 {
-  int nvars, nvars1, nvars2;
-  int varID, varID2, nlevs;
-  int index, gridID, zaxisID;
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
-  nvars1 = vlistptr1->nvars;
-  nvars2 = vlistptr2->nvars;
-  nvars = nvars1 + nvars2;
+  int nvars1 = vlistptr1->nvars;
+  int nvars2 = vlistptr2->nvars;
+  int nvars = nvars1 + nvars2;
   vlistptr2->nvars = nvars;
 
   if ( nvars > vlistptr2->varsAllocated )
     {
       vlistptr2->varsAllocated = nvars;
-      vlistptr2->vars = (var_t *) realloc(vlistptr2->vars, nvars*sizeof(var_t));
+      vlistptr2->vars = xrealloc(vlistptr2->vars,
+                                 (size_t)nvars * sizeof (var_t));
     }
-  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars, nvars1*sizeof(var_t));
+  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars,
+         (size_t)nvars1 * sizeof (var_t));
 
-  for ( varID = 0; varID < nvars1; varID++ )
+  for (int varID = 0; varID < nvars1; varID++ )
     {
-      varID2 = varID + nvars2;
+      int varID2 = varID + nvars2;
       vlistptr1->vars[varID].fvarID = varID2;
       vlistptr2->vars[varID2].fvarID = varID;
 
@@ -12260,11 +12478,14 @@ void vlistCat(int vlistID2, int vlistID1)
       if ( vlistptr1->vars[varID].units )
         vlistptr2->vars[varID2].units = strdupx(vlistptr1->vars[varID].units);
 
-      nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+      int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
       if (vlistptr1->vars[varID].levinfo)
         {
-          vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
-          memcpy(vlistptr2->vars[varID2].levinfo, vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+          vlistptr2->vars[varID2].levinfo
+            = (levinfo_t *)xmalloc((size_t)nlevs * sizeof (levinfo_t));
+          memcpy(vlistptr2->vars[varID2].levinfo,
+                 vlistptr1->vars[varID].levinfo,
+                 (size_t)nlevs * sizeof (levinfo_t));
         }
 
       if ( vlistptr1->vars[varID].ensdata )
@@ -12278,19 +12499,22 @@ void vlistCat(int vlistID2, int vlistID1)
       /* Local change: 2013-01-28, FP (DWD) */
       /* ---------------------------------- */
 
-      int i;
       vlistptr2->vars[varID2].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
-      for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
+      int n = vlistptr1->vars[varID].opt_grib_int_nentries;
+      for (int i = 0; i < n; ++i) {
 	if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 	  vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 	  vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+          vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
 	}
       }
       vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
-      for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
+      n = vlistptr1->vars[varID].opt_grib_dbl_nentries;
+      for (int i = 0; i < n; i++) {
 	if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 	  vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 	  vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+          vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
 	}
       }
 #endif
@@ -12298,27 +12522,8 @@ void vlistCat(int vlistID2, int vlistID1)
       vlistptr2->vars[varID2].atts.nelems = 0;
       vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
-      gridID = vlistptr1->vars[varID].gridID;
-      for ( index = 0; index < vlistptr2->ngrids; index++ )
-        if ( gridID == vlistptr2->gridIDs[index] ) break;
-
-      if ( index == vlistptr2->ngrids )
-	{
-	  vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
-	  if ( vlistptr2->ngrids >= MAX_GRIDS_PS )
-	    Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
-	}
-
-      zaxisID = vlistptr1->vars[varID].zaxisID;
-      for ( index = 0; index < vlistptr2->nzaxis; index++ )
-        if ( zaxisID == vlistptr2->zaxisIDs[index] ) break;
-
-      if ( index == vlistptr2->nzaxis )
-	{
-	  vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
-	  if ( vlistptr2->nzaxis >= MAX_ZAXES_PS )
-	    Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
-	}
+      vlistAdd2GridIDs(vlistptr2, vlistptr1->vars[varID].gridID);
+      vlistAdd2ZaxisIDs(vlistptr2, vlistptr1->vars[varID].zaxisID);
     }
 }
 
@@ -12338,22 +12543,15 @@ Merge the variable list vlistID1 to the variable list vlistID2.
 */
 void vlistMerge(int vlistID2, int vlistID1)
 {
-  int nvars1, nvars2;
-  int varID = 0, varID2, levID, nlevs, nlevs1, nlevs2;
-  int index, zaxisID;
-  int zaxisID1, zaxisID2;
-  int *lvar;
-  double *levels;
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  int varID = 0;
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
-  nvars1 = vlistptr1->nvars;
-  nvars2 = vlistptr2->nvars;
+  int nvars1 = vlistptr1->nvars;
+  int nvars2 = vlistptr2->nvars;
 
   if ( nvars1 == nvars2 )
     {
@@ -12382,71 +12580,72 @@ void vlistMerge(int vlistID2, int vlistID1)
           vlistptr1->vars[varID].mvarID = varID;
           vlistptr2->vars[varID].mvarID = varID;
 
-          nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-          nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
+          int nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+          int nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
 
-          nlevs = nlevs1 + nlevs2;
+          int nlevs = nlevs1 + nlevs2;
 
           /*
           fprintf(stderr, "var %d %d %d %d %d\n", varID, nlevs1, nlevs2, nlevs, sizeof(levinfo_t));
           */
           if (vlistptr1->vars[varID].levinfo)
             {
-              vlistptr2->vars[varID].levinfo = (levinfo_t*)
-                xrealloc(vlistptr2->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+              vlistptr2->vars[varID].levinfo =
+                (levinfo_t*)xrealloc(vlistptr2->vars[varID].levinfo,
+                                     (size_t)nlevs * sizeof(levinfo_t));
 
               memcpy(vlistptr2->vars[varID].levinfo+nlevs2,
-                     vlistptr1->vars[varID].levinfo, nlevs1*sizeof(levinfo_t));
+                     vlistptr1->vars[varID].levinfo,
+                     (size_t)nlevs1 * sizeof (levinfo_t));
             }
           else
             cdiVlistCreateVarLevInfo(vlistptr1, varID);
-	  for ( levID = 0; levID < nlevs1; levID++ )
+	  for ( int levID = 0; levID < nlevs1; levID++ )
 	    {
 	      vlistptr1->vars[varID].levinfo[levID].mlevelID = nlevs2 + levID;
 	    }
 	}
 
-      lvar = (int *) malloc(nvars2*sizeof(int));
-      for ( varID = 0; varID < nvars2; varID++ ) lvar[varID] = FALSE;
+      int *lvar = (int *)xcalloc((size_t)nvars2, sizeof(int));
 
       for ( varID = 0; varID < nvars2; varID++ )
         {
           if ( lvar[varID] == TRUE ) continue;
 
-          zaxisID1 = vlistptr1->vars[varID].zaxisID;
-          zaxisID2 = vlistptr2->vars[varID].zaxisID;
+          int zaxisID1 = vlistptr1->vars[varID].zaxisID;
+          int zaxisID2 = vlistptr2->vars[varID].zaxisID;
           /*
           nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
           nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
           */
-          nlevs1 = zaxisInqSize(zaxisID1);
-          nlevs2 = zaxisInqSize(zaxisID2);
+          int nlevs1 = zaxisInqSize(zaxisID1);
+          int nlevs2 = zaxisInqSize(zaxisID2);
           /*
           fprintf(stderr, "zaxis %d %d %d %d\n", zaxisID1, zaxisID2, nlevs1, nlevs2);
           */
-          nlevs = nlevs1 + nlevs2;
+          int nlevs = nlevs1 + nlevs2;
 
-          zaxisID = zaxisDuplicate(zaxisID2);
+          int zaxisID = zaxisDuplicate(zaxisID2);
 
           zaxisResize(zaxisID, nlevs);
 
-          levels = (double *) malloc(nlevs1*sizeof(double));
+          double *levels = (double *)xmalloc((size_t)nlevs1 * sizeof(double));
 
           zaxisInqLevels(zaxisID1, levels);
           /*
           for ( levID = 0; levID < nlevs1; levID++ )
             fprintf(stderr, "%d %d %d %d %d %g\n", varID, levID, nlevs1, nlevs2, vlistptr2->vars[varID].nlevs, levels[levID]);
           */
-          for ( levID = 0; levID < nlevs1; levID++ )
+          for ( int levID = 0; levID < nlevs1; levID++ )
             zaxisDefLevel(zaxisID, nlevs2+levID, levels[levID]);
 
           free(levels);
 
-          for ( index = 0; index < vlistptr2->nzaxis; index++ )
+          for ( int index = 0; index < vlistptr2->nzaxis; index++ )
             if ( vlistptr2->zaxisIDs[index] == zaxisID2 )
               vlistptr2->zaxisIDs[index] = zaxisID;
 
-          for ( varID2 = 0; varID2 < nvars2; varID2++ )
+          for ( int varID2 = 0; varID2 < nvars2; varID2++ )
             if ( lvar[varID2] == FALSE && vlistptr2->vars[varID2].zaxisID == zaxisID2 )
               {
                 vlistptr2->vars[varID2].zaxisID = zaxisID;
@@ -12480,9 +12679,7 @@ The function @func{vlistNvars} returns the number of variables in the variable l
 */
 int vlistNvars(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12492,14 +12689,12 @@ int vlistNvars(int vlistID)
 
 int vlistNrecs(int vlistID)
 {
-  int varID, nrecs = 0;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int nrecs = 0;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( varID = 0; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     nrecs +=  zaxisInqSize(vlistptr->vars[varID].zaxisID);
 
   return (nrecs);
@@ -12508,10 +12703,8 @@ int vlistNrecs(int vlistID)
 
 int vlistNumber(int vlistID)
 {
-  int varID, number, number2, datatype;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int number, number2, datatype;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12521,7 +12714,7 @@ int vlistNumber(int vlistID)
   else
     number = CDI_REAL;
 
-  for ( varID = 1; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 1; varID < vlistptr->nvars; varID++ )
     {
       datatype = vlistptr->vars[varID].datatype;
       if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
@@ -12557,9 +12750,7 @@ The function @func{vlistNgrids} returns the number of grids in the variable list
 */
 int vlistNgrids(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12584,9 +12775,7 @@ The function @func{vlistNzaxis} returns the number of zaxis in the variable list
 */
 int vlistNzaxis(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12596,27 +12785,21 @@ int vlistNzaxis(int vlistID)
 
 void vlistDefNtsteps(int vlistID, int nts)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->ntsteps != nts)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->ntsteps = nts;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->ntsteps = nts;
 }
 
 
 int vlistNtsteps(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12626,46 +12809,39 @@ int vlistNtsteps(int vlistID)
 static void
 vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
 {
-  int nvars, flag, index;
-  int varID, fvarID, mvarID, flevID, mlevID, levID;
-  int param, gridID, zaxisID, tsteptype, nlevs;
-  int dtype;
-
-  int iorank;
-
   char paramstr[32];
-  char *name, *longname, *units;
-  double level;
 
   vlist_check_ptr(__func__, vlistptr);
 
   fprintf ( fp, "#\n# vlistID %d\n#\n", vlistptr->self);
 
-  nvars = vlistptr->nvars;
+  int nvars = vlistptr->nvars;
 
-  fprintf ( fp, "nvars   %d\n", nvars);
-  fprintf ( fp, "ngrids  %d\n", vlistptr->ngrids);
-  fprintf ( fp, "nzaxis  %d\n", vlistptr->nzaxis);
-  fprintf ( fp, "taxisID %d\n", vlistptr->taxisID);
-  fprintf ( fp, "instID  %d\n", vlistptr->instID);
-  fprintf ( fp, "modelID %d\n", vlistptr->modelID);
-  fprintf ( fp, "tableID %d\n", vlistptr->tableID);
+  fprintf(fp, "nvars   %d\n"
+          "ngrids  %d\n"
+          "nzaxis  %d\n"
+          "taxisID %d\n"
+          "instID  %d\n"
+          "modelID %d\n"
+          "tableID %d\n",
+          nvars, vlistptr->ngrids, vlistptr->nzaxis, vlistptr->taxisID,
+          vlistptr->instID, vlistptr->modelID, vlistptr->tableID);
 
   if ( nvars > 0 )
     {
       fprintf(fp, " varID param    gridID zaxisID tsteptype flag "
               " name     longname iorank\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
         {
-          param    = vlistptr->vars[varID].param;
-          gridID   = vlistptr->vars[varID].gridID;
-          zaxisID  = vlistptr->vars[varID].zaxisID;
-	  tsteptype= vlistptr->vars[varID].tsteptype;
-          name     = vlistptr->vars[varID].name;
-          longname = vlistptr->vars[varID].longname;
-          units    = vlistptr->vars[varID].units;
-          flag     = vlistptr->vars[varID].flag;
-          iorank   = vlistptr->vars[varID].iorank;
+          int param = vlistptr->vars[varID].param;
+          int gridID = vlistptr->vars[varID].gridID;
+          int zaxisID = vlistptr->vars[varID].zaxisID;
+	  int tsteptype = vlistptr->vars[varID].tsteptype;
+          const char *name = vlistptr->vars[varID].name;
+          const char *longname = vlistptr->vars[varID].longname;
+          const char *units = vlistptr->vars[varID].units;
+          int flag = vlistptr->vars[varID].flag;
+          int iorank = vlistptr->vars[varID].iorank;
 
           cdiParamToString(param, paramstr, sizeof(paramstr));
           fprintf(fp, "%6d %-8s %6d %6d %6d %5d %-8s"
@@ -12674,31 +12850,31 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
                   name ? name : "", longname ? longname : "",
                   iorank);
 
-          if ( units ) fprintf ( fp, "   [%s]", units);
-          fprintf ( fp, "\n");
+          if ( units ) fprintf(fp, "   [%s]", units);
+          fputs("\n", fp);
         }
 
-      fprintf(fp, "\n");
-      fprintf(fp, " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      fputs("\n"
+            " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n", fp);
+      for ( int varID = 0; varID < nvars; varID++ )
         {
-          zaxisID  = vlistptr->vars[varID].zaxisID;
-          nlevs    = zaxisInqSize(zaxisID);
-          fvarID   = vlistptr->vars[varID].fvarID;
-          mvarID   = vlistptr->vars[varID].mvarID;
-          dtype    = vlistptr->vars[varID].datatype;
-          for ( levID = 0; levID < nlevs; levID++ )
+          int zaxisID = vlistptr->vars[varID].zaxisID;
+          int nlevs = zaxisInqSize(zaxisID);
+          int fvarID = vlistptr->vars[varID].fvarID;
+          int mvarID = vlistptr->vars[varID].mvarID;
+          int dtype    = vlistptr->vars[varID].datatype;
+          for ( int levID = 0; levID < nlevs; levID++ )
             {
               levinfo_t li;
               if (vlistptr->vars[varID].levinfo)
                 li = vlistptr->vars[varID].levinfo[levID];
               else
                 li = DEFAULT_LEVINFO(levID);
-              flevID = li.flevelID;
-              mlevID = li.mlevelID;
-              index  = li.index;
-              flag   = li.flag;
-              level  = zaxisInqLevel(zaxisID, levID);
+              int flevID = li.flevelID;
+              int mlevID = li.mlevelID;
+              int index  = li.index;
+              int flag   = li.flag;
+              double level  = zaxisInqLevel(zaxisID, levID);
 
               fprintf(fp, "%6d %6d %6d %6d %6d %6d %6d %6d %5d  %.9g\n",
                       varID, levID, fvarID, flevID, mvarID, mlevID, index,
@@ -12706,9 +12882,9 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
             }
         }
 
-      fprintf(fp, "\n");
-      fprintf(fp, " varID  size iorank\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      fputs("\n"
+            " varID  size iorank\n", fp);
+      for ( int varID = 0; varID < nvars; varID++ )
         fprintf(fp, "%3d %8d %6d\n", varID,
                 zaxisInqSize(vlistptr->vars[varID].zaxisID)
                 * gridInqSize(vlistptr->vars[varID].gridID),
@@ -12719,11 +12895,8 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
 
 void vlistPrint(int vlistID)
 {
-  vlist_t *vlistptr;
-
   if ( vlistID == CDI_UNDEFID ) return;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   vlist_check_ptr(__func__, vlistptr);
   vlistPrintKernel(vlistptr, stdout);
 }
@@ -12744,19 +12917,15 @@ The function @func{vlistDefTaxis} defines the time axis of a variable list.
 */
 void vlistDefTaxis(int vlistID, int taxisID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->taxisID != taxisID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->taxisID = taxisID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->taxisID = taxisID;
 }
 
 /*
@@ -12777,9 +12946,7 @@ The function @func{vlistInqTaxis} returns the time axis of a variable list.
 */
 int vlistInqTaxis(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12787,29 +12954,23 @@ int vlistInqTaxis(int vlistID)
 }
 
 
-void  vlistDefTable(int vlistID, int tableID)
+void vlistDefTable(int vlistID, int tableID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->tableID != tableID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->tableID = tableID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->tableID = tableID;
 }
 
 
 int vlistInqTable(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12819,38 +12980,31 @@ int vlistInqTable(int vlistID)
 
 void vlistDefInstitut(int vlistID, int instID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->instID != instID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->instID = instID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->instID = instID;
 }
 
 
 int vlistInqInstitut(int vlistID)
 {
-  int varID, instID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  instID = vlistptr->instID;
+  int instID = vlistptr->instID;
 
   if ( instID == CDI_UNDEFID )
     {
       instID  = vlistInqVarInstitut(vlistID, 0);
 
-      for ( varID = 1; varID < vlistptr->nvars; varID++ )
+      for ( int varID = 1; varID < vlistptr->nvars; varID++ )
         if ( instID != vlistInqVarInstitut(vlistID, varID) )
           {
             instID = CDI_UNDEFID;
@@ -12865,38 +13019,31 @@ int vlistInqInstitut(int vlistID)
 
 void vlistDefModel(int vlistID, int modelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->modelID != modelID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->modelID = modelID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->modelID = modelID;
 }
 
 
 int vlistInqModel(int vlistID)
 {
-  int varID, modelID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  modelID = vlistptr->modelID;
+  int modelID = vlistptr->modelID;
 
   if ( modelID == CDI_UNDEFID )
     {
       modelID = vlistInqVarModel(vlistID, 0);
 
-      for ( varID = 1; varID < vlistptr->nvars; varID++ )
+      for ( int varID = 1; varID < vlistptr->nvars; varID++ )
         if ( modelID != vlistInqVarModel(vlistID, varID) )
           {
             modelID = CDI_UNDEFID;
@@ -12912,18 +13059,15 @@ int vlistInqModel(int vlistID)
 
 int vlistGridsizeMax(int vlistID)
 {
-  int gridsize, gridsizemax = 0;
-  int gridID, index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int gridsizemax = 0;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( index = 0 ; index < vlistptr->ngrids ; index++ )
+  for ( int index = 0 ; index < vlistptr->ngrids ; index++ )
     {
-      gridID = vlistptr->gridIDs[index];
-      gridsize = gridInqSize(gridID);
+      int gridID = vlistptr->gridIDs[index];
+      int gridsize = gridInqSize(gridID);
       if ( gridsize > gridsizemax ) gridsizemax = gridsize;
     }
 
@@ -12934,9 +13078,7 @@ int vlistGridsizeMax(int vlistID)
 int vlistGrid(int vlistID, int index)
 {
   int gridID = CDI_UNDEFID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12950,9 +13092,7 @@ int vlistGrid(int vlistID, int index)
 int vlistGridIndex(int vlistID, int gridID)
 {
   int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -12967,69 +13107,54 @@ int vlistGridIndex(int vlistID, int gridID)
 
 void vlistChangeGridIndex(int vlistID, int index, int gridID)
 {
-  int gridIDold;
-  int varID, nvars;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int gridIDold = vlistptr->gridIDs[index];
+  if (gridIDold != gridID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  gridIDold = vlistptr->gridIDs[index];
-  vlistptr->gridIDs[index] = gridID;
+      vlistptr->gridIDs[index] = gridID;
 
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].gridID == gridIDold )
-      vlistptr->vars[varID].gridID = gridID;
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].gridID == gridIDold )
+          vlistptr->vars[varID].gridID = gridID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistChangeGrid(int vlistID, int gridID1, int gridID2)
 {
-  int varID, nvars;
-  int index, ngrids;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (gridID1 != gridID2)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  ngrids = vlistptr->ngrids;
-  for ( index = 0; index < ngrids; index++ )
-    {
-      if ( vlistptr->gridIDs[index] == gridID1 )
+      int ngrids = vlistptr->ngrids;
+      for ( int index = 0; index < ngrids; index++ )
         {
-          vlistptr->gridIDs[index] = gridID2;
-          break;
+          if ( vlistptr->gridIDs[index] == gridID1 )
+            {
+              vlistptr->gridIDs[index] = gridID2;
+              break;
+            }
         }
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].gridID == gridID1 )
+          vlistptr->vars[varID].gridID = gridID2;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].gridID == gridID1 )
-      vlistptr->vars[varID].gridID = gridID2;
 }
 
 
 int vlistZaxis(int vlistID, int index)
 {
   int zaxisID = CDI_UNDEFID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -13041,13 +13166,11 @@ int vlistZaxis(int vlistID, int index)
 
 int vlistZaxisIndex(int vlistID, int zaxisID)
 {
-  int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
+  int index;
   for ( index = 0 ; index < vlistptr->nzaxis ; index++ )
     if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
 
@@ -13059,63 +13182,44 @@ int vlistZaxisIndex(int vlistID, int zaxisID)
 
 void vlistChangeZaxisIndex(int vlistID, int index, int zaxisID)
 {
-  int zaxisIDold;
-  int varID, nvars;
-  int nlevs, levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int zaxisIDold = vlistptr->zaxisIDs[index];
+  if (zaxisIDold != zaxisID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  zaxisIDold = vlistptr->zaxisIDs[index];
-  vlistptr->zaxisIDs[index] = zaxisID;
-
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].zaxisID == zaxisIDold )
-      {
-        vlistptr->vars[varID].zaxisID = zaxisID;
+      vlistptr->zaxisIDs[index] = zaxisID;
 
-        nlevs = zaxisInqSize(zaxisID);
-        if ( vlistptr->vars[varID].levinfo
-             && nlevs != zaxisInqSize(zaxisIDold) )
+      int nlevs = zaxisInqSize(zaxisID),
+        nlevsOld = zaxisInqSize(zaxisIDold);
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].zaxisID == zaxisIDold )
           {
-            vlistptr->vars[varID].levinfo = (levinfo_t *) realloc(vlistptr->vars[varID].levinfo,
-                                                                     nlevs*sizeof(levinfo_t));
+            vlistptr->vars[varID].zaxisID = zaxisID;
+            if ( vlistptr->vars[varID].levinfo && nlevs != nlevsOld )
+              {
+                vlistptr->vars[varID].levinfo = (levinfo_t *)xrealloc(vlistptr->vars[varID].levinfo, (size_t)nlevs * sizeof (levinfo_t));
 
-            for ( levID = 0; levID < nlevs; levID++ )
-              vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+                for ( int levID = 0; levID < nlevs; levID++ )
+                  vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+              }
           }
-      }
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
 {
-  int varID, nvars;
-  int index, nzaxis;
-  int nlevs1 = zaxisInqSize(zaxisID1), nlevs2 = zaxisInqSize(zaxisID2), levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int nlevs1 = zaxisInqSize(zaxisID1), nlevs2 = zaxisInqSize(zaxisID2);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  nzaxis = vlistptr->nzaxis;
-  for ( index = 0; index < nzaxis; index++ )
+  int nzaxis = vlistptr->nzaxis;
+  for ( int index = 0; index < nzaxis; index++ )
     {
       if ( vlistptr->zaxisIDs[index] == zaxisID1 )
         {
@@ -13124,8 +13228,8 @@ void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
         }
     }
 
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
+  int nvars = vlistptr->nvars;
+  for ( int varID = 0; varID < nvars; varID++ )
     if ( vlistptr->vars[varID].zaxisID == zaxisID1 )
       {
         vlistptr->vars[varID].zaxisID = zaxisID2;
@@ -13133,27 +13237,25 @@ void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
         if ( vlistptr->vars[varID].levinfo && nlevs2 != nlevs1 )
           {
             vlistptr->vars[varID].levinfo
-              = (levinfo_t*) realloc(vlistptr->vars[varID].levinfo,
-                                     nlevs2 * sizeof(levinfo_t));
+              = (levinfo_t *)xrealloc(vlistptr->vars[varID].levinfo,
+                                      (size_t)nlevs2 * sizeof(levinfo_t));
 
-            for ( levID = 0; levID < nlevs2; levID++ )
+            for ( int levID = 0; levID < nlevs2; levID++ )
               vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
           }
       }
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistHasTime(int vlistID)
 {
-  int varID;
   int hastime = FALSE;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( varID = 0; varID <  vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID <  vlistptr->nvars; varID++ )
     if ( vlistptr->vars[varID].tsteptype != TSTEP_CONSTANT )
       {
         hastime = TRUE;
@@ -13227,6 +13329,20 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
     vlistVarUnpack(targetID, buf, size, position, originNamespace, context);
 }
 
+
+void vlist_check_contents(int vlistID)
+{
+  int index, nzaxis, zaxisID;
+
+  nzaxis = vlistNzaxis(vlistID);
+
+  for ( index = 0; index < nzaxis; index++ )
+    {
+      zaxisID = vlistZaxis(vlistID, index);
+      if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
+	cdiCheckZaxis(zaxisID);
+    }
+}
 /*
  * Local Variables:
  * c-file-style: "Java"
@@ -13239,9 +13355,10 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
 #ifdef HAVE_CONFIG_H
 #endif
 
+#include <assert.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 
 
@@ -13352,11 +13469,11 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp)
   cdi_atts_t *attsp;
 
   vlistptr = vlist_to_pointer(vlistID);
-  
+
   attsp = get_attsp(vlistptr, varID);
   xassert(attsp != NULL);
 
-  *nattsp = attsp->nelems;
+  *nattsp = (int)attsp->nelems;
 
   return (status);
 }
@@ -13370,7 +13487,7 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp)
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} 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 
+    @Item  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 @func{CDI_MAX_NAME}.
     @Item  typep    Pointer to location for returned attribute type.
@@ -13384,15 +13501,13 @@ The function @func{vlistInqAtt} gets information about an attribute.
 int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
   cdi_att_t *attp = NULL;
-  cdi_atts_t *attsp;
 
   xassert(name != NULL);
 
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = get_attsp(vlistptr, varID);
   xassert(attsp != NULL);
 
   if ( attnum >= 0 && attnum < (int)attsp->nelems )
@@ -13402,13 +13517,14 @@ int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int
     {
       memcpy(name, attp->name, attp->namesz+1);
       *typep  = attp->exdtype;
-      *lenp   = attp->nelems;
+      *lenp   = (int)attp->nelems;
     }
   else
     {
       name[0] =  0;
       *typep  = -1;
       *lenp   =  0;
+      status  = -1;
     }
 
   return (status);
@@ -13445,6 +13561,10 @@ int vlistDelAtt(int vlistID, int varID, const char *name)
 {
   int status = CDI_NOERR;
 
+  UNUSED(vlistID);
+  UNUSED(varID);
+  UNUSED(name);
+
   fprintf(stderr, "vlistDelAtt not implemented!\n");
 
   return (status);
@@ -13510,11 +13630,13 @@ int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t
       else
 	{
 	  Warning("Attribute %s has wrong data type!", name);
+          status = -2;
 	}
     }
   else
     {
-      Warning("Internal problem, attribute %s not found!", name);
+      //Warning("Internal problem, attribute %s not found!", name);
+      status = -1;
     }
 
   return (status);
@@ -13564,7 +13686,7 @@ The function @func{vlistDefAttInt} defines an integer attribute.
 */
 int vlistDefAttInt(int vlistID, 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, len*sizeof(int), (const void *) ip);
+  return vlist_def_att(DATATYPE_INT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (int), ip);
 }
 
 /*
@@ -13588,7 +13710,7 @@ The function @func{vlistDefAttFlt} defines a floating point attribute.
 */
 int vlistDefAttFlt(int vlistID, 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, len*sizeof(double), (const void *) dp);
+  return vlist_def_att(DATATYPE_FLT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (double), dp);
 }
 
 /*
@@ -13611,7 +13733,7 @@ The function @func{vlistDefAttTxt} defines a text attribute.
 */
 int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)
 {
-  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t) len, len*sizeof(char), (const void *) tp);
+  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (char), tp);
 }
 
 /*
@@ -13633,7 +13755,7 @@ The function @func{vlistInqAttInt} gets the values(s) of an integer attribute.
 */
 int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
 {
-  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, mlen*sizeof(int), (void *) ip);
+  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, (size_t)mlen * sizeof (int), ip);
 }
 
 /*
@@ -13655,7 +13777,7 @@ The function @func{vlistInqAttFlt} gets the values(s) of a floating point attrib
 */
 int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
 {
-  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, mlen*sizeof(double), (void *) dp);
+  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, (size_t)mlen * sizeof (double), dp);
 }
 
 /*
@@ -13677,7 +13799,7 @@ The function @func{vlistInqAttTxt} gets the values(s) of a text attribute.
 */
 int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
 {
-  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, mlen*sizeof(char), (void *) tp);
+  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, (size_t)mlen * sizeof (char), tp);
 }
 
 enum {
@@ -13740,7 +13862,7 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
   attp = &(attsp->value[attnum]);
   int txsize = serializeGetSize(vlist_att_nints, DATATYPE_INT, context)
-    + serializeGetSize(attp->namesz, DATATYPE_TXT, context);
+    + serializeGetSize((int)attp->namesz, DATATYPE_TXT, context);
   txsize += serializeGetSize((int)attp->nelems, vlistAttTypeLookup(attp), context);
   return txsize;
 }
@@ -13748,12 +13870,11 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
 int
 vlistAttsGetSize(vlist_t *p, int varID, void *context)
 {
-  int numAtts, i;
   cdi_atts_t *attsp = get_attsp(p, varID);
   int txsize = serializeGetSize(1, DATATYPE_INT, context);
-  numAtts = attsp->nelems;
-  for (i = 0; i < numAtts; ++i)
-    txsize += vlistAttGetSize(p, varID, i, context);
+  size_t numAtts = attsp->nelems;
+  for (size_t i = 0; i < numAtts; ++i)
+    txsize += vlistAttGetSize(p, varID, (int)i, context);
   return txsize;
 }
 
@@ -13768,12 +13889,12 @@ vlistAttPack(vlist_t *vlistptr, int varID, int attnum,
   xassert(attsp = get_attsp(vlistptr, varID));
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
   attp = &(attsp->value[attnum]);
-  tempbuf[0] = attp->namesz;
+  tempbuf[0] = (int)attp->namesz;
   tempbuf[1] = attp->exdtype;
   tempbuf[2] = attp->indtype;
-  tempbuf[3] = attp->nelems;
+  tempbuf[3] = (int)attp->nelems;
   serializePack(tempbuf, vlist_att_nints, DATATYPE_INT, buf, size, position, context);
-  serializePack(attp->name, attp->namesz, DATATYPE_TXT, buf, size, position, context);
+  serializePack(attp->name, (int)attp->namesz, DATATYPE_TXT, buf, size, position, context);
   serializePack(attp->xvalue, (int)attp->nelems, vlistAttTypeLookup(attp),
                 buf, size, position, context);
 }
@@ -13782,28 +13903,28 @@ void
 vlistAttsPack(vlist_t *p, int varID,
               void * buf, int size, int *position, void *context)
 {
-  int numAtts, i;
   cdi_atts_t *attsp = get_attsp(p, varID);
-  numAtts = attsp->nelems;
-  serializePack(&numAtts, 1, DATATYPE_INT, buf, size, position, context);
-  for (i = 0; i < numAtts; ++i)
-    vlistAttPack(p, varID, i, buf, size, position, context);
+  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);
 }
 
 static void
 vlistAttUnpack(int vlistID, int varID,
                void * buf, int size, int *position, void *context)
 {
-  char *attName;
   int tempbuf[vlist_att_nints];
-  int attVDt;
-  int elemSize;
 
   serializeUnpack(buf, size, position,
                   tempbuf, vlist_att_nints, DATATYPE_INT, context);
-  attName = (char*) xmalloc(tempbuf[0] + 1);
+  char *attName = (char *)xmalloc((size_t)tempbuf[0] + 1);
   serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context);
   attName[tempbuf[0]] = '\0';
+  int attVDt;
+  size_t elemSize;
   switch (tempbuf[2])
   {
   case DATATYPE_FLT:
@@ -13822,10 +13943,10 @@ vlistAttUnpack(int vlistID, int varID,
     xabort("Unknown datatype encountered in attribute %s: %d\n",
            attName, tempbuf[2]);
   }
-  void *attData = xmalloc(elemSize * tempbuf[3]);
+  void *attData = (void *)xmalloc(elemSize * (size_t)tempbuf[3]);
   serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
   vlist_def_att(tempbuf[2], tempbuf[1], vlistID, varID, attName,
-                tempbuf[3], tempbuf[3] * elemSize, attData);
+                (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
   free(attName);
   free(attData);
 }
@@ -13866,9 +13987,7 @@ resOps vlist_ops;
 static
 void vlistvarInitEntry(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistptr->vars[varID].fvarID        = varID;
   vlistptr->vars[varID].mvarID        = varID;
@@ -13878,9 +13997,10 @@ void vlistvarInitEntry(int vlistID, int varID)
   vlistptr->vars[varID].tsteptype     = TSTEP_INSTANT;
   vlistptr->vars[varID].timave        = 0;
   vlistptr->vars[varID].timaccu       = 0;
-  vlistptr->vars[varID].typeOfGeneratingProcess = 0;
+  vlistptr->vars[varID].typeOfGeneratingProcess   = 0;
+  vlistptr->vars[varID].productDefinitionTemplate = -1;
   vlistptr->vars[varID].chunktype     = cdiChunkType;
-  vlistptr->vars[varID].xyz           = 0;
+  vlistptr->vars[varID].xyz           = 321;
   vlistptr->vars[varID].gridID        = CDI_UNDEFID;
   vlistptr->vars[varID].zaxisID       = CDI_UNDEFID;
   vlistptr->vars[varID].instID        = CDI_UNDEFID;
@@ -13915,8 +14035,10 @@ void vlistvarInitEntry(int vlistID, int varID)
   vlistptr->vars[varID].opt_grib_int_nentries = 0;
   int i;
   for (i=0; i<MAX_OPT_GRIB_ENTRIES; i++) {
-    vlistptr->vars[varID].opt_grib_dbl_val[i] = 0.0;
     vlistptr->vars[varID].opt_grib_int_val[i] =   0;
+    vlistptr->vars[varID].opt_grib_dbl_val[i] = 0.0;
+    vlistptr->vars[varID].opt_grib_int_update[i] = FALSE;
+    vlistptr->vars[varID].opt_grib_dbl_update[i] = FALSE;
     vlistptr->vars[varID].opt_grib_int_keyword[i] = NULL;
     vlistptr->vars[varID].opt_grib_dbl_keyword[i] = NULL;
   } // for
@@ -13929,9 +14051,7 @@ int vlistvarNewEntry(int vlistID)
   int varID = 0;
   int vlistvarSize;
   var_t *vlistvar;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistvarSize = vlistptr->varsAllocated;
   vlistvar     = vlistptr->vars;
@@ -13941,17 +14061,9 @@ int vlistvarNewEntry(int vlistID)
   */
   if ( ! vlistvarSize )
     {
-      int i;
-
       vlistvarSize = 2;
-      vlistvar = (var_t *) malloc(vlistvarSize*sizeof(var_t));
-      if ( vlistvar == NULL )
-	{
-          Message("vlistvarSize = %d", vlistvarSize);
-	  SysError("Allocation of var_t failed");
-	}
-
-      for ( i = 0; i < vlistvarSize; i++ )
+      vlistvar = (var_t *)xmalloc((size_t)vlistvarSize * sizeof (var_t));
+      for (int i = 0; i < vlistvarSize; i++ )
 	vlistvar[i].isUsed = FALSE;
     }
   else
@@ -13967,12 +14079,8 @@ int vlistvarNewEntry(int vlistID)
       int i;
 
       vlistvarSize = 2*vlistvarSize;
-      vlistvar = (var_t *) realloc(vlistvar, vlistvarSize*sizeof(var_t));
-      if ( vlistvar == NULL )
-	{
-          Message("vlistvarSize = %d", vlistvarSize);
-	  SysError("Reallocation of var_t failed");
-	}
+      vlistvar = (var_t *)xrealloc(vlistvar,
+                                   (size_t)vlistvarSize * sizeof(var_t));
       varID = vlistvarSize/2;
 
       for ( i = varID; i < vlistvarSize; i++ )
@@ -13992,9 +14100,7 @@ int vlistvarNewEntry(int vlistID)
 static
 void vlistCheckVarID(const char *caller, int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr == NULL )
     Errorc("vlist undefined!");
@@ -14044,21 +14150,11 @@ vlistDestroy(vlistID);
 */
 int vlistDefVar(int vlistID, int gridID, int zaxisID, int tsteptype)
 {
-  int varID;
-  int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return CDI_UNDEFID;
-    }
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   if ( CDI_Debug )
     Message("gridID = %d  zaxisID = %d  tsteptype = %d", gridID, zaxisID, tsteptype);
 
-  varID = vlistvarNewEntry(vlistID);
+  int varID = vlistvarNewEntry(vlistID);
 
   vlistptr->nvars++;
 
@@ -14072,32 +14168,11 @@ int vlistDefVar(int vlistID, int gridID, int zaxisID, int tsteptype)
       vlistptr->vars[varID].tsteptype = TSTEP_INSTANT;
     }
 
-  for ( index = 0; index < vlistptr->ngrids; index++ )
-    if ( gridID == vlistptr->gridIDs[index] ) break;
-
-  if ( index == vlistptr->ngrids )
-    {
-      if ( vlistptr->ngrids + 1 >= MAX_GRIDS_PS )
-	Error("Maximum of %d grids reached", MAX_GRIDS_PS);
-
-      vlistptr->gridIDs[vlistptr->ngrids] = gridID;
-      vlistptr->ngrids++;
-    }
-
-  for ( index = 0; index < vlistptr->nzaxis; index++ )
-    if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
-
-  if ( index == vlistptr->nzaxis )
-    {
-      if ( vlistptr->nzaxis + 1 >= MAX_ZAXES_PS )
-	Error("Maximum of %d zaxis reached", MAX_ZAXES_PS);
-
-      vlistptr->zaxisIDs[vlistptr->nzaxis] = zaxisID;
-      vlistptr->nzaxis++;
-    }
+  vlistAdd2GridIDs(vlistptr, gridID);
+  vlistAdd2ZaxisIDs(vlistptr, zaxisID);
 
   vlistptr->vars[varID].param = cdiEncodeParam(-(varID + 1), 255, 255);
-
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
   return (varID);
 }
 
@@ -14107,12 +14182,13 @@ cdiVlistCreateVarLevInfo(vlist_t *vlistptr, int varID)
   xassert(varID >= 0 && varID < vlistptr->nvars
           && vlistptr->vars[varID].levinfo == NULL);
   int zaxisID = vlistptr->vars[varID].zaxisID;
-  int nlevs = zaxisInqSize(zaxisID);
+  size_t nlevs = (size_t)zaxisInqSize(zaxisID);
 
-  vlistptr->vars[varID].levinfo = (levinfo_t*) malloc(nlevs * sizeof(levinfo_t));
+  vlistptr->vars[varID].levinfo
+    = (levinfo_t*)xmalloc((size_t)nlevs * sizeof(levinfo_t));
 
-  for (int levID = 0; levID < nlevs; levID++ )
-      vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+  for (size_t levID = 0; levID < nlevs; levID++ )
+    vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO((int)levID);
 }
 
 /*
@@ -14132,19 +14208,15 @@ The function @func{vlistDefVarParam} defines the parameter number of a variable.
 */
 void vlistDefVarParam(int vlistID, int varID, int param)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].param != param)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].param = param;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].param = param;
 }
 
 /*
@@ -14164,32 +14236,25 @@ The function @func{vlistDefVarCode} defines the code number of a variable.
 */
 void vlistDefVarCode(int vlistID, int varID, int code)
 {
-  vlist_t *vlistptr;
-  int param, pnum, pcat, pdis;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int param = vlistptr->vars[varID].param;
+  int pnum, pcat, pdis;
+  cdiDecodeParam(param, &pnum, &pcat, &pdis);
+  int newParam = cdiEncodeParam(code, pcat, pdis);
+  if (vlistptr->vars[varID].param != newParam)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].param = newParam;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  param = vlistptr->vars[varID].param;
-
-  cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
-  vlistptr->vars[varID].param = cdiEncodeParam(code, pcat, pdis);
 }
 
 
 void vlistInqVar(int vlistID, int varID, int *gridID, int *zaxisID, int *tsteptype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14219,9 +14284,7 @@ The function @func{vlistInqVarGrid} returns the grid ID of a variable.
 */
 int vlistInqVarGrid(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14247,9 +14310,7 @@ The function @func{vlistInqVarZaxis} returns the zaxis ID of a variable.
 */
 int vlistInqVarZaxis(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14275,16 +14336,11 @@ The function @func{vlistInqVarParam} returns the parameter number of a variable.
 */
 int vlistInqVarParam(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int param;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  param = vlistptr->vars[varID].param;
-
-  return (param);
+  return (vlistptr->vars[varID].param);
 }
 
 /*
@@ -14306,18 +14362,14 @@ The function @func{vlistInqVarCode} returns the code number of a variable.
 */
 int vlistInqVarCode(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int param, code = -varID-1;
-  int pdis, pcat, pnum;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  param = vlistptr->vars[varID].param;
+  int param = vlistptr->vars[varID].param;
+  int pdis, pcat, pnum;
   cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
-  if ( pdis == 255 ) code = pnum;
+  int code = pdis == 255 ? pnum : -varID-1;
 
   if ( code < 0 && vlistptr->vars[varID].tableID != -1 && vlistptr->vars[varID].name != NULL )
     {
@@ -14330,9 +14382,7 @@ int vlistInqVarCode(int vlistID, int varID)
 
 const char *vlistInqVarNamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14342,9 +14392,7 @@ const char *vlistInqVarNamePtr(int vlistID, int varID)
 
 const char *vlistInqVarLongnamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14354,9 +14402,7 @@ const char *vlistInqVarLongnamePtr(int vlistID, int varID)
 
 const char *vlistInqVarStdnamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14366,9 +14412,7 @@ const char *vlistInqVarStdnamePtr(int vlistID, int varID)
 
 const char *vlistInqVarUnitsPtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14383,7 +14427,7 @@ const char *vlistInqVarUnitsPtr(int vlistID, int varID)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  name     Returned variable name. The caller must allocate space for the 
+    @Item  name     Returned variable 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 @func{CDI_MAX_NAME}.
 
@@ -14398,23 +14442,19 @@ otherwise the result is an empty string.
 */
 void vlistInqVarName(int vlistID, int varID, char *name)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   if ( vlistptr->vars[varID].name == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+	  int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParName(tableID, code, name) != 0 )
 	    sprintf(name, "var%d", code);
 	}
@@ -14422,7 +14462,7 @@ void vlistInqVarName(int vlistID, int varID, char *name)
 	{
 	  sprintf(name, "param%d.%d.%d", pnum, pcat, pdis);
 	}
-    }  
+    }
   else
     strcpy(name, vlistptr->vars[varID].name);
 
@@ -14437,7 +14477,7 @@ void vlistInqVarName(int vlistID, int varID, char *name)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  longname Long name of the variable. The caller must allocate space for the 
+    @Item  longname Long name of the variable. The caller must allocate space for the
                     returned string. The maximum possible length, in characters, of
                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
 
@@ -14452,12 +14492,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarLongname(int vlistID, int varID, char *longname)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14465,16 +14500,17 @@ void vlistInqVarLongname(int vlistID, int varID, char *longname)
 
   if ( vlistptr->vars[varID].longname == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+          int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParLongname(tableID, code, longname) != 0 )
 	    longname[0] = '\0';
 	}
-    }  
+    }
   else
     strcpy(longname, vlistptr->vars[varID].longname);
 
@@ -14489,7 +14525,7 @@ void vlistInqVarLongname(int vlistID, int varID, char *longname)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  stdname  Standard name of the variable. The caller must allocate space for the 
+    @Item  stdname  Standard name of the variable. The caller must allocate space for the
                     returned string. The maximum possible length, in characters, of
                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
 
@@ -14504,9 +14540,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarStdname(int vlistID, int varID, char *stdname)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14543,12 +14577,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarUnits(int vlistID, int varID, char *units)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14556,12 +14585,13 @@ void vlistInqVarUnits(int vlistID, int varID, char *units)
 
   if ( vlistptr->vars[varID].units == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+	  int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParUnits(tableID, code, units) != 0 )
 	    units[0] = '\0';
 	}
@@ -14575,15 +14605,12 @@ void vlistInqVarUnits(int vlistID, int varID, char *units)
 /* used in MPIOM ! */
 int vlistInqVarID(int vlistID, int code)
 {
-  int varID;
-  vlist_t *vlistptr;
-  int param, pdis, pcat, pnum;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  for ( varID = 0; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pnum == code ) return (varID);
     }
@@ -14594,20 +14621,17 @@ int vlistInqVarID(int vlistID, int code)
 
 int vlistInqVarSize(int vlistID, int varID)
 {
-  int size;
-  int zaxisID, gridID;
-  int nlevs, gridsize;
-  int tsteptype;
-
   vlistCheckVarID(__func__, vlistID, varID);
 
+  int zaxisID, gridID;
+  int tsteptype;
   vlistInqVar(vlistID, varID, &gridID, &zaxisID, &tsteptype);
 
-  nlevs = zaxisInqSize(zaxisID);
+  int nlevs = zaxisInqSize(zaxisID);
 
-  gridsize = gridInqSize(gridID);
+  int gridsize = gridInqSize(gridID);
 
-  size = gridsize*nlevs;
+  int size = gridsize*nlevs;
 
   return (size);
 }
@@ -14634,9 +14658,7 @@ The valid CDI data types are @func{DATATYPE_PACK8}, @func{DATATYPE_PACK16}, @fun
 */
 int vlistInqVarDatatype(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14646,13 +14668,11 @@ int vlistInqVarDatatype(int vlistID, int varID)
 
 int vlistInqVarNumber(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int number = CDI_REAL;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
+  int number = CDI_REAL;
   if ( vlistptr->vars[varID].datatype == DATATYPE_CPX32 ||
        vlistptr->vars[varID].datatype == DATATYPE_CPX64 )
     number = CDI_COMP;
@@ -14680,123 +14700,88 @@ The function @func{vlistDefVarDatatype} defines the data type of a variable.
 */
 void vlistDefVarDatatype(int vlistID, int varID, int datatype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].datatype != datatype)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr->vars[varID].datatype = datatype;
+      vlistptr->vars[varID].datatype = datatype;
 
-  if ( vlistptr->vars[varID].missvalused == FALSE )
-    switch (datatype)
-      {
-      case DATATYPE_INT8:   vlistptr->vars[varID].missval = -SCHAR_MAX; break;
-      case DATATYPE_UINT8:  vlistptr->vars[varID].missval =  UCHAR_MAX; break;
-      case DATATYPE_INT16:  vlistptr->vars[varID].missval = -SHRT_MAX;  break;
-      case DATATYPE_UINT16: vlistptr->vars[varID].missval =  USHRT_MAX; break;
-      case DATATYPE_INT32:  vlistptr->vars[varID].missval = -INT_MAX;   break;
-      case DATATYPE_UINT32: vlistptr->vars[varID].missval =  UINT_MAX;  break;
-      }
+      if ( vlistptr->vars[varID].missvalused == FALSE )
+        switch (datatype)
+          {
+          case DATATYPE_INT8:   vlistptr->vars[varID].missval = -SCHAR_MAX; break;
+          case DATATYPE_UINT8:  vlistptr->vars[varID].missval =  UCHAR_MAX; break;
+          case DATATYPE_INT16:  vlistptr->vars[varID].missval = -SHRT_MAX;  break;
+          case DATATYPE_UINT16: vlistptr->vars[varID].missval =  USHRT_MAX; break;
+          case DATATYPE_INT32:  vlistptr->vars[varID].missval = -INT_MAX;   break;
+          case DATATYPE_UINT32: vlistptr->vars[varID].missval =  UINT_MAX;  break;
+          }
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistDefVarInstitut(int vlistID, int varID, int instID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].instID != instID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].instID = instID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].instID = instID;
 }
 
 
 int vlistInqVarInstitut(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].instID);
 }
 
 
 void vlistDefVarModel(int vlistID, int varID, int modelID)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].modelID != modelID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].modelID = modelID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].modelID = modelID;
 }
 
 
 int vlistInqVarModel(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].modelID);
 }
 
 
 void vlistDefVarTable(int vlistID, int varID, int tableID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].tableID != tableID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
+      vlistptr->vars[varID].tableID = tableID;
+      int tablenum = tableInqNum(tableID);
 
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].tableID = tableID;
-
-  {
-    int param, pnum, pcat, pdis;
-    int tablenum;
-    tablenum = tableInqNum(tableID);
+      int param = vlistptr->vars[varID].param;
 
-    param = vlistptr->vars[varID].param;
-
-    cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
-    vlistptr->vars[varID].param = cdiEncodeParam(pnum, tablenum, pdis);
-  }
+      int pnum, pcat, pdis;
+      cdiDecodeParam(param, &pnum, &pcat, &pdis);
+      vlistptr->vars[varID].param = cdiEncodeParam(pnum, tablenum, pdis);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarTable(int vlistID, int varID)
 {
-  int tableID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  tableID = vlistptr->vars[varID].tableID;
-
-  return (tableID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  return (vlistptr->vars[varID].tableID);
 }
 
 /*
@@ -14816,15 +14801,7 @@ The function @func{vlistDefVarName} defines the name of a variable.
 */
 void vlistDefVarName(int vlistID, int varID, const char *name)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14837,6 +14814,7 @@ void vlistDefVarName(int vlistID, int varID, const char *name)
 	}
 
       vlistptr->vars[varID].name = strdupx(name);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -14857,15 +14835,7 @@ The function @func{vlistDefVarLongname} defines the long name of a variable.
 */
 void vlistDefVarLongname(int vlistID, int varID, const char *longname)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14878,6 +14848,7 @@ void vlistDefVarLongname(int vlistID, int varID, const char *longname)
 	}
 
       vlistptr->vars[varID].longname = strdupx(longname);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -14898,15 +14869,7 @@ The function @func{vlistDefVarStdname} defines the standard name of a variable.
 */
 void vlistDefVarStdname(int vlistID, int varID, const char *stdname)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14919,6 +14882,7 @@ void vlistDefVarStdname(int vlistID, int varID, const char *stdname)
 	}
 
       vlistptr->vars[varID].stdname = strdupx(stdname);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -14939,15 +14903,7 @@ The function @func{vlistDefVarUnits} defines the units of a variable.
 */
 void vlistDefVarUnits(int vlistID, int varID, const char *units)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -14960,6 +14916,7 @@ void vlistDefVarUnits(int vlistID, int varID, const char *units)
 	}
 
       vlistptr->vars[varID].units = strdupx(units);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -14982,9 +14939,7 @@ The function @func{vlistInqVarMissval} returns the missing value of a variable.
 */
 double vlistInqVarMissval(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15008,9 +14963,7 @@ The function @func{vlistDefVarMissval} defines the missing value of a variable.
 */
 void vlistDefVarMissval(int vlistID, int varID, double missval)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15035,15 +14988,7 @@ The function @func{vlistDefVarExtra} defines the extra information of a variable
 */
 void vlistDefVarExtra(int vlistID, int varID, const char *extra)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15056,6 +15001,7 @@ void vlistDefVarExtra(int vlistID, int varID, const char *extra)
 	}
 
       vlistptr->vars[varID].extra = strdupx(extra);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -15082,9 +15028,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarExtra(int vlistID, int varID, char *extra)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15099,9 +15043,7 @@ void vlistInqVarExtra(int vlistID, int varID, char *extra)
 
 int vlistInqVarValidrange(int vlistID, int varID, double *validrange)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15117,29 +15059,20 @@ int vlistInqVarValidrange(int vlistID, int varID, double *validrange)
 
 void vlistDefVarValidrange(int vlistID, int varID, const double *validrange)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   vlistptr->vars[varID].validrange[0] = validrange[0];
   vlistptr->vars[varID].validrange[1] = validrange[1];
   vlistptr->vars[varID].lvalidrange = TRUE;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 double vlistInqVarScalefactor(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return 1.0;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15149,232 +15082,195 @@ double vlistInqVarScalefactor(int vlistID, int varID)
 
 double vlistInqVarAddoffset(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   return (vlistptr->vars[varID].addoffset);
 }
 
+
 void vlistDefVarScalefactor(int vlistID, int varID, double scalefactor)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].scalefactor = scalefactor;
+  if ( IS_NOT_EQUAL(vlistptr->vars[varID].scalefactor, scalefactor) )
+    {
+      vlistptr->vars[varID].scalefactor = scalefactor;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistDefVarAddoffset(int vlistID, int varID, double addoffset)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].addoffset = addoffset;
+  if ( IS_NOT_EQUAL(vlistptr->vars[varID].addoffset, addoffset))
+    {
+      vlistptr->vars[varID].addoffset = addoffset;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].tsteptype != tsteptype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].tsteptype = tsteptype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].tsteptype = tsteptype;
 }
 
 
 int vlistInqVarTsteptype(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].tsteptype);
 }
 
 
 void vlistDefVarTimave(int vlistID, int varID, int timave)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].timave != timave)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].timave = timave;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].timave = timave;
 }
 
 
 int vlistInqVarTimave(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].timave);
 }
 
 
 void vlistDefVarTimaccu(int vlistID, int varID, int timaccu)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].timaccu != timaccu)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].timaccu = timaccu;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].timaccu = timaccu;
 }
 
 
 int vlistInqVarTimaccu(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].timaccu);
 }
 
 
 void vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGeneratingProcess)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].typeOfGeneratingProcess != typeOfGeneratingProcess)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].typeOfGeneratingProcess = typeOfGeneratingProcess;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].typeOfGeneratingProcess = typeOfGeneratingProcess;
 }
 
 
 int vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  return (vlistptr->vars[varID].typeOfGeneratingProcess);
+}
 
-  vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->vars[varID].typeOfGeneratingProcess);
+void vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDefinitionTemplate)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  if (vlistptr->vars[varID].productDefinitionTemplate != productDefinitionTemplate)
+    {
+      vlistptr->vars[varID].productDefinitionTemplate = productDefinitionTemplate;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
-void vlistDestroyVarName(int vlistID, int varID)
+int vlistInqVarProductDefinitionTemplate(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  return (vlistptr->vars[varID].productDefinitionTemplate);
+}
 
-  vlistptr = vlist_to_pointer(vlistID);
 
+void vlistDestroyVarName(int vlistID, int varID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   if ( vlistptr->vars[varID].name )
     {
       free(vlistptr->vars[varID].name);
       vlistptr->vars[varID].name = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarLongname(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].longname )
     {
       free(vlistptr->vars[varID].longname);
       vlistptr->vars[varID].longname = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarStdname(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].stdname )
     {
       free(vlistptr->vars[varID].stdname);
       vlistptr->vars[varID].stdname = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarUnits(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].units )
     {
       free(vlistptr->vars[varID].units);
       vlistptr->vars[varID].units = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 int vlistInqVarMissvalUsed(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].missvalused);
 }
 
 
 void vlistDefFlag(int vlistID, int varID, int levID, int flag)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   levinfo_t li = DEFAULT_LEVINFO(levID);
   if (vlistptr->vars[varID].levinfo)
@@ -15397,14 +15293,14 @@ void vlistDefFlag(int vlistID, int varID, int levID, int flag)
           break;
         }
     }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqFlag(int vlistID, int varID, int levID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return (vlistptr->vars[varID].levinfo[levID].flag);
@@ -15419,9 +15315,7 @@ int vlistInqFlag(int vlistID, int varID, int levID)
 int vlistFindVar(int vlistID, int fvarID)
 {
   int varID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   for ( varID = 0; varID < vlistptr->nvars; varID++ )
     {
@@ -15440,13 +15334,10 @@ int vlistFindVar(int vlistID, int fvarID)
 
 int vlistFindLevel(int vlistID, int fvarID, int flevelID)
 {
-  int varID;
   int levelID = -1;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  varID = vlistFindVar(vlistID, fvarID);
+  int varID = vlistFindVar(vlistID, fvarID);
 
   if ( varID != -1 )
     {
@@ -15470,19 +15361,14 @@ int vlistFindLevel(int vlistID, int fvarID, int flevelID)
 
 int vlistMergedVar(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].mvarID);
 }
 
 
 int vlistMergedLevel(int vlistID, int varID, int levelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return vlistptr->vars[varID].levinfo[levelID].mlevelID;
@@ -15496,15 +15382,7 @@ int vlistMergedLevel(int vlistID, int varID, int levelID)
 
 void vlistDefIndex(int vlistID, int varID, int levelID, int index)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   levinfo_t li = DEFAULT_LEVINFO(levelID);
   if (vlistptr->vars[varID].levinfo)
@@ -15514,14 +15392,13 @@ void vlistDefIndex(int vlistID, int varID, int levelID, int index)
   else
     return;
   vlistptr->vars[varID].levinfo[levelID].index = index;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqIndex(int vlistID, int varID, int levelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return (vlistptr->vars[varID].levinfo[levelID].index);
@@ -15535,71 +15412,46 @@ int vlistInqIndex(int vlistID, int varID, int levelID)
 
 void vlistChangeVarZaxis(int vlistID, int varID, int zaxisID)
 {
-  int nlevs1, nlevs2;
-  int nvars, index;
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  nlevs1 = zaxisInqSize(vlistptr->vars[varID].zaxisID);
-  nlevs2 = zaxisInqSize(zaxisID);
+  int nlevs1 = zaxisInqSize(vlistptr->vars[varID].zaxisID);
+  int nlevs2 = zaxisInqSize(zaxisID);
 
   if ( nlevs1 != nlevs2 ) Error("Number of levels must not change!");
 
-  nvars = vlistptr->nvars;
-  for ( index = 0; index < nvars; index++ )
-    if ( index != varID )
-      if ( vlistptr->vars[index].zaxisID == vlistptr->vars[varID].zaxisID ) break;
+  int nvars = vlistptr->nvars;
+  int found = 0;
+  int oldZaxisID = vlistptr->vars[varID].zaxisID;
+  for ( int i = 0; i < varID; ++i)
+    found |= (vlistptr->vars[i].zaxisID == oldZaxisID);
+  for ( int i = varID + 1; i < nvars; ++i)
+    found |= (vlistptr->vars[i].zaxisID == oldZaxisID);
 
-  if ( index == nvars )
+  if (found)
     {
-      for ( index = 0; index < vlistptr->nzaxis; index++ )
-	if ( vlistptr->zaxisIDs[index] == vlistptr->vars[varID].zaxisID )
-	  vlistptr->zaxisIDs[index] = zaxisID;
+      int nzaxis = vlistptr->nzaxis;
+      for (int i = 0; i < nzaxis; ++i)
+	if (vlistptr->zaxisIDs[i] == oldZaxisID )
+	  vlistptr->zaxisIDs[i] = zaxisID;
     }
   else
-    {
-      for ( index = 0; index < vlistptr->nzaxis; index++ )
-	if ( vlistptr->zaxisIDs[index] == zaxisID ) break;
-
-      if ( index == vlistptr->nzaxis )
-	{
-	  if ( vlistptr->nzaxis + 1 >= MAX_ZAXES_PS )
-	    Error("Maximum of %d zaxis reached", MAX_ZAXES_PS);
+    vlistAdd2ZaxisIDs(vlistptr, zaxisID);
 
-	  vlistptr->zaxisIDs[vlistptr->nzaxis] = zaxisID;
-	  vlistptr->nzaxis++;
-	}
-    }
-  
   vlistptr->vars[varID].zaxisID = zaxisID;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 void vlistChangeVarGrid(int vlistID, int varID, int gridID)
 {
-  int nvars, index;
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  nvars = vlistptr->nvars;
+  int nvars = vlistptr->nvars;
+  int index;
   for ( index = 0; index < nvars; index++ )
     if ( index != varID )
       if ( vlistptr->vars[index].gridID == vlistptr->vars[varID].gridID ) break;
@@ -15611,47 +15463,30 @@ void vlistChangeVarGrid(int vlistID, int varID, int gridID)
 	  vlistptr->gridIDs[index] = gridID;
     }
   else
-    {
-      for ( index = 0; index < vlistptr->ngrids; index++ )
-	if ( vlistptr->gridIDs[index] == gridID ) break;
-
-      if ( index == vlistptr->ngrids )
-	{
-	  if ( vlistptr->ngrids + 1 >= MAX_GRIDS_PS )
-	    Error("Maximum of %d grids reached", MAX_GRIDS_PS);
+    vlistAdd2GridIDs(vlistptr, gridID);
 
-	  vlistptr->gridIDs[vlistptr->ngrids] = gridID;
-	  vlistptr->ngrids++;
-	}
-    }
-  
   vlistptr->vars[varID].gridID = gridID;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 void vlistDefVarCompType(int vlistID, int varID, int comptype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].comptype != comptype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].comptype = comptype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].comptype = comptype;
 }
 
 
 int vlistInqVarCompType(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15661,27 +15496,21 @@ int vlistInqVarCompType(int vlistID, int varID)
 
 void vlistDefVarCompLevel(int vlistID, int varID, int complevel)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].complevel = complevel;
+  if (vlistptr->vars[varID].complevel != complevel)
+    {
+      vlistptr->vars[varID].complevel = complevel;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarCompLevel(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15691,33 +15520,46 @@ int vlistInqVarCompLevel(int vlistID, int varID)
 
 void  vlistDefVarChunkType(int vlistID, int varID, int chunktype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].chunktype = chunktype;
+  if (vlistptr->vars[varID].chunktype != chunktype)
+    {
+      vlistptr->vars[varID].chunktype = chunktype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarChunkType(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   return (vlistptr->vars[varID].chunktype);
 }
 
+static
+int vlistEncodeXyz(int (*dimorder)[3])
+{
+  return (*dimorder)[0]*100 + (*dimorder)[1]*10 + (*dimorder)[2];
+}
+
 
-void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
+static
+void vlistDecodeXyz(int xyz, int (*outDimorder)[3])
 {
-  vlist_t *vlistptr;
+  (*outDimorder)[0] = xyz/100, xyz -= (*outDimorder)[0]*100;
+  (*outDimorder)[1] = xyz/10, xyz -= (*outDimorder)[1]*10;
+  (*outDimorder)[2] = xyz;
+}
 
-  vlistptr = vlist_to_pointer(vlistID);
+
+void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15726,32 +15568,36 @@ void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
   /* check xyz dimension order */
   {
     int dimorder[3];
+    vlistDecodeXyz(xyz, &dimorder);
     int dimx = 0, dimy = 0, dimz = 0;
-    dimorder[0] = xyz/100;
-    dimorder[1] = (xyz-dimorder[0]*100)/10;
-    dimorder[2] = (xyz-dimorder[0]*100-dimorder[1]*10);
     for ( int id = 0; id < 3; ++id )
       {
-        if      ( dimorder[id] == 3 ) { dimz++; }
-        else if ( dimorder[id] == 2 ) { dimy++; }
-        else if ( dimorder[id] == 1 ) { dimx++; }
-      }
+        switch ( dimorder[id] )
+          {
+            case 1: dimx++; break;
+            case 2: dimy++; break;
+            case 3: dimz++; break;
+            default: dimorder[id] = 0; break;    //Ensure that we assign a valid dimension to this position.
+          }
+     }
     if ( dimz > 1 || dimy > 1 || dimx > 1 ) xyz = 321; // ZYX
     else
       {
-        int lchanged = 0;
-        if ( dimz == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 3; lchanged++; break;}
-        if ( dimy == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 2; lchanged++; break;}
-        if ( dimx == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 1; lchanged++; break;}
-        if ( lchanged ) xyz = dimorder[0]*100 + dimorder[1]*10 + dimorder[2];
+        if ( dimz == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 3; break;}
+        if ( dimy == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 2; break;}
+        if ( dimx == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 1; break;}
+        xyz = vlistEncodeXyz(&dimorder);
       }
   }
 
+  assert(xyz == 123 || xyz == 312 || xyz == 231 || xyz == 321 || xyz == 132 || xyz == 213);
+
   vlistptr->vars[varID].xyz = xyz;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
-int vlistInqVarXYZ(int vlistID, int varID)
+void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3])
 {
   vlist_t *vlistptr;
 
@@ -15759,34 +15605,41 @@ int vlistInqVarXYZ(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].xyz);
+  vlistDecodeXyz(vlistptr->vars[varID].xyz, outDimorder);
 }
 
 
+int vlistInqVarXYZ(int vlistID, int varID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlistCheckVarID(__func__, vlistID, varID);
+
+  return (vlistptr->vars[varID].xyz);
+}
+
 /* Ensemble Info Routines */
 void vlistDefVarEnsemble(int vlistID, int varID, int ensID, int ensCount, int forecast_type )
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   if ( vlistptr->vars[varID].ensdata == NULL )
-    vlistptr->vars[varID].ensdata = (ensinfo_t *) malloc( sizeof( ensinfo_t ) );
+    vlistptr->vars[varID].ensdata
+      = (ensinfo_t *)xmalloc( sizeof( ensinfo_t ) );
 
   vlistptr->vars[varID].ensdata->ens_index          = ensID;
   vlistptr->vars[varID].ensdata->ens_count          = ensCount;
   vlistptr->vars[varID].ensdata->forecast_init_type = forecast_type;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int *forecast_type )
 {
-  vlist_t *vlistptr;
   int status = 0;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15810,17 +15663,35 @@ int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int
 void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  int idx;
 
-  int idx = vlistptr->vars[varID].opt_grib_int_nentries;
-  vlistptr->vars[varID].opt_grib_int_nentries++;
-  if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
-  vlistptr->vars[varID].opt_grib_int_val[idx] = value;
-  if ( name )
-    vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(name);
+  if ( !vlistptr->locked )
+    Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
+          "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+
+  for ( idx=0; idx<vlistptr->vars[varID].opt_grib_int_nentries; idx++)
+    if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[idx]) == 0 ) break;
+
+  if ( idx < vlistptr->vars[varID].opt_grib_int_nentries )
+    {
+      vlistptr->vars[varID].opt_grib_int_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
+    }
   else
-    Error("Internal error!");
+    {
+      idx = vlistptr->vars[varID].opt_grib_int_nentries;
+      vlistptr->vars[varID].opt_grib_int_nentries++;
+      if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
+      vlistptr->vars[varID].opt_grib_int_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
+      if ( name )
+        vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(name);
+      else
+        Error("Internal error, name undefined!");
+    }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 #endif
 }
 
@@ -15828,17 +15699,35 @@ void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
 void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  int idx;
 
-  int idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
-  vlistptr->vars[varID].opt_grib_dbl_nentries++;
-  if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
-  vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
-  if ( name )
-    vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(name);
+  if ( !vlistptr->locked )
+    Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
+          "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+
+  for ( idx=0; idx<vlistptr->vars[varID].opt_grib_dbl_nentries; idx++)
+    if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[idx]) == 0 ) break;
+
+  if ( idx < vlistptr->vars[varID].opt_grib_dbl_nentries )
+    {
+      vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
+    }
   else
-    Error("Internal error!");
+    {
+      idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
+      vlistptr->vars[varID].opt_grib_dbl_nentries++;
+      if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
+      vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
+      if ( name )
+        vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(name);
+      else
+        Error("Internal error, name undefined!");
+    }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 #endif
 }
 
@@ -15850,8 +15739,7 @@ void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
 void cdiClearAdditionalKeys()
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  int i;
-  for (i=0; i<cdiNAdditionalGRIBKeys; i++)  free(cdiAdditionalGRIBKeys[i]);
+  for (int i=0; i<cdiNAdditionalGRIBKeys; i++)  free(cdiAdditionalGRIBKeys[i]);
   cdiNAdditionalGRIBKeys = 0;
 #endif
 }
@@ -15875,17 +15763,15 @@ int vlistHasVarKey(int vlistID, int varID, const char* name)
 {
 #if  defined  (HAVE_LIBGRIB_API)
   /* check if the GRIB key was previously read and is stored */
-  vlist_t *vlistptr;
-  int      i;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
     {
       if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[i]) == 0 )
 	return 1;
     }
 
-  for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
     {
       if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[i]) == 0 )
 	return 1;
@@ -15899,13 +15785,10 @@ double vlistInqVarDblKey(int vlistID, int varID, const char* name)
 {
   double value = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  /* check if the GRIB key was previously read and is stored in
-     "opt_grib_dbl_val" */
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  /* check if the GRIB key was previously read and is stored in "opt_grib_dbl_val" */
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  int i;
-  for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
     if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[i]) == 0 )
       return vlistptr->vars[varID].opt_grib_dbl_val[i];
 #endif
@@ -15918,13 +15801,10 @@ int vlistInqVarIntKey(int vlistID, int varID, const char* name)
 {
   long int value = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  /* check if the GRIB key was previously read and is stored in
-     "opt_grib_int_val" */
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  /* check if the GRIB key was previously read and is stored in "opt_grib_int_val" */
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  int i;
-  for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
     if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[i]) == 0 )
       return vlistptr->vars[varID].opt_grib_int_val[i];
 #endif
@@ -15932,29 +15812,23 @@ int vlistInqVarIntKey(int vlistID, int varID, const char* name)
 }
 
 
-void     vlistDefVarIOrank   ( int vlistID, int varID, int iorank )
+void vlistDefVarIOrank(int vlistID, int varID, int iorank)
 {
-  vlist_t * vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID );
+  vlist_t *vlistptr = vlist_to_pointer(vlistID );
 
   vlistCheckVarID ( __func__, vlistID, varID );
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].iorank != iorank)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].iorank = iorank;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].iorank = iorank;
 }
 
 
 int vlistInqVarIOrank(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -15969,6 +15843,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
           && varIDB >= 0 && varIDB < b->nvars);
   var_t *pva = a->vars + varIDA, *pvb = b->vars + varIDB;
 #define FCMP(f) ((pva->f) != (pvb->f))
+#define FCMPFLT(f) (IS_NOT_EQUAL((pva->f), (pvb->f)))
 #define FCMPSTR(fs) ((pva->fs) != (pvb->fs) && strcmp((pva->fs), (pvb->fs)))
 #define FCMP2(f) (namespaceResHDecode(pva->f).idx       \
                   != namespaceResHDecode(pvb->f).idx)
@@ -15976,28 +15851,29 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
     | FCMP(datatype) | FCMP(tsteptype) | FCMP(timave) | FCMP(timaccu)
     | FCMP(chunktype) | FCMP(xyz) | FCMP2(gridID) | FCMP2(zaxisID)
     | FCMP2(instID) | FCMP2(modelID) | FCMP2(tableID) | FCMP(missvalused)
-    | FCMP(missval) | FCMP(addoffset) | FCMP(scalefactor) | FCMPSTR(name)
+    | FCMPFLT(missval) | FCMPFLT(addoffset) | FCMPFLT(scalefactor) | FCMPSTR(name)
     | FCMPSTR(longname) | FCMPSTR(stdname) | FCMPSTR(units) | FCMPSTR(extra)
     | FCMP(comptype) | FCMP(complevel) | FCMP(lvalidrange)
-    | FCMP(validrange[0]) | FCMP(validrange[1]);
+    | FCMPFLT(validrange[0]) | FCMPFLT(validrange[1]);
 #undef FCMP
+#undef FCMPFLT
 #undef FCMP2
   if ((diff |= ((pva->levinfo == NULL) ^ (pvb->levinfo == NULL))))
     return 1;
   if (pva->levinfo)
     {
       int zaxisID = pva->zaxisID;
-      int nlevs = zaxisInqSize(zaxisID);
+      size_t nlevs = (size_t)zaxisInqSize(zaxisID);
       diff |= (memcmp(pva->levinfo, pvb->levinfo, sizeof (levinfo_t) * nlevs)
                != 0);
       if (diff)
         return 1;
     }
-  int natts = a->vars[varIDA].atts.nelems;
+  size_t natts = a->vars[varIDA].atts.nelems;
   if (natts != b->vars[varIDB].atts.nelems)
     return 1;
-  for (int attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, varIDA, b, varIDB, attID);
+  for (size_t attID = 0; attID < natts; ++attID)
+    diff |= vlist_att_compare(a, varIDA, b, varIDB, (int)attID);
   if ((diff |= ((pva->ensdata == NULL) ^ (pvb->ensdata == NULL))))
     return 1;
   if (pva->ensdata)
@@ -16018,13 +15894,13 @@ int vlistVarGetPackSize(vlist_t *p, int varID, void *context)
   int varsize = serializeGetSize(vlistvar_nints, DATATYPE_INT, context)
     + serializeGetSize(vlistvar_ndbls, DATATYPE_FLT64, context);
   if (var->name)
-    varsize += serializeGetSize(strlen(var->name), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->name), DATATYPE_TXT, context);
   if (var->longname)
-    varsize += serializeGetSize(strlen(var->longname), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->longname), DATATYPE_TXT, context);
   if (var->stdname)
-    varsize += serializeGetSize(strlen(var->stdname), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->stdname), DATATYPE_TXT, context);
   if (var->units)
-    varsize += serializeGetSize(strlen(var->units), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->units), DATATYPE_TXT, context);
   varsize += serializeGetSize(4 * zaxisInqSize(var->zaxisID),
                               DATATYPE_INT, context);
   varsize += vlistAttsGetSize(p, varID, context);
@@ -16042,10 +15918,10 @@ void vlistVarPack(vlist_t *p, int varID, char * buf, int size, int *position,
   tempbuf[1] = var->gridID;
   tempbuf[2] = var->zaxisID;
   tempbuf[3] = var->tsteptype;
-  tempbuf[4] = namesz = var->name?strlen(var->name):0;
-  tempbuf[5] = longnamesz = var->longname?strlen(var->longname):0;
-  tempbuf[6] = stdnamesz = var->stdname?strlen(var->stdname):0;
-  tempbuf[7] = unitssz = var->units?strlen(var->units):0;
+  tempbuf[4] = namesz = var->name?(int)strlen(var->name):0;
+  tempbuf[5] = longnamesz = var->longname?(int)strlen(var->longname):0;
+  tempbuf[6] = stdnamesz = var->stdname?(int)strlen(var->stdname):0;
+  tempbuf[7] = unitssz = var->units?(int)strlen(var->units):0;
   tempbuf[8] = var->datatype;
   tempbuf[9] = var->param;
   tempbuf[10] = var->instID;
@@ -16105,7 +15981,6 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
 {
   double dtempbuf[vlistvar_ndbls];
   int tempbuf[vlistvar_nints];
-  int newvar;
   char *varname = NULL;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
   serializeUnpack(buf, size, position,
@@ -16113,13 +15988,14 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
   serializeUnpack(buf, size, position,
                   dtempbuf, vlistvar_ndbls, DATATYPE_FLT64, context);
 
-  newvar = vlistDefVar ( vlistID,
+  int newvar = vlistDefVar ( vlistID,
 			 namespaceAdaptKey ( tempbuf[1], originNamespace ),
 			 namespaceAdaptKey ( tempbuf[2], originNamespace ),
 			 tempbuf[3]);
   if (tempbuf[4] || tempbuf[5] || tempbuf[6] || tempbuf[7])
-    varname = (char*) xmalloc(imax(imax(imax(tempbuf[4],tempbuf[5]),tempbuf[6]),
-                           tempbuf[7])+ 1);
+    varname = (char *)xmalloc((size_t)imax(imax(imax(tempbuf[4],tempbuf[5]),
+                                                tempbuf[6]),
+                                           tempbuf[7]) + 1);
   if (tempbuf[4])
   {
     serializeUnpack(buf, size, position,
@@ -16148,7 +16024,7 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
     varname[tempbuf[7]] = '\0';
     vlistDefVarUnits(vlistID, newvar, varname);
   }
-  if ( varname ) free ( varname );
+  free(varname);
   vlistDefVarDatatype(vlistID, newvar, tempbuf[8]);
   vlistDefVarInstitut ( vlistID, newvar,
 			namespaceAdaptKey ( tempbuf[10], originNamespace ));
@@ -16214,11 +16090,12 @@ void basetimeInit(basetime_t *basetime)
   if ( basetime == NULL )
     Error("Internal problem! Basetime not allocated.");
 
-  (*basetime).ncvarid       = UNDEFID;
-  (*basetime).ncdimid       = UNDEFID;
-  (*basetime).ncvarboundsid = UNDEFID;
-  (*basetime).leadtimeid    = UNDEFID;
-  (*basetime).lwrf          = 0;
+  basetime->ncvarid       = UNDEFID;
+  basetime->ncdimid       = UNDEFID;
+  basetime->ncvarboundsid = UNDEFID;
+  basetime->leadtimeid    = UNDEFID;
+  basetime->lwrf          = 0;
+  basetime->timevar_cache = NULL;
 }
 /*
  * Local Variables:
@@ -16240,10 +16117,9 @@ void basetimeInit(basetime_t *basetime)
 
 
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
-
-#define SRV_HEADER_LEN    8
+enum {
+  SRV_HEADER_LEN = 8,
+};
 
 
 static int initSrvLib      = 0;
@@ -16376,7 +16252,8 @@ int srvCheckFiletype(int fileID, int *swap)
   size_t sblocklen = 0;
   size_t data = 0;
   size_t dimx = 0, dimy = 0;
-  int fact = 0, found = 0;
+  size_t fact = 0;
+  int found = 0;
   unsigned char buffer[72], *pbuf;
 
   if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
@@ -16459,8 +16336,8 @@ int srvDefHeader(srvrec_t *srvp, const int *header)
 
   for ( i = 0; i < SRV_HEADER_LEN; i++ )
     srvp->header[i] = header[i];
-  
-  srvp->datasize = header[4]*header[5];
+
+  srvp->datasize = (size_t)(header[4] * header[5]);
 
   if ( SRV_Debug )
     Message("datasize = %lu", srvp->datasize);
@@ -16569,8 +16446,8 @@ int srvDefData(srvrec_t *srvp, int prec, const void *data)
 
   header = srvp->header;
 
-  datasize = header[4]*header[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)(header[4] * header[5]);
+  blocklen = datasize * (size_t)dprec;
 
   srvp->datasize = datasize;
 
@@ -16638,9 +16515,7 @@ int srvRead(int fileID, srvrec_t *srvp)
   size_t blocklen, blocklen2;
   size_t i;
   char tempheader[64];
-  int hprec, dprec;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -16661,9 +16536,9 @@ int srvRead(int fileID, srvrec_t *srvp)
   if ( SRV_Debug )
     Message("blocklen = %lu", blocklen);
 
-  hprec = blocklen / SRV_HEADER_LEN;
+  size_t hprec = blocklen / SRV_HEADER_LEN;
 
-  srvp->hprec = hprec;
+  srvp->hprec = (int)hprec;
 
   switch ( hprec )
     {
@@ -16700,16 +16575,16 @@ int srvRead(int fileID, srvrec_t *srvp)
       if ( blocklen2 != 0 ) return (-1);
     }
 
-  srvp->datasize = srvp->header[4]*srvp->header[5];
+  srvp->datasize = (size_t)(srvp->header[4] * srvp->header[5]);
 
   if ( SRV_Debug )
     Message("datasize = %lu", srvp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = srvp->buffersize;
+  size_t buffersize = srvp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = srvp->buffer;
@@ -16722,9 +16597,9 @@ int srvRead(int fileID, srvrec_t *srvp)
 
   datasize = srvp->datasize;
 
-  dprec = blocklen / datasize;
+  size_t dprec = blocklen / datasize;
 
-  srvp->dprec = dprec;
+  srvp->dprec = (int)dprec;
 
   if ( dprec != SINGLE_PRECISION && dprec != DOUBLE_PRECISION )
     {
@@ -16746,7 +16621,7 @@ int srvRead(int fileID, srvrec_t *srvp)
 }
 
 
-int srvWrite(int fileID, srvrec_t *srvp)
+void srvWrite(int fileID, srvrec_t *srvp)
 {
   size_t datasize;
   size_t blocklen;
@@ -16762,7 +16637,7 @@ int srvWrite(int fileID, srvrec_t *srvp)
   header = srvp->header;
 
   /* write header record */
-  blocklen = SRV_HEADER_LEN * hprec;
+  blocklen = SRV_HEADER_LEN * (size_t)hprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -16795,8 +16670,8 @@ int srvWrite(int fileID, srvrec_t *srvp)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = header[4]*header[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)(header[4] * header[5]);
+  blocklen = datasize * (size_t)dprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -16824,8 +16699,6 @@ int srvWrite(int fileID, srvrec_t *srvp)
     }
 
   binWriteF77Block(fileID, byteswap, blocklen);
-
-  return (0);
 }
 /*
  * Local Variables:
@@ -16847,10 +16720,9 @@ int srvWrite(int fileID, srvrec_t *srvp)
 
 
 
-#define  SINGLE_PRECISION    4
-#define  DOUBLE_PRECISION    8
-
-#define  EXT_HEADER_LEN      4
+enum {
+  EXT_HEADER_LEN = 4,
+};
 
 
 static int initExtLib       = 0;
@@ -16874,7 +16746,7 @@ const char *extLibraryVersion(void)
 }
 
 
-int EXT_Debug = 0;    /* If set to 1, debugging */
+static int EXT_Debug = 0;    /* If set to 1, debugging */
 
 
 void extDebug(int debug)
@@ -16886,7 +16758,7 @@ void extDebug(int debug)
 }
 
 
-void extLibInit()
+static void extLibInit()
 {
   char *envString;
   char *envName = "EXT_PRECISION";
@@ -16978,11 +16850,11 @@ void extDelete(void *ext)
 
 int extCheckFiletype(int fileID, int *swap)
 {
-  size_t blocklen = 0;
+  size_t blocklen = 0, fact = 0;
   size_t sblocklen = 0;
   size_t data =  0;
   size_t dimxy = 0;
-  int fact = 0, found = 0;
+  int found = 0;
   unsigned char buffer[40], *pbuf;
 
   if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
@@ -17063,7 +16935,7 @@ int extDefHeader(void *ext, const int *header)
   for ( i = 0; i < EXT_HEADER_LEN; i++ )
     extp->header[i] = header[i];
 
-  extp->datasize = header[3];
+  extp->datasize = (size_t)header[3];
   if ( extp->number == EXT_COMP ) extp->datasize *= 2;
 
   if ( EXT_Debug ) Message("datasize = %lu", extp->datasize);
@@ -17072,9 +16944,8 @@ int extDefHeader(void *ext, const int *header)
 }
 
 
-int extInqData(void *ext, int prec, void *data)
+static int extInqData(extrec_t *extp, int prec, void *data)
 {
-  extrec_t *extp = (extrec_t *) ext;
   size_t datasize;
   size_t i;
   int ierr = 0;
@@ -17165,9 +17036,9 @@ int extDefData(void *ext, int prec, const void *data)
 
   header = extp->header;
 
-  datasize = header[3];
+  datasize = (size_t)header[3];
   if ( extp->number == EXT_COMP ) datasize *= 2;
-  blocklen = datasize * rprec;
+  blocklen = datasize * (size_t)rprec;
 
   extp->datasize = datasize;
 
@@ -17235,9 +17106,7 @@ int extRead(int fileID, void *ext)
   size_t blocklen, blocklen2;
   size_t i;
   char tempheader[32];
-  int hprec, dprec;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -17258,9 +17127,9 @@ int extRead(int fileID, void *ext)
   if ( EXT_Debug )
     Message("blocklen = %lu", blocklen);
 
-  hprec = blocklen / EXT_HEADER_LEN;
+  size_t hprec = blocklen / EXT_HEADER_LEN;
 
-  extp->prec = hprec;
+  extp->prec = (int)hprec;
 
   switch ( hprec )
     {
@@ -17297,15 +17166,15 @@ int extRead(int fileID, void *ext)
       if ( blocklen2 != 0 ) return (-1);
     }
 
-  extp->datasize = extp->header[3];
+  extp->datasize = (size_t)extp->header[3];
 
   if ( EXT_Debug ) Message("datasize = %lu", extp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = extp->buffersize;
+  size_t buffersize = (size_t)extp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = extp->buffer;
@@ -17316,7 +17185,7 @@ int extRead(int fileID, void *ext)
   else
     buffer = extp->buffer;
 
-  dprec = blocklen / extp->datasize;
+  size_t dprec = blocklen / extp->datasize;
 
   if ( dprec == hprec )
     {
@@ -17367,7 +17236,7 @@ int extWrite(int fileID, void *ext)
   header = extp->header;
 
   /* write header record */
-  blocklen = EXT_HEADER_LEN * rprec;
+  blocklen = EXT_HEADER_LEN * (size_t)rprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -17400,9 +17269,9 @@ int extWrite(int fileID, void *ext)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = header[3];
+  datasize = (size_t)header[3];
   if ( number == EXT_COMP ) datasize *= 2;
-  blocklen = datasize * rprec;
+  blocklen = datasize * (size_t)rprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -17453,10 +17322,6 @@ int extWrite(int fileID, void *ext)
 
 
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
-
-
 static int initIegLib      = 0;
 static int iegDefaultDprec = 0;
 
@@ -17585,10 +17450,10 @@ int iegCheckFiletype(int fileID, int *swap)
   size_t sblocklen = 0;
   size_t data = 0;
   size_t dimx = 0, dimy = 0;
-  int fact = 0, found = 0;
+  size_t fact = 0;
   unsigned char buffer[1048], *pbuf;
 
-  if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
+  if ( fileRead(fileID, buffer, 4) != 4 ) return (0);
 
   blocklen  = get_UINT32(buffer);
   sblocklen = get_SUINT32(buffer);
@@ -17600,7 +17465,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 0;
       fact = 4;
-      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;    dimx = (size_t) get_UINT32(pbuf);
       pbuf = buffer+(37+5)*4;    dimy = (size_t) get_UINT32(pbuf);
       pbuf = buffer+blocklen+4;  data = (size_t) get_UINT32(pbuf);
@@ -17609,7 +17474,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 0;
       fact = 8;
-      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;    dimx = (size_t) get_UINT32(pbuf);
       pbuf = buffer+(37+5)*4;    dimy = (size_t) get_UINT32(pbuf);
       pbuf = buffer+blocklen+4;  data = (size_t) get_UINT32(pbuf);
@@ -17618,7 +17483,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 1;
       fact = 4;
-      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;     dimx = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+(37+5)*4;     dimy = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+sblocklen+4;  data = (size_t) get_SUINT32(pbuf);
@@ -17627,7 +17492,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 1;
       fact = 8;
-      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;     dimx = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+(37+5)*4;     dimy = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+sblocklen+4;  data = (size_t) get_SUINT32(pbuf);
@@ -17635,8 +17500,7 @@ int iegCheckFiletype(int fileID, int *swap)
 
   fileRewind(fileID);
 
-  if      ( data && dimx*dimy*fact == data ) found = 1;
-  else if ( data && dimx*dimy*8    == data ) found = 1;
+  int found = data && (dimx*dimy*fact == data || dimx*dimy*8 == data);
 
   if ( IEG_Debug )
     {
@@ -17752,8 +17616,8 @@ int iegDefData(iegrec_t *iegp, int prec, const void *data)
 
   iegp->dprec = dprec;
 
-  datasize = IEG_G_NumLon(iegp->igdb)*IEG_G_NumLat(iegp->igdb);
-  blocklen = datasize * dprec;
+  datasize = (size_t)IEG_G_NumLon(iegp->igdb) * (size_t)IEG_G_NumLat(iegp->igdb);
+  blocklen = datasize * (size_t)dprec;
 
   iegp->datasize = datasize;
 
@@ -17823,7 +17687,6 @@ int iegRead(int fileID, iegrec_t *iegp)
   char tmpbuffer[800], *tmpbuf = tmpbuffer;
   int dprec = 0;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -17915,16 +17778,17 @@ int iegRead(int fileID, iegrec_t *iegp)
       return (-1);
     }
 
-  iegp->datasize = IEG_G_NumLon(iegp->igdb)*IEG_G_NumLat(iegp->igdb);
+  iegp->datasize = (size_t)IEG_G_NumLon(iegp->igdb)
+    * (size_t)IEG_G_NumLat(iegp->igdb);
 
   if ( IEG_Debug )
     Message("datasize = %lu", iegp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = iegp->buffersize;
+  size_t buffersize = iegp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = iegp->buffer;
@@ -18010,8 +17874,8 @@ int iegWrite(int fileID, iegrec_t *iegp)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = iegp->igdb[4]*iegp->igdb[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)iegp->igdb[4] * (size_t)iegp->igdb[5];
+  blocklen = datasize * (size_t)dprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -18107,7 +17971,6 @@ static const resOps gridOps = {
   gridTxCode
 };
 
-
 static int  GRID_Debug = 0;   /* If set to 1, debugging */
 
 
@@ -18254,7 +18117,7 @@ int gridSize(void)
   return reshCountType ( &gridOps );
 }
 
-
+// used also in CDO
 void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
 {
   if ( (! (fabs(xinc) > 0)) && xsize > 1 )
@@ -18277,32 +18140,28 @@ void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *x
 static
 void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
 {
-  long yhsize;
-
-  double *yw = (double *)xmalloc(ysize*sizeof(double));
-  gaussaw(yvals, yw, ysize);
+  double *yw = (double *)xmalloc((size_t)ysize * sizeof(double));
+  gaussaw(yvals, yw, (size_t)ysize);
   free(yw);
-  for (long i = 0; i < ysize; i++ )
+  for (int i = 0; i < ysize; i++ )
     yvals[i] = asin(yvals[i])/M_PI*180.0;
 
   if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
     {
-      double ytmp;
-      yhsize = ysize/2;
-      for (long i = 0; i < yhsize; i++ )
+      int yhsize = ysize/2;
+      for (int i = 0; i < yhsize; i++ )
         {
-          ytmp = yvals[i];
+          double ytmp = yvals[i];
           yvals[i] = yvals[ysize-i-1];
           yvals[ysize-i-1] = ytmp;
         }
     }
 }
 
-
+// used also in CDO
 void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals)
 {
-  long i;
-  double deleps = 0.002;
+  const double deleps = 0.002;
 
   if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -18321,8 +18180,9 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 		/* printf("%g %g %g %g %g %d\n", ylast, yfirst, ylast-yfirst,yinc, 180/yinc, ny); */
 		if ( ny > ysize && ny < 4096 )
 		  {
-		    ytmp = (double *) malloc(ny*sizeof(double));
+		    ytmp = (double *)xmalloc((size_t)ny * sizeof (double));
 		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
+                    int i;
 		    for ( i = 0; i < (ny-ysize); i++ )
 		      if ( fabs(ytmp[i] - yfirst) < deleps ) break;
 
@@ -18334,12 +18194,12 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 
 		if ( lfound )
 		  {
-		    for ( i = 0; i < ysize; i++ ) yvals[i] = ytmp[i+nstart];
+		    for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
 		  }
 		else
 		  {
 		    Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
-		    for ( i = 0; i < ysize; i++ ) yvals[i] = 0;
+		    for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
 		    yvals[0] = yfirst;
 		    yvals[ysize-1] = ylast;
 		  }
@@ -18381,7 +18241,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 
       if ( yfirst > ylast && yinc > 0 ) yinc = -yinc;
 
-      for ( i = 0; i < ysize; i++ )
+      for (int i = 0; i < ysize; i++ )
         yvals[i] = yfirst + i*yinc;
     }
   /*
@@ -18431,19 +18291,16 @@ gridDefYvals(gridID, lats);
 */
 int gridCreate(int gridtype, int size)
 {
-  int gridID;
-  grid_t *gridptr;
-
   if ( CDI_Debug ) Message("gridtype=%s  size=%d", gridNamePtr(gridtype), size);
 
   if ( size < 0 || size > INT_MAX ) Error("Grid size (%d) out of bounds (0 - %d)!", size, INT_MAX);
 
   gridInit();
 
-  gridptr = gridNewEntry(CDI_UNDEFID);
+  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
   if ( ! gridptr ) Error("No memory");
 
-  gridID = gridptr->self;
+  int gridID = gridptr->self;
 
   if ( CDI_Debug ) Message("gridID: %d", gridID);
 
@@ -18570,9 +18427,7 @@ void gridDestroyKernel( grid_t * gridptr )
 */
 void gridDestroy(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   gridDestroyKernel ( gridptr );
 }
@@ -18618,20 +18473,15 @@ The function @func{gridDefXname} defines the name of a X-axis.
 */
 void gridDefXname(int gridID, const char *xname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( xname )
-    strcpy(gridptr->xname, xname);
+    {
+      strcpy(gridptr->xname, xname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -18650,18 +18500,14 @@ The function @func{gridDefXlongname} defines the longname of a X-axis.
 */
 void gridDefXlongname(int gridID, const char *xlongname)
 {
-  grid_t *gridptr;
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
+  grid_check_ptr(gridID, gridptr);
 
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
+  if ( xlongname )
     {
-      Warning ("%s", "Operation not executed." );
-      return;
+      strcpy(gridptr->xlongname, xlongname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
-
-  if ( xlongname )
-    strcpy(gridptr->xlongname, xlongname);
 }
 
 /*
@@ -18680,20 +18526,15 @@ The function @func{gridDefXunits} defines the units of a X-axis.
 */
 void gridDefXunits(int gridID, const char *xunits)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( xunits )
-    strcpy(gridptr->xunits, xunits);
+    {
+      strcpy(gridptr->xunits, xunits);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -18712,20 +18553,15 @@ The function @func{gridDefYname} defines the name of a Y-axis.
 */
 void gridDefYname(int gridID, const char *yname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( yname )
-    strcpy(gridptr->yname, yname);
+    {
+      strcpy(gridptr->yname, yname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -18744,20 +18580,15 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis.
 */
 void gridDefYlongname(int gridID, const char *ylongname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( ylongname )
-    strcpy(gridptr->ylongname, ylongname);
+    {
+      strcpy(gridptr->ylongname, ylongname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -18776,20 +18607,15 @@ The function @func{gridDefYunits} defines the units of a Y-axis.
 */
 void gridDefYunits(int gridID, const char *yunits)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( yunits )
-    strcpy(gridptr->yunits, yunits);
+    {
+      strcpy(gridptr->yunits, yunits);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -18813,9 +18639,7 @@ The function @func{gridInqXname} returns the name of a X-axis.
 */
 void gridInqXname(int gridID, char *xname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18843,9 +18667,7 @@ The function @func{gridInqXlongname} returns the longname of a X-axis.
 */
 void gridInqXlongname(int gridID, char *xlongname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18873,9 +18695,7 @@ The function @func{gridInqXunits} returns the units of a X-axis.
 */
 void gridInqXunits(int gridID, char *xunits)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18885,9 +18705,7 @@ void gridInqXunits(int gridID, char *xunits)
 
 void gridInqXstdname(int gridID, char *xstdname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18915,9 +18733,7 @@ The function @func{gridInqYname} returns the name of a Y-axis.
 */
 void gridInqYname(int gridID, char *yname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18945,9 +18761,7 @@ The function @func{gridInqYlongname} returns the longname of a Y-axis.
 */
 void gridInqYlongname(int gridID, char *ylongname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18975,9 +18789,7 @@ The function @func{gridInqYunits} returns the units of a Y-axis.
 */
 void gridInqYunits(int gridID, char *yunits)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -18986,9 +18798,7 @@ void gridInqYunits(int gridID, char *yunits)
 
 void gridInqYstdname(int gridID, char *ystdname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19017,9 +18827,7 @@ The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
 */
 int gridInqType(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19045,14 +18853,11 @@ The function @func{gridInqSize} returns the size of a Grid.
 */
 int gridInqSize(int gridID)
 {
-  int size = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  int size = gridptr->size;
 
   if ( ! size )
     {
@@ -19091,9 +18896,7 @@ int nsp2trunc(int nsp)
 
 int gridInqTrunc(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19113,19 +18916,15 @@ int gridInqTrunc(int gridID)
 
 void gridDefTrunc(int gridID, int trunc)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->trunc = trunc;
+  if (gridptr->trunc != trunc)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->trunc = trunc;
+    }
 }
 
 /*
@@ -19144,15 +18943,7 @@ The function @func{gridDefXsize} defines the number of values of a X-axis.
 */
 void gridDefXsize(int gridID, int xsize)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19162,7 +18953,11 @@ void gridDefXsize(int gridID, int xsize)
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED && xsize != gridInqSize(gridID) )
     Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridInqSize(gridID));
 
-  gridptr->xsize = xsize;
+  if (gridptr->xsize != xsize)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->xsize = xsize;
+    }
 
   if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
     {
@@ -19185,19 +18980,15 @@ void gridDefXsize(int gridID, int xsize)
 */
 void gridDefPrec(int gridID, int prec)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->prec = prec;
+  if (gridptr->prec != prec)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->prec = prec;
+    }
 }
 
 /*
@@ -19212,9 +19003,7 @@ void gridDefPrec(int gridID, int prec)
 */
 int gridInqPrec(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19239,9 +19028,7 @@ The function @func{gridInqXsize} returns the number of values of a X-axis.
 */
 int gridInqXsize(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19264,15 +19051,7 @@ The function @func{gridDefYsize} defines the number of values of a Y-axis.
 */
 void gridDefYsize(int gridID, int ysize)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19282,7 +19061,11 @@ void gridDefYsize(int gridID, int ysize)
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ysize != gridInqSize(gridID) )
     Error("ysize %d must be equal gridsize %d for gridtype: UNSTRUCTURED", ysize, gridInqSize(gridID));
 
-  gridptr->ysize = ysize;
+  if (gridptr->ysize != ysize)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->ysize = ysize;
+    }
 
   if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
     {
@@ -19311,9 +19094,7 @@ The function @func{gridInqYsize} returns the number of values of a Y-axis.
 */
 int gridInqYsize(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19337,19 +19118,15 @@ of a Gaussian grid.
 */
 void gridDefNP(int gridID, int np)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->np = np;
+  if (gridptr->np != np)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->np = np;
+    }
 }
 
 /*
@@ -19371,9 +19148,7 @@ of a Gaussian grid.
 */
 int gridInqNP(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19392,22 +19167,14 @@ int gridInqNP(int gridID)
 */
 void gridDefRowlon(int gridID, int nrowlon, const int *rowlon)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->rowlon = (int *) malloc(nrowlon*sizeof(int));
+  gridptr->rowlon = (int *)xmalloc((size_t)nrowlon * sizeof(int));
   gridptr->nrowlon = nrowlon;
-
-  memcpy(gridptr->rowlon, rowlon, nrowlon*sizeof(int));
+  memcpy(gridptr->rowlon, rowlon, (size_t)nrowlon * sizeof(int));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -19422,35 +19189,30 @@ void gridDefRowlon(int gridID, int nrowlon, const int *rowlon)
 */
 void gridInqRowlon(int gridID, int *rowlon)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( gridptr->rowlon == 0 )  Error("undefined pointer!");
 
-  memcpy(rowlon, gridptr->rowlon, gridptr->nrowlon*sizeof(int));
+  memcpy(rowlon, gridptr->rowlon, (size_t)gridptr->nrowlon * sizeof(int));
 }
 
 
 int gridInqMask(int gridID, int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( CDI_Debug && size == 0 )
     Warning("Size undefined for gridID = %d", gridID);
 
-  if ( mask && gridptr->mask )
-    for ( i = 0; i < size; ++i )
-      mask[i] = gridptr->mask[i];
+  if (mask && gridptr->mask)
+    for (long i = 0; i < size; ++i)
+      mask[i] = (int)gridptr->mask[i];
 
   if ( gridptr->mask == NULL ) size = 0;
 
@@ -19460,18 +19222,9 @@ int gridInqMask(int gridID, int *mask)
 
 void gridDefMask(int gridID, const int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d", gridID);
@@ -19487,33 +19240,30 @@ void gridDefMask(int gridID, const int *mask)
   else
     {
       if ( gridptr->mask == NULL )
-	gridptr->mask = (mask_t *) malloc(size*sizeof(mask_t));
+	gridptr->mask = (mask_t *)xmalloc((size_t)size*sizeof(mask_t));
       else if ( CDI_Debug )
 	Warning("grid mask already defined!");
 
-      for ( i = 0; i < size; ++i )
-	gridptr->mask[i] = mask[i];
+      for (long i = 0; i < size; ++i )
+	gridptr->mask[i] = (mask_t)(mask[i] != 0);
     }
 }
 
 
 int gridInqMaskGME(int gridID, int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( CDI_Debug && size == 0 )
     Warning("Size undefined for gridID = %d", gridID);
 
   if ( mask && gridptr->mask_gme )
-    for ( i = 0; i < size; ++i )
-      mask[i] = gridptr->mask_gme[i];
+    for (long i = 0; i < size; ++i)
+      mask[i] = (int)gridptr->mask_gme[i];
 
   if ( gridptr->mask_gme == NULL ) size = 0;
 
@@ -19523,31 +19273,22 @@ int gridInqMaskGME(int gridID, int *mask)
 
 void gridDefMaskGME(int gridID, const int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d", gridID);
 
   if ( gridptr->mask_gme == NULL )
-    gridptr->mask_gme = (mask_t *) malloc(size*sizeof(mask_t));
+    gridptr->mask_gme = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
   else if ( CDI_Debug )
     Warning("mask already defined!");
 
-  for ( i = 0; i < size; ++i )
-    gridptr->mask_gme[i] = mask[i];
+  for (long i = 0; i < size; ++i)
+    gridptr->mask_gme[i] = (mask_t)(mask[i] != 0);
 }
 
 /*
@@ -19572,13 +19313,11 @@ Otherwise, 0 is returned and @func{xvals} is empty.
 */
 int gridInqXvals(int gridID, double *xvals)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
+  long size;
   if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
     size = gridptr->size;
   else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
@@ -19590,7 +19329,7 @@ int gridInqXvals(int gridID, double *xvals)
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && xvals && gridptr->xvals )
-    memcpy(xvals, gridptr->xvals, size*sizeof(double));
+    memcpy(xvals, gridptr->xvals, (size_t)size * sizeof (double));
 
   if ( gridptr->xvals == NULL ) size = 0;
 
@@ -19613,20 +19352,13 @@ The function @func{gridDefXvals} defines all values of the X-axis.
 */
 void gridDefXvals(int gridID, const double *xvals)
 {
-  int gridtype;
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
+  int gridtype;
+  long size;
+
   gridtype = gridptr->type;
 
   if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
@@ -19641,8 +19373,10 @@ void gridDefXvals(int gridID, const double *xvals)
 
   if (gridptr->xvals && CDI_Debug)
     Warning("values already defined!");
-  gridptr->xvals = (double *)xrealloc(gridptr->xvals, size * sizeof(double));
-  memcpy(gridptr->xvals, xvals, size*sizeof(double));
+  gridptr->xvals = (double *)xrealloc(gridptr->xvals,
+                                      (size_t)size * sizeof(double));
+  memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -19667,23 +19401,20 @@ Otherwise, 0 is returned and @func{yvals} is empty.
 */
 int gridInqYvals(int gridID, double *yvals)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = gridptr->size;
-  else
-    size = gridptr->ysize;
+  int gridtype = gridptr->type;
+  long size
+    = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+    ? gridptr->size : gridptr->ysize;
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d!", gridID);
 
   if ( size && yvals && gridptr->yvals )
-    memcpy(yvals, gridptr->yvals, size*sizeof(double));
+    memcpy(yvals, gridptr->yvals, (size_t)size * sizeof (double));
 
   if ( gridptr->yvals == NULL ) size = 0;
 
@@ -19706,26 +19437,14 @@ The function @func{gridDefYvals} defines all values of the Y-axis.
 */
 void gridDefYvals(int gridID, const double *yvals)
 {
-  int gridtype;
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridptr->type;
-
-  if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
-    size = gridptr->size;
-  else
-    size = gridptr->ysize;
+  int gridtype = gridptr->type;
+  long size
+    = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+    ? gridptr->size : gridptr->ysize;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d!", gridID);
@@ -19733,17 +19452,16 @@ void gridDefYvals(int gridID, const double *yvals)
   if (gridptr->yvals && CDI_Debug)
     Warning("Values already defined!");
 
-  gridptr->yvals = (double *)xrealloc(gridptr->yvals, size*sizeof(double));
-  memcpy(gridptr->yvals, yvals, size*sizeof(double));
+  gridptr->yvals = (double *)xrealloc(gridptr->yvals, (size_t)size * sizeof (double));
+  memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 
 double gridInqXval(int gridID, int index)
 {
   double xval = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19766,9 +19484,7 @@ double gridInqXval(int gridID, int index)
 double gridInqYval(int gridID, int index)
 {
   double yval = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19798,17 +19514,13 @@ double gridInqXinc(int gridID)
 
   if ( (! (fabs(xinc) > 0)) && gridptr->xvals )
     {
-      int xsize;
-      double *xvals;
-
-      xsize = gridptr->xsize;
-      xvals = gridptr->xvals;
-
+      int xsize = gridptr->xsize;
       if ( xsize > 1 )
         {
-          long i;
+          double *xvals = gridptr->xvals;
           xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
-          for ( i = 2; i < xsize; i++ )
+          int i;
+          for (i = 2; i < xsize; i++ )
             if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc ) break;
 
           if ( i < xsize ) xinc = 0;
@@ -19846,8 +19558,8 @@ double gridInqYinc(int gridID)
 
       if ( ysize > 1 )
         {
-          long i;
           yinc = fabs(yvals[1] - yvals[0]);
+          int i;
           for ( i = 2; i < ysize; i++ )
             if ( fabs(fabs(yvals[i] - yvals[i-1]) - yinc) > (yinc/1000) ) break;
 
@@ -19871,9 +19583,7 @@ double gridInqYinc(int gridID)
 */
 double gridInqXpole(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19892,23 +19602,19 @@ double gridInqXpole(int gridID)
 */
 void gridDefXpole(int gridID, double xpole)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( memcmp(gridptr->xstdname, "grid", 4) != 0 )
     strcpy(gridptr->xstdname, "grid_longitude");
 
-  gridptr->isRotated = TRUE;
-  gridptr->xpole = xpole;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->xpole = xpole;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -19923,9 +19629,7 @@ void gridDefXpole(int gridID, double xpole)
 */
 double gridInqYpole(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19944,23 +19648,19 @@ double gridInqYpole(int gridID)
 */
 void gridDefYpole(int gridID, double ypole)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( memcmp(gridptr->ystdname, "grid", 4) != 0 )
     strcpy(gridptr->ystdname, "grid_latitude");
 
-  gridptr->isRotated = TRUE;
-  gridptr->ypole = ypole;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->ypole = ypole;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -19975,9 +19675,7 @@ void gridDefYpole(int gridID, double ypole)
 */
 double gridInqAngle(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -19996,20 +19694,16 @@ double gridInqAngle(int gridID)
 */
 void gridDefAngle(int gridID, double angle)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->isRotated = TRUE;
-  gridptr->angle = angle;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->angle, angle) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->angle = angle;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -20024,9 +19718,7 @@ void gridDefAngle(int gridID, double angle)
 */
 int gridInqGMEnd(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20045,19 +19737,15 @@ int gridInqGMEnd(int gridID)
 */
 void gridDefGMEnd(int gridID, int nd)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->nd = nd;
+  if (gridptr->nd != nd)
+    {
+      gridptr->nd = nd;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -20072,9 +19760,7 @@ void gridDefGMEnd(int gridID, int nd)
 */
 int gridInqGMEni(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20093,19 +19779,15 @@ int gridInqGMEni(int gridID)
 */
 void gridDefGMEni(int gridID, int ni)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni = ni;
+  if (gridptr->ni != ni)
+    {
+      gridptr->ni = ni;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -20120,9 +19802,7 @@ void gridDefGMEni(int gridID, int ni)
 */
 int gridInqGMEni2(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20141,18 +19821,15 @@ int gridInqGMEni2(int gridID)
 */
 void gridDefGMEni2(int gridID, int ni2)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni2 = ni2;
+  if (gridptr->ni2 != ni2)
+    {
+      gridptr->ni2 = ni2;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -20167,9 +19844,7 @@ void gridDefGMEni2(int gridID, int ni2)
 */
 int gridInqGMEni3(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20178,19 +19853,15 @@ int gridInqGMEni3(int gridID)
 
 void gridDefGMEni3(int gridID, int ni3)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni3 = ni3;
+  if (gridptr->ni3 != ni3)
+    {
+      gridptr->ni3 = ni3;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -20205,16 +19876,18 @@ void gridDefGMEni3(int gridID, int ni3)
 */
 void gridChangeType(int gridID, int gridtype)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( CDI_Debug ) 
+  if ( CDI_Debug )
     Message("Changed grid type from %s to %s", gridNamePtr(gridptr->type), gridNamePtr(gridtype));
 
-  gridptr->type = gridtype;
+  if (gridptr->type != gridtype)
+    {
+      gridptr->type = gridtype;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 static
@@ -20323,9 +19996,7 @@ void grid_check_cyclic(grid_t *gridptr)
 
 int gridIsCircular(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20337,9 +20008,7 @@ int gridIsCircular(int gridID)
 
 int gridIsRotated(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20354,9 +20023,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 
   if ( !differ && xsize == gridInqXvals(gridID, NULL) )
     {
-      double *xvals;
-
-      xvals = (double *) malloc(xsize*sizeof(double));
+      double *xvals = (double *)xmalloc((size_t)xsize * sizeof (double));
 
       gridInqXvals(gridID, xvals);
 
@@ -20372,9 +20039,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 
   if ( !differ && ysize == gridInqYvals(gridID, NULL) )
     {
-      double *yvals;
-
-      yvals = (double *) malloc(ysize*sizeof(double));
+      double *yvals = (double *)xmalloc((size_t)ysize * sizeof (double));
 
       gridInqYvals(gridID, yvals);
 
@@ -20392,7 +20057,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 }
 
 static
-int compareXYvals2(int gridID, long gridsize, double *xvals, double *yvals)
+int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
 {
   int differ = 0;
 
@@ -20502,8 +20167,8 @@ int gridCompare(int gridID, grid_t grid)
 		    {
 		      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.001 ||
-			     fabs(grid.yfirst - gridInqYval(gridID, 0)) > 0.001 ||
+			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(gridInqXinc(gridID))) > fabs(grid.xinc/1000)) )
 			  {
 			    differ = 1;
@@ -20542,12 +20207,21 @@ int gridCompare(int gridID, grid_t grid)
 	    {
               char uuidOfHGrid[17];
               gridInqUUID(gridID, uuidOfHGrid);
-
+              /*
+              printf("compare unstructured grids\n");
+	      printf("gridID        %d\n", gridID);
+	      printf("gridsize      %d\n", grid.size);
+              if ( uuidOfHGrid[0] != 0 && grid.uuid[0] != 0 && memcmp(grid.uuid, uuidOfHGrid, 16) )
+                printf("uuidOfHGrid     differ\n");
+              printf("nvertex      %d  %d\n", grid.nvertex, gridInqNvertex(gridID));
+              printf("number       %d  %d\n", grid.number, gridInqNumber(gridID));
+              printf("position     %d  %d\n", grid.position, gridInqPosition(gridID));
+              */
               if ( uuidOfHGrid[0] != 0 && grid.uuid[0] != 0 )
                 if ( !differ && memcmp(uuidOfHGrid, grid.uuid, 16) != 0 ) differ = 1;
               if ( !differ && grid.nvertex != gridInqNvertex(gridID) ) differ = 1;
               if ( !differ && grid.number != gridInqNumber(gridID) ) differ = 1;
-              if ( !differ && grid.position != gridInqPosition(gridID) ) differ = 1;
+              if ( !differ && grid.number > 0 && grid.position != gridInqPosition(gridID) ) differ = 1;
 	      if ( !differ )
 		differ = compareXYvals2(gridID, grid.size, grid.xvals, grid.yvals);
 	    }
@@ -20718,8 +20392,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   if ( g1->reference )
     {
       if ( !g2->reference ) return differ;
-      size = strlen ( g1->reference ) + 1;
-      if ( memcmp ( g1->reference, g2->reference, size ) ) return differ;
+      if ( strcmp(g1->reference, g2->reference) ) return differ;
     }
   else if ( g2->reference )
     return differ;
@@ -20728,7 +20401,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
     {
       xassert ( g1->size );
       if ( !g2->mask ) return differ;
-      if ( memcmp ( g1->mask, g2->mask, g1->size*sizeof(unsigned char)) ) return differ;
+      if ( memcmp ( g1->mask, g2->mask, (size_t)g1->size * sizeof(mask_t)) ) return differ;
     }
   else if ( g2->mask )
     return differ;
@@ -20737,7 +20410,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
     {
       xassert ( g1->size );
       if ( !g2->mask_gme ) return differ;
-      if ( memcmp ( g1->mask_gme, g2->mask_gme, g1->size*sizeof(unsigned char)) ) return differ;
+      if ( memcmp ( g1->mask_gme, g2->mask_gme, (size_t)g1->size * sizeof(mask_t)) ) return differ;
     }
   else if ( g2->mask_gme )
     return differ;
@@ -20748,12 +20421,9 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
 
 int gridGenerate(grid_t grid)
 {
-  int gridID;
-  grid_t *gridptr;
+  int gridID = gridCreate(grid.type, grid.size);
 
-  gridID = gridCreate(grid.type, grid.size);
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -20788,7 +20458,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.xdef == 2 )
 	  {
-	    double *xvals = (double *) malloc(grid.xsize*sizeof(double));
+	    double *xvals
+              = (double *)xmalloc((size_t)grid.xsize * sizeof (double));
 	    gridGenXvals(grid.xsize, grid.xfirst, grid.xlast, grid.xinc, xvals);
 	    gridDefXvals(gridID, xvals);
 	    free(xvals);
@@ -20805,7 +20476,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.ydef == 2 )
 	  {
-	    double *yvals = (double *) malloc(grid.ysize*sizeof(double));
+	    double *yvals
+              = (double *)xmalloc((size_t)grid.ysize * sizeof (double));
 	    gridGenYvals(grid.type, grid.ysize, grid.yfirst, grid.ylast, grid.yinc, yvals);
 	    gridDefYvals(gridID, yvals);
 	    free(yvals);
@@ -20889,7 +20561,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.ydef == 2 )
 	  {
-	    double *yvals = (double *) malloc(grid.ysize*sizeof(double));
+	    double *yvals
+              = (double *)xmalloc((size_t)grid.ysize * sizeof (double));
 	    gridGenYvals(grid.type, grid.ysize, grid.yfirst, grid.ylast, grid.yinc, yvals);
 	    gridDefYvals(gridID, yvals);
 	    free(yvals);
@@ -20972,21 +20645,15 @@ The function @func{gridDuplicate} duplicates a horizontal Grid.
 */
 int gridDuplicate(int gridID)
 {
-  int gridIDnew;
-  int gridtype, gridsize;
-  int nrowlon;
-  int size;
-  grid_t *gridptr, *gridptrnew;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridInqType(gridID);
-  gridsize = gridInqSize(gridID);
+  int gridtype = gridInqType(gridID);
+  int gridsize = gridInqSize(gridID);
 
-  gridIDnew = gridCreate(gridtype, gridsize);
-  gridptrnew = ( grid_t *) reshGetVal ( gridIDnew, &gridOps );
+  int gridIDnew = gridCreate(gridtype, gridsize);
+  grid_t *gridptrnew = reshGetVal(gridIDnew, &gridOps);
 
   grid_copy(gridptrnew, gridptr);
 
@@ -20999,85 +20666,73 @@ int gridDuplicate(int gridID)
   strcpy(gridptrnew->xstdname, gridptr->xstdname);
   strcpy(gridptrnew->ystdname, gridptr->ystdname);
 
-  if ( gridptr->reference )  gridptrnew->reference = strdupx(gridptr->reference);
+  if (gridptr->reference)
+    gridptrnew->reference = strdupx(gridptr->reference);
 
-  nrowlon = gridptr->nrowlon;
+  size_t nrowlon = (size_t)gridptr->nrowlon;
+  int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
   if ( nrowlon )
     {
-      gridptrnew->rowlon = (int *) malloc(nrowlon*sizeof(int));
-      memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon*sizeof(int));
+      gridptrnew->rowlon = (int *)xmalloc(nrowlon * sizeof (int));
+      memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon * sizeof(int));
     }
 
   if ( gridptr->xvals != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->xsize;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->xsize);
 
-      gridptrnew->xvals = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->xvals, gridptr->xvals, size*sizeof(double));
+      gridptrnew->xvals = (double *)xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->xvals, gridptr->xvals, size * sizeof (double));
     }
 
   if ( gridptr->yvals != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->ysize;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->ysize);
 
-      gridptrnew->yvals = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->yvals, gridptr->yvals, size*sizeof(double));
+      gridptrnew->yvals = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->yvals, gridptr->yvals, size * sizeof (double));
     }
 
   if ( gridptr->xbounds != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->xsize;
-
-      size *= gridptr->nvertex;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->xsize)
+        * (size_t)gridptr->nvertex;
 
-      gridptrnew->xbounds = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->xbounds, gridptr->xbounds, size*sizeof(double));
+      gridptrnew->xbounds = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->xbounds, gridptr->xbounds, size * sizeof (double));
     }
 
   if ( gridptr->ybounds != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->ysize;
-
-      size *= gridptr->nvertex;
+      size_t size = (size_t)(irregular ? gridsize : gridptr->ysize)
+        * (size_t)gridptr->nvertex;
 
-      gridptrnew->ybounds = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->ybounds, gridptr->ybounds, size*sizeof(double));
+      gridptrnew->ybounds = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->ybounds, gridptr->ybounds, size * sizeof (double));
     }
 
   if ( gridptr->area != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->area = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->area, gridptr->area, size*sizeof(double));
+      gridptrnew->area = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->area, gridptr->area, size * sizeof (double));
     }
 
   if ( gridptr->mask != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->mask = (mask_t *) malloc(size*sizeof(mask_t));
-      memcpy(gridptrnew->mask, gridptr->mask, size*sizeof(mask_t));
+      gridptrnew->mask = xmalloc(size * sizeof(mask_t));
+      memcpy(gridptrnew->mask, gridptr->mask, size * sizeof (mask_t));
     }
 
   if ( gridptr->mask_gme != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->mask_gme = (mask_t *) malloc(size*sizeof(mask_t));
-      memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size*sizeof(mask_t));
+      gridptrnew->mask_gme = xmalloc(size * sizeof (mask_t));
+      memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size * sizeof(mask_t));
     }
 
   return (gridIDnew);
@@ -21086,38 +20741,38 @@ int gridDuplicate(int gridID)
 
 void gridCompress(int gridID)
 {
-  int gridtype, gridsize;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridInqType(gridID);
-  gridsize = gridInqSize(gridID);
-
+  int gridtype = gridInqType(gridID);
   if ( gridtype == GRID_UNSTRUCTURED )
     {
       if ( gridptr->mask_gme != NULL )
 	{
-	  long i, j, iv, nv;
-
-	  nv = gridptr->nvertex;
-
-	  j = 0;
-	  for ( i = 0; i < gridsize; i++ )
+          size_t gridsize = (size_t)gridInqSize(gridID);
+	  size_t nv = (size_t)gridptr->nvertex;
+
+	  size_t j = 0;
+          double *area = gridptr->area,
+            *xvals = gridptr->xvals,
+            *yvals = gridptr->yvals,
+            *xbounds = gridptr->xbounds,
+            *ybounds = gridptr->ybounds;
+          mask_t *mask_gme = gridptr->mask_gme;
+	  for (size_t i = 0; i < gridsize; i++ )
 	    {
-	      if ( gridptr->mask_gme[i] )
+	      if (mask_gme[i])
 		{
-		  if ( gridptr->xvals != NULL ) gridptr->xvals[j] = gridptr->xvals[i];
-		  if ( gridptr->yvals != NULL ) gridptr->yvals[j] = gridptr->yvals[i];
-		  if ( gridptr->area  != NULL ) gridptr->area[j]  = gridptr->area[i];
-		  if ( gridptr->xbounds != NULL )
-		    for ( iv = 0; iv < nv; iv++ )
-		      gridptr->xbounds[j*nv+iv] = gridptr->xbounds[i*nv+iv];
-		  if ( gridptr->ybounds != NULL )
-		    for ( iv = 0; iv < nv; iv++ )
-		      gridptr->ybounds[j*nv+iv] = gridptr->ybounds[i*nv+iv];
+		  if (xvals) xvals[j] = xvals[i];
+		  if (yvals) yvals[j] = yvals[i];
+		  if (area) area[j]  = area[i];
+		  if (xbounds != NULL)
+		    for (size_t iv = 0; iv < nv; iv++)
+		      xbounds[j * nv + iv] = xbounds[i * nv + iv];
+		  if (ybounds != NULL)
+		    for (size_t iv = 0; iv < nv; iv++)
+		      ybounds[j * nv + iv] = ybounds[i * nv + iv];
 
 		  j++;
 		}
@@ -21125,27 +20780,28 @@ void gridCompress(int gridID)
 
 	  /* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */
 	  gridsize = j;
-	  gridptr->size  = gridsize;
-	  gridptr->xsize = gridsize;
-	  gridptr->ysize = gridsize;
+	  gridptr->size  = (int)gridsize;
+	  gridptr->xsize = (int)gridsize;
+	  gridptr->ysize = (int)gridsize;
 
 	  if ( gridptr->xvals )
-	    gridptr->xvals = (double *) realloc(gridptr->xvals, gridsize*sizeof(double));
+	    gridptr->xvals = (double *)xrealloc(gridptr->xvals, gridsize*sizeof(double));
 
 	  if ( gridptr->yvals )
-	    gridptr->yvals = (double *) realloc(gridptr->yvals, gridsize*sizeof(double));
+	    gridptr->yvals = (double *)xrealloc(gridptr->yvals, gridsize*sizeof(double));
 
 	  if ( gridptr->area )
-	    gridptr->area  = (double *) realloc(gridptr->area, gridsize*sizeof(double));
+	    gridptr->area  = (double *)xrealloc(gridptr->area, gridsize*sizeof(double));
 
 	  if ( gridptr->xbounds )
-	    gridptr->xbounds = (double *) realloc(gridptr->xbounds, nv*gridsize*sizeof(double));
+	    gridptr->xbounds = (double *)xrealloc(gridptr->xbounds, nv*gridsize*sizeof(double));
 
 	  if ( gridptr->ybounds )
-	    gridptr->ybounds = (double *) realloc(gridptr->ybounds, nv*gridsize*sizeof(double));
+	    gridptr->ybounds = (double *)xrealloc(gridptr->ybounds, nv*gridsize*sizeof(double));
 
 	  free(gridptr->mask_gme);
 	  gridptr->mask_gme = NULL;
+          reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 	}
     }
   else
@@ -21155,59 +20811,43 @@ void gridCompress(int gridID)
 
 void gridDefArea(int gridID, const double *area)
 {
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  size_t size = gridptr->size;
 
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
   if ( gridptr->area == NULL )
-    gridptr->area = (double *) malloc(size*sizeof(double));
+    gridptr->area = (double *)xmalloc(size*sizeof(double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->area, area, size*sizeof(double));
+  memcpy(gridptr->area, area, size * sizeof(double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 
 void gridInqArea(int gridID, double *area)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
-
-  if ( gridptr->area )
-    memcpy(area, gridptr->area, size*sizeof(double));
+  if (gridptr->area)
+    memcpy(area, gridptr->area, (size_t)gridptr->size * sizeof (double));
 }
 
 
 int gridHasArea(int gridID)
 {
-  int hasArea = FALSE;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( gridptr->area != NULL ) hasArea = TRUE;
+  int hasArea = (gridptr->area != NULL);
 
   return (hasArea);
 }
@@ -21215,9 +20855,7 @@ int gridHasArea(int gridID)
 
 const double *gridInqAreaPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21227,27 +20865,21 @@ const double *gridInqAreaPtr(int gridID)
 
 void gridDefNvertex(int gridID, int nvertex)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->nvertex = nvertex;
+  if (gridptr->nvertex != nvertex)
+    {
+      gridptr->nvertex = nvertex;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int gridInqNvertex(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21270,41 +20902,31 @@ The function @func{gridDefXbounds} defines all bounds of the X-axis.
 */
 void gridDefXbounds(int gridID, const double *xbounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( nvertex == 0 )
     {
       Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
       return;
     }
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->xsize;
-
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex
+    * (size_t)(irregular ? gridptr->size : gridptr->xsize);
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
-  if ( gridptr->xbounds == NULL )
-    gridptr->xbounds = (double *) malloc(size*sizeof(double));
+  if (gridptr->xbounds == NULL)
+    gridptr->xbounds = xmalloc(size * sizeof (double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->xbounds, xbounds, size*sizeof(double));
+  memcpy(gridptr->xbounds, xbounds, size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -21329,28 +20951,23 @@ Otherwise, 0 is returned and @func{xbounds} is empty.
 */
 int gridInqXbounds(int gridID, double *xbounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( CDI_Debug && nvertex == 0 )
     Warning("nvertex undefined for gridID = %d", gridID);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->xsize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && xbounds && gridptr->xbounds )
-    memcpy(xbounds, gridptr->xbounds, size*sizeof(double));
+    memcpy(xbounds, gridptr->xbounds, size * sizeof (double));
 
   if ( gridptr->xbounds == NULL ) size = 0;
 
@@ -21360,9 +20977,7 @@ int gridInqXbounds(int gridID, double *xbounds)
 
 const double *gridInqXboundsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21385,41 +21000,31 @@ The function @func{gridDefYbounds} defines all bounds of the Y-axis.
 */
 void gridDefYbounds(int gridID, const double *ybounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( nvertex == 0 )
     {
       Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
       return;
     }
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->ysize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
 
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
   if ( gridptr->ybounds == NULL )
-    gridptr->ybounds = (double *) malloc(size*sizeof(double));
+    gridptr->ybounds = xmalloc(size * sizeof (double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->ybounds, ybounds, size*sizeof(double));
+  memcpy(gridptr->ybounds, ybounds, size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -21444,28 +21049,23 @@ Otherwise, 0 is returned and @func{ybounds} is empty.
 */
 int gridInqYbounds(int gridID, double *ybounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( CDI_Debug && nvertex == 0 )
     Warning("nvertex undefined for gridID = %d", gridID);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->ysize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && ybounds && gridptr->ybounds )
-    memcpy(ybounds, gridptr->ybounds, size*sizeof(double));
+    memcpy(ybounds, gridptr->ybounds, size * sizeof (double));
 
   if ( gridptr->ybounds == NULL ) size = 0;
 
@@ -21475,9 +21075,7 @@ int gridInqYbounds(int gridID, double *ybounds)
 
 const double *gridInqYboundsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21739,7 +21337,7 @@ void gridPrintKernel(grid_t * gridptr, int opt, FILE *fp)
             int *rowlon;
             nbyte0 = fprintf(fp, "rowlon    = ");
             nbyte  = nbyte0;
-            rowlon = (int *) malloc(ysize*sizeof(int));
+            rowlon = (int *)xmalloc((size_t)ysize*sizeof(int));
             gridInqRowlon(gridID, rowlon);
             for ( i = 0; i < ysize; i++ )
               {
@@ -21833,9 +21431,7 @@ void gridPrintKernel(grid_t * gridptr, int opt, FILE *fp)
 
 void gridPrint ( int gridID, int opt )
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21902,9 +21498,7 @@ void gridPrintP ( void * voidptr, FILE * fp )
 
 const double *gridInqXvalsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21914,9 +21508,7 @@ const double *gridInqXvalsPtr(int gridID)
 
 const double *gridInqYvalsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21949,15 +21541,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
                 double lat1, double lat2, double xinc, double yinc,
                 int projflag, int scanflag)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -21976,6 +21560,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
       gridptr->lcc_projflag  = projflag;
       gridptr->lcc_scanflag  = scanflag;
       gridptr->lcc_defined   = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -22005,9 +21590,7 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar
                 double *lat1, double *lat2, double *xinc, double *yinc,
                 int *projflag, int *scanflag)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22035,15 +21618,7 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar
 
 void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, double lat_1, double lat_2)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22058,15 +21633,14 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do
       gridptr->lcc2_lat_1   = lat_1;
       gridptr->lcc2_lat_2   = lat_2;
       gridptr->lcc2_defined = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0, double *lat_1, double *lat_2)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22090,13 +21664,7 @@ void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0,
 
 void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22109,6 +21677,7 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
       gridptr->laea_lon_0   = lon_0;
       gridptr->laea_lat_0   = lat_0;
       gridptr->laea_defined = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -22138,17 +21707,16 @@ void gridInqLaea(int gridID, double *earth_radius, double *lon_0, double *lat_0)
 
 void gridDefComplexPacking(int gridID, int lcomplex)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->lcomplex = lcomplex;
+
+  if (gridptr->lcomplex != lcomplex)
+    {
+      gridptr->lcomplex = lcomplex;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -22164,17 +21732,15 @@ int gridInqComplexPacking(int gridID)
 
 void gridDefHasDims(int gridID, int hasdims)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->hasdims = hasdims;
+  if (gridptr->hasdims != hasdims)
+    {
+      gridptr->hasdims = hasdims;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -22203,17 +21769,15 @@ The function @func{gridDefNumber} defines the reference number for an unstructur
 */
 void gridDefNumber(int gridID, const int number)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->number = number;
+  if (gridptr->number != number)
+    {
+      gridptr->number = number;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -22233,7 +21797,7 @@ The function @func{gridInqNumber} returns the reference number to an unstructure
 */
 int gridInqNumber(int gridID)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t* gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22256,17 +21820,15 @@ The function @func{gridDefPosition} defines the position of grid in the referenc
 */
 void gridDefPosition(int gridID, int position)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->position = position;
+  if (gridptr->position != position)
+    {
+      gridptr->position = position;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -22286,7 +21848,7 @@ The function @func{gridInqPosition} returns the position of grid in the referenc
 */
 int gridInqPosition(int gridID)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22309,12 +21871,6 @@ The function @func{gridDefReference} defines the reference URI for an unstructur
 */
 void gridDefReference(int gridID, const char *reference)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
@@ -22328,6 +21884,7 @@ void gridDefReference(int gridID, const char *reference)
         }
 
       gridptr->reference = strdupx(reference);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -22380,17 +21937,12 @@ The function @func{gridDefUUID} defines the UUID for an unstructured grid.
 */
 void gridDefUUID(int gridID, const char *uuid)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   memcpy(gridptr->uuid, uuid, 16);
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -22410,7 +21962,7 @@ The function @func{gridInqUUID} returns the UUID to an unstructured grid.
 */
 void gridInqUUID(int gridID, char *uuid)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -22445,7 +21997,7 @@ enum { gridNint    = 27,
 };
 
 
-static int gridGetComponentFlags ( grid_t * gridP )
+static int gridGetComponentFlags(const grid_t * gridP)
 {
   int flags = (gridHasMaskFlag & (int)((unsigned)(gridP->mask == NULL) - 1U))
     | (gridHasGMEMaskFlag & (int)((unsigned)(gridP->mask_gme == NULL) - 1U))
@@ -22541,8 +22093,9 @@ gridGetPackSize(void * voidP, void *context)
 
   if (gridP->reference)
     {
+      size_t len = strlen(gridP->reference);
       packBuffSize += serializeGetSize(1, DATATYPE_INT, context)
-        + serializeGetSize(strlen(gridP->reference) + 1, DATATYPE_TXT, context)
+        + serializeGetSize((int)len + 1, DATATYPE_TXT, context)
         + serializeGetSize(1, DATATYPE_UINT32, context);
     }
 
@@ -22621,7 +22174,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasRowLonFlag)
     {
       xassert(gridP->nrowlon);
-      gridP->rowlon = (int*) xmalloc(gridP->nrowlon * sizeof (int));
+      gridP->rowlon = (int *)xmalloc((size_t)gridP->nrowlon * sizeof (int));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->rowlon, gridP->nrowlon , DATATYPE_INT, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22663,14 +22216,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
     gridP->angle = doubleBuffer[23];
   }
 
+  int irregular = gridP->type == GRID_UNSTRUCTURED
+    || gridP->type == GRID_CURVILINEAR;
   if (memberMask & gridHasXValsFlag)
     {
-      if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
-	size = gridP->size;
-      else
-	size = gridP->xsize;
+      size = irregular ? gridP->size : gridP->xsize;
 
-      gridP->xvals = (double*) xmalloc(size * sizeof (double));
+      gridP->xvals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->xvals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22680,12 +22232,9 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasYValsFlag)
     {
-      if ( gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR )
-	size = gridP->size;
-      else
-	size = gridP->ysize;
+      size = irregular ? gridP->size : gridP->ysize;
 
-      gridP->yvals =  (double*) xmalloc( size * sizeof (double));
+      gridP->yvals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->yvals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22695,8 +22244,9 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasAreaFlag)
     {
-      xassert((size = gridP->size));
-      gridP->area = (double*) xmalloc(size * sizeof (double));
+      size = gridP->size;
+      xassert(size);
+      gridP->area = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->area, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22706,13 +22256,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasXBoundsFlag)
     {
-      if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
-	size = gridP->nvertex * gridP->size;
-      else
-	size = gridP->nvertex * gridP->xsize;
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->xsize);
       xassert(size);
 
-      gridP->xbounds = (double*) xmalloc(size * sizeof (double));
+      gridP->xbounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->xbounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22722,13 +22269,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasYBoundsFlag)
     {
-      if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
-	size = gridP->nvertex * gridP->size;
-      else
-	size = gridP->nvertex * gridP->ysize;
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->ysize);
       xassert(size);
 
-      gridP->ybounds = (double*) xmalloc(size * sizeof (double));
+      gridP->ybounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
 			  gridP->ybounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22757,7 +22301,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
       int referenceSize;
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &referenceSize, 1, DATATYPE_INT, context);
-      gridP->reference = (char*) xmalloc(referenceSize);
+      gridP->reference = (char *)xmalloc((size_t)referenceSize);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->reference, referenceSize, DATATYPE_TXT, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22768,7 +22312,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasMaskFlag)
     {
       xassert((size = gridP->size));
-      gridP->mask = (mask_t*) xmalloc(size * sizeof (mask_t));
+      gridP->mask = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->mask, gridP->size, DATATYPE_UCHAR, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22779,7 +22323,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasGMEMaskFlag)
     {
       xassert((size = gridP->size));
-      gridP->mask_gme = (mask_t*) xmalloc(size * sizeof (mask_t));
+      gridP->mask_gme = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->mask_gme, gridP->size, DATATYPE_UCHAR, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -22970,7 +22514,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
 
   if ( gridP->reference )
     {
-      size = strlen ( gridP->reference ) + 1;
+      size = (int)strlen(gridP->reference) + 1;
       serializePack(&size, 1, DATATYPE_INT,
                     packBuffer, packBufferSize, packBufferPos, context);
       serializePack(gridP->reference, size, DATATYPE_TXT,
@@ -23079,6 +22623,7 @@ typedef struct {
   int      prec;
   int      type;
   int      ltype;    /* GRIB level type */
+  int      ltype2;
   int      size;
   int      direction;
   int      vctsize;
@@ -23108,7 +22653,7 @@ static const resOps zaxisOps = {
 static int  ZAXIS_Debug = 0;   /* If set to 1, debugging */
 
 static
-void zaxisDefaultValue ( zaxis_t *zaxisptr )
+void zaxisDefaultValue(zaxis_t *zaxisptr)
 {
   zaxisptr->self        = CDI_UNDEFID;
   zaxisptr->name[0]     = 0;
@@ -23121,6 +22666,7 @@ void zaxisDefaultValue ( zaxis_t *zaxisptr )
   zaxisptr->weights     = NULL;
   zaxisptr->type        = CDI_UNDEFID;
   zaxisptr->ltype       = 0;
+  zaxisptr->ltype2      = -1;
   zaxisptr->positive    = 0;
   zaxisptr->direction   = 0;
   zaxisptr->prec        = 0;
@@ -23192,6 +22738,7 @@ zaxisCreate_(int zaxistype, int size, int id)
 {
   zaxis_t *zaxisptr = zaxisNewEntry(id);
 
+  xassert(size >= 0);
   zaxisptr->type = zaxistype;
   zaxisptr->size = size;
 
@@ -23208,7 +22755,8 @@ zaxisCreate_(int zaxistype, int size, int id)
 
   zaxisptr->positive = ZaxistypeEntry[zaxistype].positive;
 
-  double *vals = zaxisptr->vals = (double *)xmalloc(size*sizeof(double));
+  double *vals = zaxisptr->vals
+    = (double *)xmalloc((size_t)size * sizeof(double));
 
   for ( int ilev = 0; ilev < size; ilev++ )
     vals[ilev] = 0.0;
@@ -23344,15 +22892,7 @@ The function @func{zaxisDefName} defines the name of a Z-axis.
 */
 void zaxisDefName(int zaxisID, const char *name)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -23360,6 +22900,7 @@ void zaxisDefName(int zaxisID, const char *name)
     {
       strncpy(zaxisptr->name, name, CDI_MAX_NAME - 1);
       zaxisptr->name[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -23379,15 +22920,7 @@ The function @func{zaxisDefLongname} defines the longname of a Z-axis.
 */
 void zaxisDefLongname(int zaxisID, const char *longname)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -23395,6 +22928,7 @@ void zaxisDefLongname(int zaxisID, const char *longname)
     {
       strncpy(zaxisptr->longname, longname, CDI_MAX_NAME - 1);
       zaxisptr->longname[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -23414,15 +22948,7 @@ The function @func{zaxisDefUnits} defines the units of a Z-axis.
 */
 void zaxisDefUnits(int zaxisID, const char *units)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -23430,6 +22956,7 @@ void zaxisDefUnits(int zaxisID, const char *units)
     {
       strncpy(zaxisptr->units, units, CDI_MAX_NAME - 1);
       zaxisptr->units[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -23530,19 +23057,15 @@ void zaxisInqStdname(int zaxisID, char *stdname)
 
 void zaxisDefPrec(int zaxisID, int prec)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->prec = prec;
+  if (zaxisptr->prec != prec)
+    {
+      zaxisptr->prec = prec;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -23558,19 +23081,15 @@ int zaxisInqPrec(int zaxisID)
 
 void zaxisDefPositive(int zaxisID, int positive)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->positive = positive;
+  if (zaxisptr->positive != positive)
+    {
+      zaxisptr->positive = (unsigned char)positive;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -23586,29 +23105,49 @@ int zaxisInqPositive(int zaxisID)
 
 void zaxisDefLtype(int zaxisID, int ltype)
 {
-  zaxis_t *zaxisptr;
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
+
+  zaxis_check_ptr(zaxisID, zaxisptr);
 
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
+  if (zaxisptr->ltype != ltype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      zaxisptr->ltype = ltype;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
+}
 
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+
+int zaxisInqLtype(int zaxisID)
+{
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->ltype = ltype;
+  return (zaxisptr->ltype);
 }
 
 
-int zaxisInqLtype(int zaxisID)
+void zaxisDefLtype2(int zaxisID, int ltype2)
 {
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  return (zaxisptr->ltype);
+  if (zaxisptr->ltype2 != ltype2)
+    {
+      zaxisptr->ltype2 = ltype2;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
+}
+
+
+int zaxisInqLtype2(int zaxisID)
+{
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
+
+  zaxis_check_ptr(zaxisID, zaxisptr);
+
+  return (zaxisptr->ltype2);
 }
 
 /*
@@ -23627,15 +23166,7 @@ The function @func{zaxisDefLevels} defines the levels of a Z-axis.
 */
 void zaxisDefLevels(int zaxisID, const double *levels)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -23645,6 +23176,7 @@ void zaxisDefLevels(int zaxisID, const double *levels)
 
   for (int ilev = 0; ilev < size; ilev++ )
     vals[ilev] = levels[ilev];
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -23664,38 +23196,27 @@ The function @func{zaxisDefLevel} defines one level of a Z-axis.
 */
 void zaxisDefLevel(int zaxisID, int levelID, double level)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   if ( levelID >= 0 && levelID < zaxisptr->size )
     zaxisptr->vals[levelID] = level;
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefNlevRef(int zaxisID, const int nhlev)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->nhlev = nhlev;
+  if (zaxisptr->nhlev != nhlev)
+    {
+      zaxisptr->nhlev = nhlev;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -23724,19 +23245,15 @@ The function @func{zaxisDefNumber} defines the reference number for a generalize
 */
 void zaxisDefNumber(int zaxisID, const int number)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->number = number;
+  if (zaxisptr->number != number)
+    {
+      zaxisptr->number = number;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -23779,21 +23296,12 @@ The function @func{zaxisDefUUID} defines the UUID for a generalized  Z-axis.
 */
 void zaxisDefUUID(int zaxisID, const char *uuid)
 {
-  zaxis_t *zaxisptr;
-
-    if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   memcpy(zaxisptr->uuid, uuid, 16);
-
-  return;
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -24097,23 +23605,16 @@ void cdiCheckZaxis(int zaxisID)
 
 void zaxisDefVct(int zaxisID, int size, const double *vct)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   if ( zaxisptr->vct == 0 )
     {
       zaxisptr->vctsize = size;
-      zaxisptr->vct = (double *) malloc(size*sizeof(double));
-      memcpy(zaxisptr->vct, vct, size*sizeof(double));
+      zaxisptr->vct = (double *)xmalloc((size_t)size * sizeof (double));
+      memcpy(zaxisptr->vct, vct, (size_t)size * sizeof (double));
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
   else
     if ( zaxisptr->vctsize != size )
@@ -24127,7 +23628,7 @@ void zaxisInqVct(int zaxisID, double *vct)
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  memcpy(vct, zaxisptr->vct, zaxisptr->vctsize*sizeof(double));
+  memcpy(vct, zaxisptr->vct, (size_t)zaxisptr->vctsize * sizeof (double));
 }
 
 
@@ -24153,19 +23654,11 @@ const double *zaxisInqVctPtr(int zaxisID)
 
 void zaxisDefLbounds(int zaxisID, const double *lbounds)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->lbounds != NULL )
@@ -24175,24 +23668,17 @@ void zaxisDefLbounds(int zaxisID, const double *lbounds)
     zaxisptr->lbounds = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->lbounds, lbounds, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefUbounds(int zaxisID, const double *ubounds)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->ubounds != NULL )
@@ -24202,24 +23688,17 @@ void zaxisDefUbounds(int zaxisID, const double *ubounds)
     zaxisptr->ubounds = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->ubounds, ubounds, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefWeights(int zaxisID, const double *weights)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->weights != NULL )
@@ -24229,6 +23708,7 @@ void zaxisDefWeights(int zaxisID, const double *weights)
     zaxisptr->weights = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->weights, weights, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
@@ -24246,26 +23726,25 @@ void zaxisResize(int zaxisID, int size)
 {
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
+  xassert(size >= 0);
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   zaxisptr->size = size;
 
   if ( zaxisptr->vals )
-    zaxisptr->vals = (double *)xrealloc(zaxisptr->vals, size*sizeof(double));
+    zaxisptr->vals = (double *)xrealloc(zaxisptr->vals, (size_t)size * sizeof(double));
 }
 
 
 int zaxisDuplicate(int zaxisID)
 {
   int zaxisIDnew;
-  int zaxistype, zaxissize;
-  int size;
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxistype = zaxisInqType(zaxisID);
-  zaxissize = zaxisInqSize(zaxisID);
+  int zaxistype = zaxisInqType(zaxisID);
+  int zaxissize = zaxisInqSize(zaxisID);
 
   zaxisIDnew = zaxisCreate(zaxistype, zaxissize);
   zaxis_t *zaxisptrnew = reshGetVal(zaxisIDnew, &zaxisOps);
@@ -24278,37 +23757,37 @@ int zaxisDuplicate(int zaxisID)
 
   if ( zaxisptr->vals != NULL )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->vals = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->vals, zaxisptr->vals, size*sizeof(double));
+      zaxisptrnew->vals = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->vals, zaxisptr->vals, size * sizeof (double));
     }
 
   if ( zaxisptr->lbounds )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->lbounds = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->lbounds, zaxisptr->lbounds, size*sizeof(double));
+      zaxisptrnew->lbounds = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->lbounds, zaxisptr->lbounds, size * sizeof(double));
     }
 
   if ( zaxisptr->ubounds )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->ubounds = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->ubounds, zaxisptr->ubounds, size*sizeof(double));
+      zaxisptrnew->ubounds = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->ubounds, zaxisptr->ubounds, size * sizeof (double));
     }
 
   if ( zaxisptr->vct != NULL )
     {
-      size = zaxisptr->vctsize;
+      size_t size = (size_t)zaxisptr->vctsize;
 
       if ( size )
         {
-          zaxisptrnew->vctsize = size;
-          zaxisptrnew->vct = (double *)xmalloc(size*sizeof(double));
-          memcpy(zaxisptrnew->vct, zaxisptr->vct, size*sizeof(double));
+          zaxisptrnew->vctsize = (int)size;
+          zaxisptrnew->vct = (double *)xmalloc(size * sizeof (double));
+          memcpy(zaxisptrnew->vct, zaxisptr->vct, size * sizeof (double));
         }
     }
 
@@ -24633,10 +24112,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & vals)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->vals = (double*) xmalloc(size * sizeof ( double ));
+      zaxisP->vals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->vals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -24646,10 +24125,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & lbounds)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->lbounds = (double*) xmalloc(size * sizeof (double));
+      zaxisP->lbounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->lbounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -24659,10 +24138,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & ubounds)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->ubounds = (double*) xmalloc(size * sizeof (double));
+      zaxisP->ubounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->ubounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -24672,10 +24151,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & weights)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->weights = (double*) xmalloc(size * sizeof (double));
+      zaxisP->weights = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->weights, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -24685,10 +24164,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if ( memberMask & vct )
     {
-      int size;
-      xassert((size = zaxisP->vctsize));
+      int size = zaxisP->vctsize;
+      xassert(size >= 0);
 
-      zaxisP->vct = (double*) xmalloc(size * sizeof (double));
+      zaxisP->vct = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->vct, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -24872,7 +24351,8 @@ void cdf_create(const char *path, int cmode, int *ncidp)
   chunksizehint = 16777216; /* 16 MB */
 #endif
 
-  if ( cdiNcChunksizehint != CDI_UNDEFID ) chunksizehint = cdiNcChunksizehint;
+  if ( cdiNcChunksizehint != CDI_UNDEFID )
+    chunksizehint = (size_t)cdiNcChunksizehint;
 
   cdi_nc__create_funcp my_nc__create =
     (cdi_nc__create_funcp)namespaceSwitchGet(NSSWITCH_NC__CREATE).func;
@@ -24917,7 +24397,8 @@ int cdf_open(const char *path, int omode, int *ncidp)
       /*
       if ( chunksizehint < ChunkSizeMin ) chunksizehint = ChunkSizeMin;
       */
-      if ( cdiNcChunksizehint != CDI_UNDEFID ) chunksizehint = cdiNcChunksizehint;
+      if ( cdiNcChunksizehint != CDI_UNDEFID )
+        chunksizehint = (size_t)cdiNcChunksizehint;
 
       /* FIXME: parallel part missing */
       status = nc__open(path, omode, &chunksizehint, ncidp);
@@ -25352,6 +24833,19 @@ void  cdf_get_vara_text(int ncid, int varid, const size_t start[],
 }
 
 
+void  cdf_get_vara_uchar(int ncid, int varid, const size_t start[], const size_t count[], unsigned char *tp)
+{
+  int status;
+
+  status = nc_get_vara_uchar(ncid, varid, start, count, tp);
+
+  if ( CDF_Debug || status != NC_NOERR )
+    Message("ncid = %d varid = %d", ncid, varid);
+
+  if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
+}
+
+
 void cdf_put_var_double(int ncid, int varid, const double *dp)
 {
   int status;
@@ -25539,7 +25033,7 @@ void cdf_put_att_double(int ncid, int varid, const char *name, nc_type xtype,
 }
 
 
-void cdf_get_att_text(int ncid, int varid, char *name, char *tp)
+void cdf_get_att_text(int ncid, int varid, const char *name, char *tp)
 {
   int status;
 
@@ -25551,8 +25045,22 @@ void cdf_get_att_text(int ncid, int varid, char *name, char *tp)
   if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
 }
 
+void cdf_get_att_string(int ncid, int varid, const char *name, char **tp)
+{
+#if  defined  (HAVE_NETCDF4)
+  int status;
+
+  status = nc_get_att_string(ncid, varid, name, tp);
+
+  if ( CDF_Debug || status != NC_NOERR )
+    Message("ncid = %d varid = %d name = %s", ncid, varid, name);
+
+  if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
+#endif
+}
+
 
-void cdf_get_att_int(int ncid, int varid, char *name, int *ip)
+void cdf_get_att_int(int ncid, int varid, const char *name, int *ip)
 {
   int status;
 
@@ -25565,7 +25073,7 @@ void cdf_get_att_int(int ncid, int varid, char *name, int *ip)
 }
 
 
-void cdf_get_att_double(int ncid, int varid, char *name, double *dp)
+void cdf_get_att_double(int ncid, int varid, const char *name, double *dp)
 {
   int status;
 
@@ -25699,28 +25207,28 @@ char *cdiStringError(int cdiErrno)
 
 void cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis)
 {
-  unsigned int *uparam = (unsigned int *) ¶m;
-  unsigned int upnum;
+  unsigned uparam = (unsigned)param;
+  unsigned upnum;
 
-  *pdis = 0xff   & *uparam;
-  *pcat = 0xff   & *uparam >> 8;
-  upnum = 0xffff & *uparam >> 16;
-  if ( upnum > 0x7fff ) upnum = 0x8000 - upnum;
-  *pnum = upnum;
+  *pdis = 0xff   & uparam;
+  *pcat = 0xff   & uparam >> 8;
+  upnum = 0xffff & uparam >> 16;
+  if ( upnum > 0x7fffU ) upnum = 0x8000U - upnum;
+  *pnum = (int)upnum;
 }
 
 
 int cdiEncodeParam(int pnum, int pcat, int pdis)
 {
-  unsigned int uparam, upnum;
+  unsigned uparam, upnum;
 
   if ( pcat < 0 || pcat > 255 ) pcat = 255;
   if ( pdis < 0 || pdis > 255 ) pdis = 255;
 
-  upnum = pnum;
-  if ( pnum < 0 ) upnum = 0x8000 - pnum;
+  upnum = (unsigned)pnum;
+  if ( pnum < 0 ) upnum = (unsigned)(0x8000 - pnum);
 
-  uparam = upnum << 16 | pcat << 8 | pdis;
+  uparam = upnum << 16 | (unsigned)(pcat << 8) | (unsigned)pdis;
 
   return ((int)uparam);
 }
@@ -25829,7 +25337,6 @@ char *cdiUnitNamePtr(int cdi_unit)
 #include <stdarg.h>
 #include <ctype.h>
 
-
 #ifdef HAVE_LIBNETCDF
 #endif
 
@@ -25879,32 +25386,14 @@ const char Filetypes[][9] = {
 
 int CDI_Debug   = 0;    /* If set to 1, debugging           */
 
-static int  STREAM_Debug = 0;   /* If set to 1, debugging */
-
 int cdiGribApiDebug     = 0;
 int cdiDefaultLeveltype = -1;
-static int cdiDataUnreduced = 0;
-static int cdiSortName = 0;
-static int cdiHaveMissval = 0;
-
-
-static int    streamCompareP ( void * streamptr1, void * streamptr2 );
-static void   streamDestroyP ( void * streamptr );
-static void   streamPrintP   ( void * streamptr, FILE * fp );
-static int    streamGetPackSize ( void * streamptr, void *context);
-static void   streamPack        ( void * streamptr, void * buff, int size, int * position, void *context );
-static int    streamTxCode      ( void );
+int cdiDataUnreduced = 0;
+int cdiSortName = 0;
+int cdiHaveMissval = 0;
 
-const resOps streamOps = {
-  streamCompareP,
-  streamDestroyP,
-  streamPrintP,
-  streamGetPackSize,
-  streamPack,
-  streamTxCode
-};
 
-long cdiGetenvInt(char *envName)
+static long cdiGetenvInt(char *envName)
 {
   char *envString;
   long envValue = -1;
@@ -25944,6 +25433,126 @@ long cdiGetenvInt(char *envName)
   return (envValue);
 }
 
+static void
+cdiPrintDefaults(void)
+{
+  fprintf(stderr, "default instID     :  %d\n"
+          "default modelID    :  %d\n"
+          "default tableID    :  %d\n"
+          "default missval    :  %g\n", cdiDefaultInstID,
+          cdiDefaultModelID, cdiDefaultTableID, cdiDefaultMissval);
+}
+
+void cdiPrintVersion(void)
+{
+  fprintf(stderr, "     CDI library version : %s\n", cdiLibraryVersion());
+#if  defined  (HAVE_LIBCGRIBEX)
+  fprintf(stderr, " CGRIBEX library version : %s\n", cgribexLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBGRIB_API)
+  fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersionString());
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+  fprintf(stderr, "  netCDF library version : %s\n", cdfLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBHDF5)
+  fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBSERVICE)
+  fprintf(stderr, " SERVICE library version : %s\n", srvLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+  fprintf(stderr, "   EXTRA library version : %s\n", extLibraryVersion());
+#endif
+#if  defined  (HAVE_LIBIEG)
+  fprintf(stderr, "     IEG library version : %s\n", iegLibraryVersion());
+#endif
+  fprintf(stderr, "    FILE library version : %s\n", fileLibraryVersion());
+}
+
+void cdiDebug(int level)
+{
+  if ( level == 1 || (level &  2) ) CDI_Debug = 1;
+
+  if ( CDI_Debug ) Message("debug level %d", level);
+
+  if ( level == 1 || (level &  4) ) memDebug(1);
+
+  if ( level == 1 || (level &  8) ) fileDebug(1);
+
+  if ( level == 1 || (level & 16) )
+    {
+#if  defined  (HAVE_LIBGRIB)
+      gribSetDebug(1);
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+      cdfDebug(1);
+#endif
+#if  defined  (HAVE_LIBSERVICE)
+      srvDebug(1);
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+      extDebug(1);
+#endif
+#if  defined  (HAVE_LIBIEG)
+      iegDebug(1);
+#endif
+    }
+
+  if ( CDI_Debug )
+    {
+      cdiPrintDefaults();
+      cdiPrintDatatypes();
+    }
+}
+
+
+int cdiHaveFiletype(int filetype)
+{
+  int status = 0;
+
+  switch (filetype)
+    {
+#if  defined  (HAVE_LIBSERVICE)
+    case FILETYPE_SRV:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBEXTRA)
+    case FILETYPE_EXT:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBIEG)
+    case FILETYPE_IEG:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBGRIB)
+#if  defined  (HAVE_LIBGRIB_API) || defined  (HAVE_LIBCGRIBEX)
+    case FILETYPE_GRB:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_LIBGRIB_API)
+    case FILETYPE_GRB2: { status = 1; break; }
+#endif
+#endif
+#if  defined  (HAVE_LIBNETCDF)
+    case FILETYPE_NC:   { status = 1; break; }
+#if  defined  (HAVE_NETCDF2)
+    case FILETYPE_NC2:  { status = 1; break; }
+#endif
+#if  defined  (HAVE_NETCDF4)
+    case FILETYPE_NC4:  { status = 1; break; }
+    case FILETYPE_NC4C: { status = 1; break; }
+#endif
+#endif
+    default: { status = 0; break; }
+    }
+
+  return (status);
+}
+
+void cdiDefTableID(int tableID)
+{
+  cdiDefaultTableID = tableID;
+  int modelID = cdiDefaultModelID = tableInqModel(tableID);
+  cdiDefaultInstID = modelInqInstitut(modelID);
+}
+
 static
 void cdiSetChunk(const char *chunkAlgo)
 {
@@ -26084,9 +25693,6 @@ void cdiInitialize(void)
 
       envString = getenv("PARTAB_PATH");
       if ( envString ) cdiPartabPath = strdup(envString);
-
-      envString = getenv("STREAM_DEBUG");
-      if ( envString ) STREAM_Debug = atoi(envString);
     }
 }
 
@@ -26105,108 +25711,6 @@ const char *strfiletype(int filetype)
 }
 
 
-stream_t *stream_to_pointer(int idx)
-{
-  return ( stream_t *) reshGetVal ( idx, &streamOps );
-}
-
-static
-void streamDefaultValue ( stream_t * streamptr )
-{
-  int i;
-
-  streamptr->self              = UNDEFID;
-  streamptr->accesstype        = UNDEFID;
-  streamptr->accessmode        = 0;
-  streamptr->filetype          = UNDEFID;
-  streamptr->byteorder         = UNDEFID;
-  streamptr->fileID            = 0;
-  streamptr->dimgroupID        = UNDEFID;
-  streamptr->filemode          = 0;
-  streamptr->numvals           = 0;
-  streamptr->filename          = NULL;
-  streamptr->record            = NULL;
-  streamptr->varsAllocated     = 0;
-  streamptr->nrecs             = 0;
-  streamptr->nvars             = 0;
-  streamptr->vars              = NULL;
-  streamptr->varinit           = 0;
-  streamptr->ncmode            = 0;
-  streamptr->curTsID           = UNDEFID;
-  streamptr->rtsteps           = 0;
-  streamptr->ntsteps           = UNDEFID;
-  streamptr->numTimestep       = 0;
-  streamptr->tsteps            = NULL;
-  streamptr->tstepsTableSize   = 0;
-  streamptr->tstepsNextID      = 0;
-  streamptr->historyID         = UNDEFID;
-  streamptr->vlistID           = UNDEFID;
-  streamptr->globalatts        = 0;
-  streamptr->localatts         = 0;
-  streamptr->vct.ilev          = 0;
-  streamptr->vct.mlev          = 0;
-  streamptr->vct.ilevID        = UNDEFID;
-  streamptr->vct.mlevID        = UNDEFID;
-  streamptr->unreduced         = cdiDataUnreduced;
-  streamptr->sortname          = cdiSortName;
-  streamptr->have_missval      = cdiHaveMissval;
-  streamptr->comptype          = COMPRESS_NONE;
-  streamptr->complevel         = 0;
-
-  basetimeInit(&streamptr->basetime);
-
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i]   = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i]   = UNDEFID;
-  for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->zaxisID[i]  = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncxvarID[i] = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncyvarID[i] = UNDEFID;
-  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncavarID[i] = UNDEFID;
-
-  streamptr->curfile           = 0;
-  streamptr->nfiles            = 0;
-  streamptr->fnames            = NULL;
-
-  streamptr->gribContainers    = NULL;
-  streamptr->vlistIDorig       = UNDEFID;
-}
-
-
-stream_t *stream_new_entry(void)
-{
-  stream_t *streamptr;
-
-  cdiInitialize(); /* ***************** make MT version !!! */
-
-  streamptr = (stream_t *) xmalloc(sizeof(stream_t));
-  streamDefaultValue ( streamptr );
-  streamptr->self = reshPut (( void * ) streamptr, &streamOps );
-
-  return streamptr;
-}
-
-
-void stream_delete_entry(stream_t *streamptr)
-{
-  int idx;
-
-  xassert ( streamptr );
-
-  idx = streamptr->self;
-  free ( streamptr );
-  reshRemove ( idx, &streamOps );
-
-  if ( STREAM_Debug )
-    Message("Removed idx %d from stream list", idx);
-}
-
-
-void stream_check_ptr(const char *caller, stream_t *streamptr)
-{
-  if ( streamptr == NULL )
-    Errorc("stream undefined!");
-}
-
-
 int streamSize(void)
 {
   return reshCountType ( &streamOps );
@@ -26240,364 +25744,6 @@ double cdiInqMissval(void)
   return (cdiDefaultMissval);
 }
 
-
-void vlist_check_contents(int vlistID)
-{
-  int index, nzaxis, zaxisID;
-
-  nzaxis = vlistNzaxis(vlistID);
-
-  for ( index = 0; index < nzaxis; index++ )
-    {
-      zaxisID = vlistZaxis(vlistID, index);
-      if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
-	cdiCheckZaxis(zaxisID);
-    }
-}
-
-
-int streamInqFileID(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->fileID);
-}
-
-/* not used anymore */
-/*
-void streamDefineTaxis(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  if ( streamptr->tsteps == NULL )
-    {
-      int varID, nvars;
-      int vlistID;
-
-      vlistID = streamptr->vlistID;
-
-      nvars = vlistNvars(vlistID);
-      for ( varID = 0; varID < nvars; varID++ )
-	if ( vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT ) break;
-
-      if ( varID == nvars )
-	{
-	  int taxisID;
-
-	  taxisID = vlistInqTaxis(vlistID);
-	  if ( taxisID == CDI_UNDEFID )
-	    {
-	      taxisID = taxisCreate(TAXIS_ABSOLUTE);
-	      vlistDefTaxis(vlistID, taxisID);
-	    }
-
-	  (void) streamDefTimestep(streamID, 0);
-	}
-      else
-	Error("time axis undefined");
-    }
-}
-*/
-
-void streamDefDimgroupID(int streamID, int dimgroupID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  streamptr->dimgroupID = dimgroupID;
-}
-
-
-int streamInqDimgroupID(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->dimgroupID);
-}
-
-
-void cdiDefAccesstype(int streamID, int type)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  if ( streamptr->accesstype == UNDEFID )
-    {
-      streamptr->accesstype = type;
-    }
-  else
-    {
-      if ( streamptr->accesstype != type )
-	{
-	  if ( streamptr->accesstype == TYPE_REC )
-	    Error("Changing access type from REC to VAR not allowed!");
-	  else
-	    Error("Changing access type from VAR to REC not allowed!");
-	}
-    }
-}
-
-
-int cdiInqAccesstype(int streamID)
-{
-  stream_t *streamptr;
-
-  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
-
-  return (streamptr->accesstype);
-} 
-
-
-int streamInqNvars ( int streamID )
-{
-  stream_t * streamptr;
-  streamptr = ( stream_t * ) reshGetVal ( streamID, &streamOps );
-  return ( streamptr->nvars );
-}
-
-
-int  streamCompareP ( void * streamptr1, void * streamptr2 )
-{
-  stream_t * s1 = ( stream_t * ) streamptr1;
-  stream_t * s2 = ( stream_t * ) streamptr2;
-  int differ = -1;
-  int equal  = 0;
-  int len;
-
-  xassert ( s1 );
-  xassert ( s2 );
-
-  if ( s1->filetype  != s2->filetype  ) return differ;
-  if (  namespaceAdaptKey2 ( s1->vlistIDorig ) !=
-	namespaceAdaptKey2 ( s2->vlistIDorig )) return differ;
-  if ( s1->byteorder != s2->byteorder ) return differ;
-  if ( s1->comptype  != s2->comptype  ) return differ;
-  if ( s1->complevel != s2->complevel ) return differ;
-
-  if ( s1->filename )
-    {
-      len = strlen ( s1->filename ) + 1;
-      if ( memcmp ( s1->filename, s2->filename, len ))
-	return differ;
-    }
-  else if ( s2->filename )
-    return differ;
-
-  return equal;
-}
-
-
-void streamDestroyP ( void * streamptr )
-{
-  int id;
-  stream_t * sp = ( stream_t * ) streamptr;
-
-  xassert ( sp );
-
-  id = sp->self;
-  streamClose ( id );
-}
-
-
-void streamPrintP   ( void * streamptr, FILE * fp )
-{
-  stream_t * sp = ( stream_t * ) streamptr;
-
-  if ( !sp ) return;
-
-  fprintf ( fp, "#\n");
-  fprintf ( fp, "# streamID %d\n", sp->self);
-  fprintf ( fp, "#\n");
-  fprintf ( fp, "self          = %d\n", sp->self );
-  fprintf ( fp, "accesstype    = %d\n", sp->accesstype );
-  fprintf ( fp, "accessmode    = %d\n", sp->accessmode );
-  fprintf ( fp, "filetype      = %d\n", sp->filetype );
-  fprintf ( fp, "byteorder     = %d\n", sp->byteorder );
-  fprintf ( fp, "fileID        = %d\n", sp->fileID );
-  fprintf ( fp, "dimgroupID    = %d\n", sp->dimgroupID );
-  fprintf ( fp, "filemode      = %d\n", sp->filemode );
-  fprintf ( fp, "//off_t numvals;\n" );
-  fprintf ( fp, "filename      = %s\n", sp->filename );
-  fprintf ( fp, "//Record   *record;\n" );
-  fprintf ( fp, "nrecs         = %d\n", sp->nrecs );
-  fprintf ( fp, "nvars         = %d\n", sp->nvars );
-  fprintf ( fp, "varlocked     = %d\n", sp->varlocked );
-  fprintf ( fp, "//svarinfo_t *vars;\n" );
-  fprintf ( fp, "varsAllocated = %d\n", sp->varsAllocated );
-  fprintf ( fp, "varinit       = %d\n", sp->varinit );
-  fprintf ( fp, "curTsID       = %d\n", sp->curTsID );
-  fprintf ( fp, "rtsteps       = %d\n", sp->rtsteps );
-  fprintf ( fp, "//long ntsteps;\n" );
-  fprintf ( fp, "numTimestep   = %d\n", sp->numTimestep );
-  fprintf ( fp, "//  tsteps_t   *tsteps;\n" );
-  fprintf ( fp, "tstepsTableSize= %d\n", sp->tstepsTableSize );
-  fprintf ( fp, "tstepsNextID  = %d\n", sp->tstepsNextID );
-  fprintf ( fp, "//basetime_t  basetime;\n" );
-  fprintf ( fp, "ncmode        = %d\n", sp->ncmode );
-  fprintf ( fp, "vlistID       = %d\n", sp->vlistID );
-  fprintf ( fp, "//  int       xdimID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ydimID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       zaxisID[MAX_ZAXES_PS];\n" );
-  fprintf ( fp, "//  int       ncxvarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ncyvarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "//  int       ncavarID[MAX_GRIDS_PS];\n" );
-  fprintf ( fp, "historyID     = %d\n", sp->historyID );
-  fprintf ( fp, "globalatts    = %d\n", sp->globalatts );
-  fprintf ( fp, "localatts     = %d\n", sp->localatts );
-  fprintf ( fp, "//  VCT       vct;\n" );
-  fprintf ( fp, "unreduced     = %d\n", sp->unreduced );
-  fprintf ( fp, "sortname      = %d\n", sp->sortname );
-  fprintf ( fp, "have_missval  = %d\n", sp->have_missval );
-  fprintf ( fp, "ztype         = %d\n", sp->comptype );
-  fprintf ( fp, "zlevel        = %d\n", sp->complevel );
-  fprintf ( fp, "curfile       = %d\n", sp->curfile );
-  fprintf ( fp, "nfiles        = %d\n", sp->nfiles );
-  fprintf ( fp, "//  char    **fnames;\n" );
-  fprintf ( fp, "//  void    **gribContainers;\n" );
-  fprintf ( fp, "vlistIDorig   = %d\n", sp->vlistIDorig );
-}
-
-
-void streamGetIndexList ( int nstreams, int * streamIndexList )
-{
-  reshGetResHListOfType ( nstreams, streamIndexList, &streamOps );
-}
-
-void
-cdiStreamSetupVlist(stream_t *streamptr, int vlistID, int vlistIDorig)
-{
-  int nvars = vlistNvars(vlistID);
-  streamptr->vlistID = vlistID;
-  streamptr->vlistIDorig = vlistIDorig;
-  for (int varID = 0; varID < nvars; varID++ )
-    {
-      int gridID  = vlistInqVarGrid(vlistID, varID);
-      int zaxisID = vlistInqVarZaxis(vlistID, varID);
-      stream_new_var(streamptr, gridID, zaxisID);
-      if ( streamptr->have_missval )
-        vlistDefVarMissval(vlistID, varID,
-                           vlistInqVarMissval(vlistID, varID));
-    }
-
-  if (streamptr->filemode == 'w' )
-    {
-      if ( streamptr->filetype == FILETYPE_NC  ||
-           streamptr->filetype == FILETYPE_NC2 ||
-           streamptr->filetype == FILETYPE_NC4 ||
-           streamptr->filetype == FILETYPE_NC4C )
-        {
-#ifdef HAVE_LIBNETCDF
-          void (*myCdfDefVars)(stream_t *streamptr)
-            = (void (*)(stream_t *))
-            namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
-          myCdfDefVars(streamptr);
-#endif
-        }
-      else if ( streamptr->filetype == FILETYPE_GRB  ||
-                streamptr->filetype == FILETYPE_GRB2 )
-        {
-          gribContainersNew(streamptr);
-        }
-    }
-}
-
-
-static int
-streamTxCode(void)
-{
-  return STREAM;
-}
-
-
-int streamNint = 11 ;
-
-
-static int
-streamGetPackSize(void * voidP, void *context)
-{
-  stream_t * streamP = ( stream_t * ) voidP;
-  int packBufferSize
-    = serializeGetSize(streamNint, DATATYPE_INT, context)
-    + serializeGetSize(2, DATATYPE_UINT32, context)
-    + serializeGetSize((int)strlen(streamP->filename) + 1,
-                       DATATYPE_TXT, context)
-    + serializeGetSize(1, DATATYPE_FLT64, context);
-  return packBufferSize;
-}
-
-
-static void
-streamPack(void * streamptr, void * packBuffer, int packBufferSize,
-           int * packBufferPos, void *context)
-{
-  stream_t * streamP = ( stream_t * ) streamptr;
-  int intBuffer[streamNint];
-
-  intBuffer[0]  = streamP->self;
-  intBuffer[1]  = streamP->filetype;
-  intBuffer[2]  = (int)strlen(streamP->filename) + 1;
-  intBuffer[3]  = streamP->vlistID;
-  intBuffer[4]  = streamP->vlistIDorig;
-  intBuffer[5]  = streamP->byteorder;
-  intBuffer[6]  = streamP->comptype;
-  intBuffer[7]  = streamP->complevel;
-  intBuffer[8]  = cdiDataUnreduced;
-  intBuffer[9]  = cdiSortName;
-  intBuffer[10] = cdiHaveMissval;
-
-  serializePack(intBuffer, streamNint, DATATYPE_INT, packBuffer, packBufferSize, packBufferPos, context);
-  uint32_t d = cdiCheckSum(DATATYPE_INT, streamNint, intBuffer);
-  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
-
-  serializePack(&cdiDefaultMissval, 1, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context);
-  serializePack(streamP->filename, intBuffer[2], DATATYPE_TXT, packBuffer, packBufferSize, packBufferPos, context);
-  d = cdiCheckSum(DATATYPE_TXT, intBuffer[2], streamP->filename);
-  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
-}
-
-struct streamAssoc
-streamUnpack(char * unpackBuffer, int unpackBufferSize,
-             int * unpackBufferPos, int originNamespace, void *context)
-{
-  int intBuffer[streamNint], streamID;
-  uint32_t d;
-  char filename[CDI_MAX_NAME];
-
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  intBuffer, streamNint, DATATYPE_INT, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &d, 1, DATATYPE_UINT32, context);
-  xassert(cdiCheckSum(DATATYPE_INT, streamNint, intBuffer) == d);
-
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &cdiDefaultMissval, 1, DATATYPE_FLT64, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &filename, intBuffer[2], DATATYPE_TXT, context);
-  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
-                  &d, 1, DATATYPE_UINT32, context);
-  xassert(d == cdiCheckSum(DATATYPE_TXT, intBuffer[2], filename));
-  streamID = streamOpenWrite ( filename, intBuffer[1] );
-  xassert ( streamID >= 0 &&
-            namespaceAdaptKey ( intBuffer[0], originNamespace ) == streamID );
-  streamDefByteorder(streamID, intBuffer[5]);
-  streamDefCompType(streamID, intBuffer[6]);
-  streamDefCompLevel(streamID, intBuffer[7]);
-  cdiDefGlobal("REGULARGRID", intBuffer[8]);
-  cdiDefGlobal("SORTNAME", intBuffer[9]);
-  cdiDefGlobal("HAVE_MISSVAL", intBuffer[10]);
-  struct streamAssoc retval = { streamID, intBuffer[3], intBuffer[4] };
-  return retval;
-}
-
-
 /*
  * Local Variables:
  * c-file-style: "Java"
@@ -26621,93 +25767,25 @@ streamUnpack(char * unpackBuffer, int unpackBufferSize,
 
 
 
-#define  MAX_FNAMES  3
-
-static void
-cdiPrintDefaults(void)
-{
-  fprintf (stderr, "default instID     :  %d\n", cdiDefaultInstID);
-  fprintf (stderr, "default modelID    :  %d\n", cdiDefaultModelID);
-  fprintf (stderr, "default tableID    :  %d\n", cdiDefaultTableID);
-  fprintf (stderr, "default missval    :  %g\n", cdiDefaultMissval);
-}
-
-
-void cdiDebug(int level)
-{
-  if ( level == 1 || (level &  2) ) CDI_Debug = 1;
-
-  if ( CDI_Debug ) Message("debug level %d", level);
-
-  if ( level == 1 || (level &  4) ) memDebug(1);
-
-  if ( level == 1 || (level &  8) ) fileDebug(1);
-
-  if ( level == 1 || (level & 16) )
-    {
-#if  defined  (HAVE_LIBGRIB)
-      gribSetDebug(1);
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-      cdfDebug(1);
-#endif
-#if  defined  (HAVE_LIBSERVICE)
-      srvDebug(1);
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-      extDebug(1);
-#endif
-#if  defined  (HAVE_LIBIEG)
-      iegDebug(1);
-#endif
-    }
-
-  if ( CDI_Debug )
-    {
-      cdiPrintDefaults();
-      cdiPrintDatatypes();
-    }
-}
-
+static stream_t *stream_new_entry(void);
+static void stream_delete_entry(stream_t *streamptr);
+static int streamCompareP(void * streamptr1, void * streamptr2);
+static void streamDestroyP(void * streamptr);
+static void streamPrintP(void * streamptr, FILE * fp);
+static int streamGetPackSize(void * streamptr, void *context);
+static void streamPack(void * streamptr, void * buff, int size, int * position, void *context);
+static int streamTxCode(void);
 
-int cdiHaveFiletype(int filetype)
-{
-  int status = 0;
+const resOps streamOps = {
+  streamCompareP,
+  streamDestroyP,
+  streamPrintP,
+  streamGetPackSize,
+  streamPack,
+  streamTxCode
+};
 
-  switch (filetype)
-    {
-#if  defined  (HAVE_LIBSERVICE)
-    case FILETYPE_SRV:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-    case FILETYPE_EXT:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBIEG)
-    case FILETYPE_IEG:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBGRIB)
-#if  defined  (HAVE_LIBGRIB_API) || defined  (HAVE_LIBCGRIBEX)
-    case FILETYPE_GRB:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBGRIB_API)
-    case FILETYPE_GRB2: { status = 1; break; }
-#endif
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-    case FILETYPE_NC:   { status = 1; break; }
-#if  defined  (HAVE_NETCDF2)
-    case FILETYPE_NC2:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_NETCDF4)
-    case FILETYPE_NC4:  { status = 1; break; }
-    case FILETYPE_NC4C: { status = 1; break; }
-#endif
-#endif
-    default: { status = 0; break; }
-    }
 
-  return (status);
-}
 
 
 #undef  IsBigendian
@@ -26734,18 +25812,16 @@ int getByteorder(int byteswap)
   return (byteorder);
 }
 
-
 static
 int getFiletype(const char *filename, int *byteorder)
 {
   int filetype = CDI_EUFTYPE;
-  int fileID;
   int swap = 0;
   int version;
   long recpos;
   char buffer[8];
 
-  fileID = fileOpen(filename, "r");
+  int fileID = fileOpen(filename, "r");
 
   if ( fileID == CDI_UNDEFID )
     {
@@ -26830,146 +25906,13 @@ int getFiletype(const char *filename, int *byteorder)
   return (filetype);
 }
 
+/*
+ at Function  streamInqFiletype
+ at Title     Get the filetype
 
-int _readline_(FILE *fp, char *line, int len)
-{
-  int ichar, ipos = 0;
-
-  while ( (ichar = fgetc(fp)) != EOF )
-    {
-      if ( ichar == '\n' ) break;
-      line[ipos++] = ichar;
-      if ( ipos >= len )
-        {
-          fprintf(stderr, "readline Warning: end of line not found (maxlen = %d)!\n", len);
-          break;
-        }
-    }
-  line[ipos] = 0;
-
-  if ( feof(fp) && ipos == 0 ) return (0);
-
-  return (1);
-}
-
-#define  MAX_LINE  4096
-
-int get_fnames(const char *argument, char *fnames[], int max_fnames)
-{
-  int num_fnames = 0;
-  int len;
-  int nfiles = 0;
-  int i, j;
-  const char *pch;
-  char line[MAX_LINE];
-
-  len = (int) strlen(argument);
-  for ( i = 0; i < len; ++i )
-    if ( argument[i] == ':' ) break;
-
-  if ( i < len )
-    {
-      pch = &argument[i+1];
-      len -= (i+1);
-      if ( len && ( memcmp(argument, "filelist:", i) == 0 ||
-		    memcmp(argument, "flist:", i) == 0 ) )
-	{
-	  for ( i = 0; i < len; ++i ) if ( pch[i] == ',' ) nfiles++;
-
-	  if ( nfiles == 0 )
-	    {
-	      FILE *fp;
-	      fp = fopen(pch, "r");
-	      if ( fp == NULL ) Error("Open failed on %s", pch);
-
-	      if ( CDI_Debug )
-		Message("Reading file names from %s", pch);
-
-	      rewind(fp);
-
-	      nfiles = 0;
-	      while ( _readline_(fp, line, MAX_LINE) )
-		{
-		  if ( line[0] == '#' || line[0] == '\0' ||
-		       line[0] == ' ' ) continue;
-
-		  if ( nfiles >= max_fnames )
-		    {
-		      Warning("Too many input files (limit: %d)", max_fnames);
-		      break;
-		    }
-		  fnames[nfiles] = strdupx(line);
-		  nfiles++;
-		}
-
-	      fclose(fp);
-
-	      if ( nfiles == 0 ) Error("No input file found in %s", pch);
-	    }
-	  else
-	    {
-	      char xline[65536];
-
-	      strcpy(xline, pch);
-	      for ( i = 0; i < len; i++ ) if ( xline[i] == ',' ) xline[i] = 0;
-
-	      nfiles++;
-	      if ( nfiles >= max_fnames )
-		{
-		  Warning("Too many input files (limit: %d)", max_fnames);
-		  nfiles = max_fnames;
-		}
-
-	      i = 0;
-	      for ( j = 0; j < nfiles; j++ )
-		{
-		  fnames[j] = strdupx(&xline[i]);
-		  i += strlen(&xline[i]) + 1;
-		}
-	    }
-	}
-      else if ( len && memcmp(argument, "ls:", i) == 0 )
-	{
-	  char command[4096];
-	  FILE *pfp;
-
-	  strcpy(command, "ls ");
-	  strcat(command, pch);
-
-	  pfp = popen(command, "r");
-	  if ( pfp == NULL ) SysError("popen %s failed", command);
-
-	  nfiles = 0;
-	  while ( _readline_(pfp, line, MAX_LINE) )
-	    {
-	      if ( nfiles >= max_fnames )
-		{
-		  Warning("Too many input files (limit: %d)", max_fnames);
-		  break;
-		}
-	      fnames[nfiles++] = strdupx(line);
-	    }
-
-	  pclose(pfp);
-	  /*
-	  for ( j = 0; j < nfiles; j++ )
-	    fnames[j] = fnames[j];
-	  */
-	}
-    }
-
-  num_fnames = nfiles;
-
-  return (num_fnames);
-}
-
-/*
- at Function  streamInqFiletype
- at Title     Get the filetype
-
- at Prototype int streamInqFiletype(int streamID)
- at Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
+ at Prototype int streamInqFiletype(int streamID)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
 
 @Description
 The function @func{streamInqFiletype} returns the filetype of a stream.
@@ -27032,12 +25975,6 @@ void streamDefByteorder(int streamID, int byteorder)
 
   stream_check_ptr(__func__, streamptr);
 
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   streamptr->byteorder = byteorder;
   filetype = streamptr->filetype;
 
@@ -27071,6 +26008,7 @@ void streamDefByteorder(int streamID, int byteorder)
       }
 #endif
     }
+  reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -27124,20 +26062,18 @@ char *streamFilename(int streamID)
 }
 
 static
-int cdiInqTimeSize(int streamID)
+long cdiInqTimeSize(int streamID)
 {
-  int ntsteps;
   int tsID = 0, nrecs;
   stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  ntsteps = streamptr->ntsteps;
+  long ntsteps = streamptr->ntsteps;
 
-  if ( ntsteps == CDI_UNDEFID )
+  if ( ntsteps == (long)CDI_UNDEFID )
     while ( (nrecs = streamInqTimestep(streamID, tsID++)) )
-
-  ntsteps = streamptr->ntsteps;
+      ntsteps = streamptr->ntsteps;
 
   return (ntsteps);
 }
@@ -27145,12 +26081,9 @@ int cdiInqTimeSize(int streamID)
 static
 int cdiInqContents(stream_t * streamptr)
 {
-  int filetype;
-  int vlistID;
-  int taxisID;
   int status = 0;
 
-  filetype = streamptr->filetype;
+  int filetype = streamptr->filetype;
 
   switch (filetype)
     {
@@ -27205,15 +26138,13 @@ int cdiInqContents(stream_t * streamptr)
 
   if ( status == 0 )
     {
-      vlistID = streamptr->vlistID;
-      taxisID = vlistInqTaxis(vlistID);
-      if ( taxisID != -1 )
+      int vlistID = streamptr->vlistID;
+      int taxisID = vlistInqTaxis(vlistID);
+      if ( taxisID != CDI_UNDEFID )
         {
           taxis_t *taxisptr1 = &streamptr->tsteps[0].taxis;
           taxis_t *taxisptr2 = taxisPtr(taxisID);
           ptaxisCopy(taxisptr2, taxisptr1);
-          if ( taxisptr1->name     ) taxisptr2->name = taxisptr1->name;
-          if ( taxisptr1->longname ) taxisptr2->longname = taxisptr1->longname;
         }
     }
 
@@ -27353,16 +26284,14 @@ int streamOpen(const char *filename, const char *filemode, int filetype)
 
       if ( streamptr->filemode == 'r' )
 	{
-	  vlist_t *vlistptr;
-	  int vlistID;
-	  vlistID = vlistCreate();
+	  int vlistID = vlistCreate();
 	  if ( vlistID < 0 ) return(CDI_ELIMIT);
 
 	  streamptr->vlistID = vlistID;
 	  /* cdiReadByteorder(streamID); */
 	  status = cdiInqContents(streamptr);
 	  if ( status < 0 ) return (status);
-	  vlistptr = vlist_to_pointer(streamptr->vlistID);
+	  vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
 	  vlistptr->ntsteps = streamNtsteps(streamID);
 	}
     }
@@ -27407,7 +26336,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
   status = cdiInqContents(streamptr);
   if ( status < 0 ) return (status);
   vlistptr = vlist_to_pointer(streamptr->vlistID);
-  vlistptr->ntsteps = cdiInqTimeSize(streamID);
+  vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
 
   {
     void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
@@ -27521,46 +26450,21 @@ if ( streamID < 0 ) handle_error(streamID);
 @EndSource
 @EndFunction
 */
-int streamOpenRead(const char *filenames)
+int streamOpenRead(const char *filename)
 {
-  int filetype, byteorder;
-  int streamID;
-  int num_fnames = 0;
-  char *fnames[MAX_FNAMES];
-  const char *filename;
-
   cdiInitialize();
 
-  //num_fnames = get_fnames(filenames, fnames, MAX_FNAMES);
-
-  if ( num_fnames == 0 )
-    filename = filenames;
-  else
-    {
-      int i;
-      for ( i = 0; i < num_fnames; ++i ) printf("fnames: %d %s\n", i, fnames[i]);
-      filename = fnames[0];
-    }
-
-  filetype = getFiletype(filename, &byteorder);
+  int byteorder = 0;
+  int filetype = getFiletype(filename, &byteorder);
 
   if ( filetype < 0 ) return (filetype);
 
-  streamID = streamOpen(filename, "r", filetype);
+  int streamID = streamOpen(filename, "r", filetype);
 
   if ( streamID >= 0 )
     {
       stream_t *streamptr = stream_to_pointer(streamID);
       streamptr->byteorder = byteorder;
-
-      if ( num_fnames > 0 )
-	{
-	  int i;
-	  streamptr->nfiles = num_fnames;
-	  streamptr->fnames = (char **) malloc(num_fnames*sizeof(char *));
-	  for ( i = 0; i < num_fnames; ++i )
-	    streamptr->fnames[i] = fnames[i];
-	}
     }
 
   return (streamID);
@@ -27569,10 +26473,9 @@ int streamOpenRead(const char *filenames)
 
 int streamOpenAppend(const char *filename)
 {
-  int byteorder;
-
   cdiInitialize();
 
+  int byteorder = 0;
   int filetype = getFiletype(filename, &byteorder);
 
   if ( filetype < 0 ) return (filetype);
@@ -27635,6 +26538,81 @@ int streamOpenWrite(const char *filename, int filetype)
   return (streamOpen(filename, "w", filetype));
 }
 
+static
+void streamDefaultValue ( stream_t * streamptr )
+{
+  int i;
+
+  streamptr->self              = CDI_UNDEFID;
+  streamptr->accesstype        = CDI_UNDEFID;
+  streamptr->accessmode        = 0;
+  streamptr->filetype          = FILETYPE_UNDEF;
+  streamptr->byteorder         = CDI_UNDEFID;
+  streamptr->fileID            = 0;
+  streamptr->dimgroupID        = CDI_UNDEFID;
+  streamptr->filemode          = 0;
+  streamptr->numvals           = 0;
+  streamptr->filename          = NULL;
+  streamptr->record            = NULL;
+  streamptr->varsAllocated     = 0;
+  streamptr->nrecs             = 0;
+  streamptr->nvars             = 0;
+  streamptr->vars              = NULL;
+  streamptr->varinit           = 0;
+  streamptr->ncmode            = 0;
+  streamptr->curTsID           = CDI_UNDEFID;
+  streamptr->rtsteps           = 0;
+  streamptr->ntsteps           = CDI_UNDEFID;
+  streamptr->numTimestep       = 0;
+  streamptr->tsteps            = NULL;
+  streamptr->tstepsTableSize   = 0;
+  streamptr->tstepsNextID      = 0;
+  streamptr->historyID         = CDI_UNDEFID;
+  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->complevel         = 0;
+
+  basetimeInit(&streamptr->basetime);
+
+  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_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->curfile           = 0;
+  streamptr->nfiles            = 0;
+  streamptr->fnames            = NULL;
+
+  streamptr->gribContainers    = NULL;
+  streamptr->vlistIDorig       = CDI_UNDEFID;
+}
+
+
+static stream_t *stream_new_entry(void)
+{
+  stream_t *streamptr;
+
+  cdiInitialize(); /* ***************** make MT version !!! */
+
+  streamptr = (stream_t *) xmalloc(sizeof(stream_t));
+  streamDefaultValue ( streamptr );
+  streamptr->self = reshPut (( void * ) streamptr, &streamOps );
+
+  return streamptr;
+}
+
+
 void
 cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
 {
@@ -27759,10 +26737,13 @@ void streamClose(int streamID)
 	free(streamptr->tsteps[index].records);
       if ( streamptr->tsteps[index].recIDs )
 	free(streamptr->tsteps[index].recIDs);
+      taxisDestroyKernel(&streamptr->tsteps[index].taxis);
     }
 
   if ( streamptr->tsteps ) free(streamptr->tsteps);
 
+  if ( streamptr->basetime.timevar_cache ) free(streamptr->basetime.timevar_cache);
+
   if ( streamptr->nfiles > 0 )
     {
       for ( index = 0; index < streamptr->nfiles; ++index )
@@ -27779,12 +26760,28 @@ void streamClose(int streamID)
 	    taxisDestroy(vlistInqTaxis(vlistID));
 	  }
 
+      vlist_unlock(vlistID);
       vlistDestroy(vlistID);
     }
 
   stream_delete_entry(streamptr);
 }
 
+static void stream_delete_entry(stream_t *streamptr)
+{
+  int idx;
+
+  xassert ( streamptr );
+
+  idx = streamptr->self;
+  free ( streamptr );
+  reshRemove ( idx, &streamOps );
+
+  if ( CDI_Debug )
+    Message("Removed idx %d from stream list", idx);
+}
+
+
 void cdiStreamSync_(stream_t *streamptr)
 {
   int fileID   = streamptr->fileID;
@@ -27886,11 +26883,6 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
       taxis_t *taxisptr1 = taxisPtr(taxisID);
       taxis_t *taxisptr2 = &streamptr->tsteps[tsID].taxis;
       ptaxisCopy(taxisptr2, taxisptr1);
-      if ( tsID == 0 )
-        {
-          if ( taxisptr1->name     ) taxisptr2->name = taxisptr1->name;
-          if ( taxisptr1->longname ) taxisptr2->longname = taxisptr1->longname;
-        }
     }
 
   streamptr->ntsteps = tsID + 1;
@@ -27911,7 +26903,7 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
 
   cdi_create_records(streamptr, tsID);
 
-  return (streamptr->ntsteps);
+  return (int)streamptr->ntsteps;
 }
 
 /*
@@ -28054,24 +27046,9 @@ int streamInqTimestep(int streamID, int tsID)
   return (nrecs);
 }
 
-/*
- at Function  streamReadVar
- at Title     Read a variable
-
- at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
- at Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
-    @Item  varID     Variable identifier.
-    @Item  data      Pointer to the location into which the data values are read.
-                     The caller must allocate space for the returned values.
-    @Item  nmiss     Number of missing values.
-
- at Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+/* the single image implementation */
+static
+void cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamID, varID);
 
@@ -28092,6 +27069,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("grbReadVar not implemented for memtype float!");
         grbReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -28099,6 +27077,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("srvReadVar not implemented for memtype float!");
         srvReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -28106,6 +27085,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("extReadVar not implemented for memtype float!");
         extReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -28113,6 +27093,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("iegReadVar not implemented for memtype float!");
         iegReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -28123,7 +27104,11 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
       {
-        cdfReadVarDP(streamptr, varID, data, nmiss);
+        if ( memtype == MEMTYPE_FLOAT )
+          cdfReadVarSP(streamptr, varID, data, nmiss);
+        else
+          cdfReadVarDP(streamptr, varID, data, nmiss);
+
 	break;
       }
 #endif
@@ -28135,36 +27120,52 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     }
 }
 
+/*
+ at Function  streamReadVar
+ at Title     Read a variable
+
+ at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+{
+  cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+}
 
 /*
- at Function  streamWriteVar
- at Title     Write a variable
+ at Function  streamReadVarF
+ at Title     Read a variable
 
- at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+ at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
 @Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
     @Item  varID     Variable identifier.
-    @Item  data      Pointer to a block of double precision floating point data values to be written.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamWriteVar writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
 @EndFunction
 */
-void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
 {
-  void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
-                               const void *data, int nmiss)
-    = (void (*)(int, int, int, const void *, int))
-    namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
-  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+  cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
 }
 
 /* the single image implementation */
-void
-cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
-                   int nmiss)
+void cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
 
@@ -28233,51 +27234,63 @@ cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
 }
 
 /*
- at Function  streamWriteVarF
+ at Function  streamWriteVar
 @Title     Write a variable
 
- at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+ at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
 @Parameter
     @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
     @Item  varID     Variable identifier.
-    @Item  data      Pointer to a block of single precision floating point data values to be written.
+    @Item  data      Pointer to a block of double precision floating point data values to be written.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The function streamWriteVar writes the values of one time step of a variable to an open dataset.
 The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
 @EndFunction
 */
-void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
 {
   void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
                                const void *data, int nmiss)
     = (void (*)(int, int, int, const void *, int))
     namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
-  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
 }
 
 /*
- at Function  streamReadVarSlice
- at Title     Read a horizontal slice of a variable
+ at Function  streamWriteVarF
+ at Title     Write a variable
 
- at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
 @Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
     @Item  varID     Variable identifier.
-    @Item  levelID   Level identifier.
-    @Item  data      Pointer to the location into which the data values are read.
-                     The caller must allocate space for the returned values.
+    @Item  data      Pointer to a block of single precision floating point data values to be written.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamReadVar reads all the values of a horizontal slice of a variable
-from an open dataset.
+The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+Only support for netCDF was implemented in this function.
 @EndFunction
 */
-void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+{
+  void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+                               const void *data, int nmiss)
+    = (void (*)(int, int, int, const void *, int))
+    namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+}
+
+static
+int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
 {
+  // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+  // A value > 0 is returned in this case, otherwise it returns zero.
+  int status = 0;
+
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamID, varID);
 
   check_parg(data);
@@ -28297,6 +27310,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         grbReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -28304,6 +27318,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         srvReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -28311,6 +27326,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         extReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -28318,6 +27334,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         iegReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -28328,21 +27345,86 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
       {
-        /* FIXME: status value ignored */
-        int ierr = cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
-	break;
+        if ( memtype == MEMTYPE_FLOAT )
+          cdfReadVarSliceSP(streamptr, varID, levelID, data, nmiss);
+        else
+          cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
+        break;
       }
 #endif
     default:
       {
 	Error("%s support not compiled in!", strfiletype(filetype));
+        status = 2;
 	break;
       }
     }
+
+  return status;
+}
+
+/*
+ at Function  streamReadVarSlice
+ at Title     Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  levelID   Level identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVarSlice reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+{
+  if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
+    {
+      Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
+      size_t elementCount = gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+      memset(data, 0, elementCount * sizeof(*data));
+    }
+}
+
+/*
+ at Function  streamReadVarSliceF
+ at Title     Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  levelID   Level identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+{
+  if ( cdiStreamReadVarSlice(streamID, varID,levelID, MEMTYPE_FLOAT, data, nmiss) )
+    {
+      // In case the file format does not support single precision reading,
+      // we fall back to double precision reading, converting the data on the fly.
+      size_t elementCount = gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+      double* conversionBuffer = malloc(elementCount * sizeof(*conversionBuffer));
+      streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+      for (size_t i = elementCount; i--; ) data[i] = conversionBuffer[i];
+      free(conversionBuffer);
+    }
 }
 
 static
-void stream_write_var_slice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
+void cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
 
@@ -28396,12 +27478,9 @@ void stream_write_var_slice(int streamID, int varID, int levelID, int memtype, c
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        int ierr = 0;
-	if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
-        ierr = cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-	break;
-      }
+      if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+      cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+      break;
 #endif
     default:
       {
@@ -28430,7 +27509,7 @@ The values are converted to the external data type of the variable, if necessary
 */
 void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
 {
-  stream_write_var_slice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
+  cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
 }
 
 /*
@@ -28453,7 +27532,7 @@ Only support for netCDF was implemented in this function.
 */
 void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
 {
-  stream_write_var_slice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
+  cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
 }
 
 
@@ -28617,53 +27696,17 @@ void streamWriteContents(int streamID, char *cname)
 }
 
 
-void cdiDefTableID(int tableID)
-{
-  cdiDefaultTableID = tableID;
-  int modelID = cdiDefaultModelID = tableInqModel(tableID);
-  cdiDefaultInstID = modelInqInstitut(modelID);
-}
-
-
-void cdiPrintVersion(void)
-{
-  fprintf(stderr, "     CDI library version : %s\n", cdiLibraryVersion());
-#if  defined  (HAVE_LIBCGRIBEX)
-  fprintf(stderr, " CGRIBEX library version : %s\n", cgribexLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBGRIB_API)
-  fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-  fprintf(stderr, "  netCDF library version : %s\n", cdfLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBHDF5)
-  fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBSERVICE)
-  fprintf(stderr, " SERVICE library version : %s\n", srvLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-  fprintf(stderr, "   EXTRA library version : %s\n", extLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBIEG)
-  fprintf(stderr, "     IEG library version : %s\n", iegLibraryVersion());
-#endif
-  fprintf(stderr, "    FILE library version : %s\n", fileLibraryVersion());
-}
-
-
 int streamNtsteps(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  return (streamptr->ntsteps);
+  return (int)streamptr->ntsteps;
 }
 
-
-off_t   streamNvals(int streamID)
+// This function is used in CDO!
+off_t streamNvals(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
@@ -28745,37 +27788,29 @@ int streamInqVlistIDorig(int streamID)
 
 void streamDefCompType(int streamID, int comptype)
 {
-  stream_t *streamptr;
-
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  streamptr->comptype = comptype;
+  if (streamptr->comptype != comptype)
+    {
+      streamptr->comptype = comptype;
+      reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void streamDefCompLevel(int streamID, int complevel)
 {
-  stream_t *streamptr;
-
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  streamptr->complevel = complevel;
+  if (streamptr->complevel != complevel)
+    {
+      streamptr->complevel = complevel;
+      reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -28797,6 +27832,309 @@ int streamInqCompLevel(int streamID)
 
   return (streamptr->complevel);
 }
+
+int streamInqFileID(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->fileID);
+}
+
+void streamDefDimgroupID(int streamID, int dimgroupID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  streamptr->dimgroupID = dimgroupID;
+}
+
+
+int streamInqDimgroupID(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->dimgroupID);
+}
+
+
+void cdiDefAccesstype(int streamID, int type)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  if ( streamptr->accesstype == CDI_UNDEFID )
+    {
+      streamptr->accesstype = type;
+    }
+  else
+    {
+      if ( streamptr->accesstype != type )
+	{
+	  if ( streamptr->accesstype == TYPE_REC )
+	    Error("Changing access type from REC to VAR not allowed!");
+	  else
+	    Error("Changing access type from VAR to REC not allowed!");
+	}
+    }
+}
+
+
+int cdiInqAccesstype(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->accesstype);
+}
+
+static
+int streamTxCode(void)
+{
+  return STREAM;
+}
+
+
+void cdiStreamSetupVlist(stream_t *streamptr, int vlistID, int vlistIDorig)
+{
+  vlist_lock(vlistID);
+  int nvars = vlistNvars(vlistID);
+  streamptr->vlistID = vlistID;
+  streamptr->vlistIDorig = vlistIDorig;
+  for (int varID = 0; varID < nvars; varID++ )
+    {
+      int gridID  = vlistInqVarGrid(vlistID, varID);
+      int zaxisID = vlistInqVarZaxis(vlistID, varID);
+      stream_new_var(streamptr, gridID, zaxisID);
+      if ( streamptr->have_missval )
+        vlistDefVarMissval(vlistID, varID,
+                           vlistInqVarMissval(vlistID, varID));
+    }
+
+  if (streamptr->filemode == 'w' )
+    {
+      if ( streamptr->filetype == FILETYPE_NC  ||
+           streamptr->filetype == FILETYPE_NC2 ||
+           streamptr->filetype == FILETYPE_NC4 ||
+           streamptr->filetype == FILETYPE_NC4C )
+        {
+#ifdef HAVE_LIBNETCDF
+          void (*myCdfDefVars)(stream_t *streamptr)
+            = (void (*)(stream_t *))
+            namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
+          myCdfDefVars(streamptr);
+#endif
+        }
+      else if ( streamptr->filetype == FILETYPE_GRB  ||
+                streamptr->filetype == FILETYPE_GRB2 )
+        {
+          gribContainersNew(streamptr);
+        }
+    }
+}
+
+
+void streamGetIndexList ( int nstreams, int * streamIndexList )
+{
+  reshGetResHListOfType ( nstreams, streamIndexList, &streamOps );
+}
+
+int streamInqNvars ( int streamID )
+{
+  stream_t * streamptr;
+  streamptr = ( stream_t * ) reshGetVal ( streamID, &streamOps );
+  return ( streamptr->nvars );
+}
+
+
+static int streamCompareP(void * streamptr1, void * streamptr2)
+{
+  stream_t * s1 = ( stream_t * ) streamptr1;
+  stream_t * s2 = ( stream_t * ) streamptr2;
+  enum {
+    differ = -1,
+    equal  = 0,
+  };
+
+  xassert ( s1 );
+  xassert ( s2 );
+
+  if ( s1->filetype  != s2->filetype  ) return differ;
+  if (  namespaceAdaptKey2 ( s1->vlistIDorig ) !=
+	namespaceAdaptKey2 ( s2->vlistIDorig )) return differ;
+  if ( s1->byteorder != s2->byteorder ) return differ;
+  if ( s1->comptype  != s2->comptype  ) return differ;
+  if ( s1->complevel != s2->complevel ) return differ;
+
+  if ( s1->filename )
+    {
+      if (strcmp(s1->filename, s2->filename))
+	return differ;
+    }
+  else if ( s2->filename )
+    return differ;
+
+  return equal;
+}
+
+
+void streamDestroyP ( void * streamptr )
+{
+  stream_t * sp = ( stream_t * ) streamptr;
+
+  xassert ( sp );
+
+  int id = sp->self;
+  streamClose ( id );
+}
+
+
+void streamPrintP   ( void * streamptr, FILE * fp )
+{
+  stream_t * sp = ( stream_t * ) streamptr;
+
+  if ( !sp ) return;
+
+  fprintf ( fp, "#\n");
+  fprintf ( fp, "# streamID %d\n", sp->self);
+  fprintf ( fp, "#\n");
+  fprintf ( fp, "self          = %d\n", sp->self );
+  fprintf ( fp, "accesstype    = %d\n", sp->accesstype );
+  fprintf ( fp, "accessmode    = %d\n", sp->accessmode );
+  fprintf ( fp, "filetype      = %d\n", sp->filetype );
+  fprintf ( fp, "byteorder     = %d\n", sp->byteorder );
+  fprintf ( fp, "fileID        = %d\n", sp->fileID );
+  fprintf ( fp, "dimgroupID    = %d\n", sp->dimgroupID );
+  fprintf ( fp, "filemode      = %d\n", sp->filemode );
+  fprintf ( fp, "//off_t numvals;\n" );
+  fprintf ( fp, "filename      = %s\n", sp->filename );
+  fprintf ( fp, "//Record   *record;\n" );
+  fprintf ( fp, "nrecs         = %d\n", sp->nrecs );
+  fprintf ( fp, "nvars         = %d\n", sp->nvars );
+  fprintf ( fp, "varlocked     = %d\n", sp->varlocked );
+  fprintf ( fp, "//svarinfo_t *vars;\n" );
+  fprintf ( fp, "varsAllocated = %d\n", sp->varsAllocated );
+  fprintf ( fp, "varinit       = %d\n", sp->varinit );
+  fprintf ( fp, "curTsID       = %d\n", sp->curTsID );
+  fprintf ( fp, "rtsteps       = %d\n", sp->rtsteps );
+  fprintf ( fp, "//long ntsteps;\n" );
+  fprintf ( fp, "numTimestep   = %d\n", sp->numTimestep );
+  fprintf ( fp, "//  tsteps_t   *tsteps;\n" );
+  fprintf ( fp, "tstepsTableSize= %d\n", sp->tstepsTableSize );
+  fprintf ( fp, "tstepsNextID  = %d\n", sp->tstepsNextID );
+  fprintf ( fp, "//basetime_t  basetime;\n" );
+  fprintf ( fp, "ncmode        = %d\n", sp->ncmode );
+  fprintf ( fp, "vlistID       = %d\n", sp->vlistID );
+  fprintf ( fp, "//  int       xdimID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ydimID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       zaxisID[MAX_ZAXES_PS];\n" );
+  fprintf ( fp, "//  int       ncxvarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ncyvarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ncavarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "historyID     = %d\n", sp->historyID );
+  fprintf ( fp, "globalatts    = %d\n", sp->globalatts );
+  fprintf ( fp, "localatts     = %d\n", sp->localatts );
+  fprintf ( fp, "//  VCT       vct;\n" );
+  fprintf ( fp, "unreduced     = %d\n", sp->unreduced );
+  fprintf ( fp, "sortname      = %d\n", sp->sortname );
+  fprintf ( fp, "have_missval  = %d\n", sp->have_missval );
+  fprintf ( fp, "ztype         = %d\n", sp->comptype );
+  fprintf ( fp, "zlevel        = %d\n", sp->complevel );
+  fprintf ( fp, "curfile       = %d\n", sp->curfile );
+  fprintf ( fp, "nfiles        = %d\n", sp->nfiles );
+  fprintf ( fp, "//  char    **fnames;\n" );
+  fprintf ( fp, "//  void    **gribContainers;\n" );
+  fprintf ( fp, "vlistIDorig   = %d\n", sp->vlistIDorig );
+}
+
+
+enum {
+  streamNint = 11,
+};
+
+static int
+streamGetPackSize(void * voidP, void *context)
+{
+  stream_t * streamP = ( stream_t * ) voidP;
+  int packBufferSize
+    = serializeGetSize(streamNint, DATATYPE_INT, context)
+    + serializeGetSize(2, DATATYPE_UINT32, context)
+    + serializeGetSize((int)strlen(streamP->filename) + 1,
+                       DATATYPE_TXT, context)
+    + serializeGetSize(1, DATATYPE_FLT64, context);
+  return packBufferSize;
+}
+
+
+static void
+streamPack(void * streamptr, void * packBuffer, int packBufferSize,
+           int * packBufferPos, void *context)
+{
+  stream_t * streamP = ( stream_t * ) streamptr;
+  int intBuffer[streamNint];
+
+  intBuffer[0]  = streamP->self;
+  intBuffer[1]  = streamP->filetype;
+  intBuffer[2]  = (int)strlen(streamP->filename) + 1;
+  intBuffer[3]  = streamP->vlistID;
+  intBuffer[4]  = streamP->vlistIDorig;
+  intBuffer[5]  = streamP->byteorder;
+  intBuffer[6]  = streamP->comptype;
+  intBuffer[7]  = streamP->complevel;
+  intBuffer[8]  = streamP->unreduced;
+  intBuffer[9]  = streamP->sortname;
+  intBuffer[10] = streamP->have_missval;
+
+  serializePack(intBuffer, streamNint, DATATYPE_INT, packBuffer, packBufferSize, packBufferPos, context);
+  uint32_t d = cdiCheckSum(DATATYPE_INT, streamNint, intBuffer);
+  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
+
+  serializePack(&cdiDefaultMissval, 1, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context);
+  serializePack(streamP->filename, intBuffer[2], DATATYPE_TXT, packBuffer, packBufferSize, packBufferPos, context);
+  d = cdiCheckSum(DATATYPE_TXT, intBuffer[2], streamP->filename);
+  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
+}
+
+struct streamAssoc
+streamUnpack(char * unpackBuffer, int unpackBufferSize,
+             int * unpackBufferPos, int originNamespace, void *context)
+{
+  int intBuffer[streamNint], streamID;
+  uint32_t d;
+  char filename[CDI_MAX_NAME];
+
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  intBuffer, streamNint, DATATYPE_INT, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &d, 1, DATATYPE_UINT32, context);
+  xassert(cdiCheckSum(DATATYPE_INT, streamNint, intBuffer) == d);
+
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &cdiDefaultMissval, 1, DATATYPE_FLT64, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &filename, intBuffer[2], DATATYPE_TXT, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &d, 1, DATATYPE_UINT32, context);
+  xassert(d == cdiCheckSum(DATATYPE_TXT, intBuffer[2], filename));
+  streamID = streamOpenWrite ( filename, intBuffer[1] );
+  xassert ( streamID >= 0 &&
+            namespaceAdaptKey ( intBuffer[0], originNamespace ) == streamID );
+  streamDefByteorder(streamID, intBuffer[5]);
+  streamDefCompType(streamID, intBuffer[6]);
+  streamDefCompLevel(streamID, intBuffer[7]);
+  stream_t *streamptr = stream_to_pointer(streamID);
+  streamptr->unreduced = intBuffer[8];
+  streamptr->sortname = intBuffer[9];
+  streamptr->have_missval = intBuffer[10];
+  struct streamAssoc retval = { streamID, intBuffer[3], intBuffer[4] };
+  return retval;
+}
 /*
  * Local Variables:
  * c-file-style: "Java"
@@ -28897,6 +28235,7 @@ typedef struct {
   int level1;
   int level2;
   int ltype;
+  int tsteptype;
 } compvar_t;
 
 
@@ -28933,7 +28272,7 @@ int cgribexGetIsRotated(int *isec2)
     {
       isRotated = 1;
     }
- 
+
   return (isRotated);
 }
 
@@ -28964,13 +28303,14 @@ int cgribexGetTimeUnit(int *isec1)
 
   switch ( ISEC1_TimeUnit )
     {
-    case ISEC1_TABLE4_MINUTE:  timeunit = TUNIT_MINUTE;  break;
-    case ISEC1_TABLE4_QUARTER: timeunit = TUNIT_QUARTER; break;
-    case ISEC1_TABLE4_HOUR:    timeunit = TUNIT_HOUR;    break;
-    case ISEC1_TABLE4_3HOURS:  timeunit = TUNIT_3HOURS;  break;
-    case ISEC1_TABLE4_6HOURS:  timeunit = TUNIT_6HOURS;  break;
-    case ISEC1_TABLE4_12HOURS: timeunit = TUNIT_12HOURS; break;
-    case ISEC1_TABLE4_DAY:     timeunit = TUNIT_DAY;     break;
+    case ISEC1_TABLE4_MINUTE:    timeunit = TUNIT_MINUTE;    break;
+    case ISEC1_TABLE4_QUARTER:   timeunit = TUNIT_QUARTER;   break;
+    case ISEC1_TABLE4_30MINUTES: timeunit = TUNIT_30MINUTES; break;
+    case ISEC1_TABLE4_HOUR:      timeunit = TUNIT_HOUR;      break;
+    case ISEC1_TABLE4_3HOURS:    timeunit = TUNIT_3HOURS;    break;
+    case ISEC1_TABLE4_6HOURS:    timeunit = TUNIT_6HOURS;    break;
+    case ISEC1_TABLE4_12HOURS:   timeunit = TUNIT_12HOURS;   break;
+    case ISEC1_TABLE4_DAY:       timeunit = TUNIT_DAY;       break;
     default:
       if ( lprint )
 	{
@@ -29012,7 +28352,7 @@ int cgribexGetTsteptype(int timerange)
     default:
       if ( lprint )
 	{
-	  Message("GRIB time range %d unsupported!", timerange);
+	  Message("Time range indicator %d unsupported, set to 0!", timerange);
 	  lprint = FALSE;
 	}
       break;
@@ -29024,9 +28364,8 @@ int cgribexGetTsteptype(int timerange)
 static
 void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, int iret)
 {
-  int gridtype;
-
-  gridtype = cgribexGetGridType(isec2);
+  int compyinc = TRUE;
+  int gridtype = cgribexGetGridType(isec2);
 
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
     {
@@ -29036,6 +28375,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
       gridtype = GRID_GAUSSIAN;
       ISEC2_NumLon = nlon;
       ISEC4_NumValues = nlon*ISEC2_NumLat;
+      compyinc = FALSE;
     }
 
   memset(grid, 0, sizeof(grid_t));
@@ -29092,10 +28432,9 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
 	grid->ydef  = 0;
 	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
 	  {
-	    if ( grid->ysize > 1 )
+	    if ( grid->ysize > 1 && compyinc )
 	      {
                 int recompinc = TRUE;
-
 		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
                   {
                     if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
@@ -29231,62 +28570,55 @@ static
 void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, double *fsec2, double *fsec3,
 		      int *isec4, long recsize, off_t position, int datatype, int comptype, int lmv, int iret)
 {
-  int zaxistype;
-  int gridID = CDI_UNDEFID, varID;
+  int varID;
   int levelID = 0;
-  int tsID, recID;
-  int level1, level2;
-  int numavg;
-  int tsteptype;
-  int lbounds = 0;
-  record_t *record;
   grid_t grid;
-  int vlistID;
 
-  vlistID = streamptr->vlistID;
-  tsID    = streamptr->curTsID;
-  recID   = recordNewEntry(streamptr, tsID);
-  record  = &streamptr->tsteps[tsID].records[recID];
+  int vlistID = streamptr->vlistID;
+  int tsID    = streamptr->curTsID;
+  int recID   = recordNewEntry(streamptr, tsID);
+  record_t *record  = &streamptr->tsteps[tsID].records[recID];
 
-  tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
-  numavg    = ISEC1_AvgNum;
+  int tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
+  int numavg    = ISEC1_AvgNum;
 
-  level1  = ISEC1_Level1;
-  level2  = ISEC1_Level2;
+  int level1  = ISEC1_Level1;
+  int level2  = ISEC1_Level2;
 
   /* fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, ISEC1_LevelType); */
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = ISEC1_LevelType;
+  record->size      = (size_t)recsize;
+  record->position  = position;
+  record->param     = param;
+  record->ilevel    = level1;
+  record->ilevel2   = level2;
+  record->ltype     = ISEC1_LevelType;
+  record->tsteptype = tsteptype;
 
   cgribexGetGrid(streamptr, isec2, isec4, &grid, iret);
 
-  gridID = varDefGrid(vlistID, grid, 0);
+  int gridID = varDefGrid(vlistID, grid, 0);
 
-  zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
+  int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
 
   if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
     {
-      int vctsize = ISEC2_NumVCP;
+      size_t vctsize = (size_t)ISEC2_NumVCP;
       double *vctptr = &fsec2[10];
 
       varDefVCT(vctsize, vctptr);
     }
 
-  lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
+  int lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
 
   if ( datatype > 32 ) datatype = DATATYPE_PACK32;
   if ( datatype <  0 ) datatype = DATATYPE_PACK;
 
   varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, 0, 0,
-	       datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   varDefCompType(varID, comptype);
 
@@ -29385,30 +28717,38 @@ void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
 }
 
 static
-compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype)
+compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int trange)
 {
   compvar_t compVar;
+  int tsteptype = cgribexGetTsteptype(trange);
 
-  compVar.param  = param;
-  compVar.level1 = level1;
-  compVar.level2 = level2;
-  compVar.ltype  = leveltype;
+  compVar.param     = param;
+  compVar.level1    = level1;
+  compVar.level2    = level2;
+  compVar.ltype     = leveltype;
+  compVar.tsteptype = tsteptype;
 
   return (compVar);
 }
 
 static
-int cgribexVarCompare(compvar_t compVar, record_t record)
+int cgribexVarCompare(compvar_t compVar, record_t record, int flag)
 {
-  int rstatus;
   compvar_t compVar0;
 
-  compVar0.param  = record.param;
-  compVar0.level1 = record.ilevel;
-  compVar0.level2 = record.ilevel2;
-  compVar0.ltype  = record.ltype;
+  compVar0.param     = record.param;
+  compVar0.level1    = record.ilevel;
+  compVar0.level2    = record.ilevel2;
+  compVar0.ltype     = record.ltype;
+  compVar0.tsteptype = record.tsteptype;
 
-  rstatus = memcmp(&compVar0, &compVar, sizeof(compvar_t));
+  if ( flag == 0 )
+    {
+      if ( compVar0.tsteptype == TSTEP_INSTANT  && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
+      if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT  ) compVar0.tsteptype = TSTEP_INSTANT;
+    }
+
+  int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar_t));
 
   return (rstatus);
 }
@@ -29425,7 +28765,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
   int lmv = 0, iret = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int rstatus;
   int fileID;
   int param = 0;
@@ -29491,13 +28831,13 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      if ( recsize > buffersize )
+      if ( (size_t)recsize > buffersize )
 	{
-	  buffersize = recsize;
+	  buffersize = (size_t)recsize;
 	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
-      readsize = recsize;
+      readsize = (size_t)recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
@@ -29506,16 +28846,16 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	{
 	  comptype = COMPRESS_SZIP;
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
 
       nrecs_scanned++;
       cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			  (int *) gribbuffer, recsize, &lmv, &iret);
+			  (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
       param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -29546,11 +28886,11 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
 	  for ( recID = 0; recID < nrecs; recID++ )
 	    {
-	      if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID]) == 0 ) break;
+	      if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
 	    }
 
 	  if ( cdiInventoryMode == 1 )
@@ -29618,8 +28958,8 @@ int cgribexScanTimestep1(stream_t * streamptr)
       taxis->unit  = tunit;
     }
 
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -29638,7 +28978,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
     streamptr->tsteps[0].recIDs[recID] = recID;
 
   streamptr->record->buffer     = gribbuffer;
-  streamptr->record->buffersize = buffersize;
+  streamptr->record->buffersize = (size_t)buffersize;
 
   if ( streamptr->ntsteps == -1 )
     {
@@ -29678,7 +29018,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
   int lmv = 0, iret = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int param = 0;
   int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -29749,28 +29089,28 @@ int cgribexScanTimestep2(stream_t * streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      if ( recsize > buffersize )
+      if ( (size_t)recsize > buffersize )
 	{
-	  buffersize = recsize;
-	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
+	  buffersize = (size_t)recsize;
+	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
-      readsize = recsize;
+      readsize = (size_t)recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
       if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
 
       cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			  (int *) gribbuffer, recsize, &lmv, &iret);
+			  (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
       nrecs_scanned++;
 
@@ -29825,11 +29165,11 @@ int cgribexScanTimestep2(stream_t * streamptr)
       datetime.date  = vdate;
       datetime.time  = vtime;
 
-      compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+      compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
       for ( recID = 0; recID < nrecords; recID++ )
 	{
-	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	}
 
       if ( recID == nrecords )
@@ -29869,9 +29209,9 @@ int cgribexScanTimestep2(stream_t * streamptr)
       if ( CDI_Debug )
 	Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
 
-      streamptr->tsteps[tsID].records[recID].size = recsize;
+      streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
 
-      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
@@ -29935,31 +29275,26 @@ int cgribexScanTimestep(stream_t * streamptr)
 {
   int rstatus = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
-  int *isec0, *isec1, *isec2, *isec3, *isec4;
   double fsec2[512], fsec3[2], *fsec4 = NULL;
   int lmv = 0, iret = 0;
   long recsize = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int param = 0;
   int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
   DateTime datetime, datetime0;
-  int tsID;
   int vrecID, recID;
   int warn_numavg = TRUE;
   size_t readsize;
   int taxisID = -1;
-  taxis_t *taxis;
-  int vlistID;
   int rindex, nrecs = 0;
   int nrecs_scanned;
   long unzipsize;
   compvar_t compVar;
   char paramstr[32];
 
-  vlistID = streamptr->vlistID;
   /*
   if ( CDI_Debug )
     {
@@ -29969,14 +29304,14 @@ int cgribexScanTimestep(stream_t * streamptr)
       Message("nts = %d", streamptr->ntsteps);
     }
   */
-  isec0 = streamptr->record->sec0;
-  isec1 = streamptr->record->sec1;
-  isec2 = streamptr->record->sec2;
-  isec3 = streamptr->record->sec3;
-  isec4 = streamptr->record->sec4;
+  int *isec0 = streamptr->record->sec0;
+  int *isec1 = streamptr->record->sec1;
+  int *isec2 = streamptr->record->sec2;
+  int *isec3 = streamptr->record->sec3;
+  int *isec4 = streamptr->record->sec4;
 
-  tsID  = streamptr->rtsteps;
-  taxis = &streamptr->tsteps[tsID].taxis;
+  int tsID  = streamptr->rtsteps;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -29988,7 +29323,7 @@ int cgribexScanTimestep(stream_t * streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -30009,15 +29344,15 @@ int cgribexScanTimestep(stream_t * streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  if ( recsize > buffersize )
+	  if ( recsize > 0 && (size_t)recsize > buffersize )
 	    {
-	      buffersize = recsize;
+	      buffersize = (size_t)recsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 
 	  if ( rindex >= nrecs ) break;
 
-	  readsize = recsize;
+	  readsize = (size_t)recsize;
 	  rstatus = gribRead(fileID, gribbuffer, &readsize);
 	  if ( rstatus )
 	    {
@@ -30029,15 +29364,15 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
 	    {
 	      unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	      if ( (long) buffersize < unzipsize )
+	      if ( buffersize < (size_t)unzipsize )
 		{
-		  buffersize = unzipsize;
+		  buffersize = (size_t)unzipsize;
 		  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 		}
 	    }
 
 	  cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			      (int *) gribbuffer, recsize, &lmv, &iret);
+			      (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
           nrecs_scanned++;
 
@@ -30055,6 +29390,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 
 	  if ( rindex == 0 )
 	    {
+              int vlistID = streamptr->vlistID;
 	      taxisID = vlistInqTaxis(vlistID);
 	      if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
 		{
@@ -30093,12 +29429,12 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
 	  for ( vrecID = 0; vrecID < nrecs; vrecID++ )
 	    {
 	      recID   = streamptr->tsteps[1].recIDs[vrecID];
-	      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	    }
 
 	  if ( vrecID == nrecs )
@@ -30140,7 +29476,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  if ( CDI_Debug )
             Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
 
-	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	    {
 	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		      tsID, recID,
@@ -30150,7 +29486,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
-	  streamptr->tsteps[tsID].records[recID].size = recsize;
+	  streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
 
 	  rindex++;
 	}
@@ -30194,7 +29530,7 @@ int cgribexScanTimestep(stream_t * streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  rstatus = streamptr->ntsteps;
+  rstatus = (int)streamptr->ntsteps;
 #endif
 
   return (rstatus);
@@ -30205,62 +29541,20 @@ int cgribexScanTimestep(stream_t * streamptr)
 #endif
 
 int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval)
+		  int unreduced, int *nmiss, double missval)
 {
   int status = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
   int iret = 0, iword = 0;
   int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
-  int izip;
-  long unzipsize;
   double fsec2[512], fsec3[2];
   char hoper[2];
 
-  *zip = 0;
-
   if ( unreduced ) strcpy(hoper, "R");
   else             strcpy(hoper, "D");
 
   FSEC3_MissVal = missval;
 
-  if ( (izip = gribGetZip(gribsize, gribbuffer, &unzipsize)) > 0 )
-    {
-      *zip = izip;
-      if ( izip == 128 ) /* szip */
-	{
-	  unsigned char *itmpbuffer = NULL;
-	  size_t itmpbuffersize = 0;
-
-	  if ( unzipsize < (long) gribsize )
-	    {
-	      fprintf(stderr, "Decompressed size smaller than compressed size (in %d; out %ld)!\n",
-		      gribsize, unzipsize);
-	      return (status);
-	    }
-
-	  if ( itmpbuffersize < (size_t) gribsize )
-	    {
-	      itmpbuffersize = gribsize;
-	      itmpbuffer = (unsigned char *) realloc(itmpbuffer, itmpbuffersize);
-	    }
-
-	  memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
-
-	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-
-	  gribsize = gribUnzip(gribbuffer, unzipsize, itmpbuffer, gribsize);
-
-	  if ( gribsize <= 0 )
-	    Error("Decompression problem!");
-
-	  free(itmpbuffer);
-	}
-      else
-	{
-	  Error("Decompression for %d not implemented!", izip);
-	}
-    }
-
   gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, data,
 	   gridsize, (int *) gribbuffer, gribsize, &iword, hoper, &iret);
 
@@ -30440,14 +29734,15 @@ int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
 
   switch (timeunit)
     {
-    case TUNIT_MINUTE:  factor =    60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE;  break;
-    case TUNIT_QUARTER: factor =   900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER; break;
-    case TUNIT_HOUR:    factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;    break;
-    case TUNIT_3HOURS:  factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS;  break;
-    case TUNIT_6HOURS:  factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS;  break;
-    case TUNIT_12HOURS: factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS; break;
-    case TUNIT_DAY:     factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY;     break;
-    default:            factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;    break;
+    case TUNIT_MINUTE:    factor =    60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE;    break;
+    case TUNIT_QUARTER:   factor =   900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER;   break;
+    case TUNIT_30MINUTES: factor =  1800; ISEC1_TimeUnit = ISEC1_TABLE4_30MINUTES; break;
+    case TUNIT_HOUR:      factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;      break;
+    case TUNIT_3HOURS:    factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS;    break;
+    case TUNIT_6HOURS:    factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS;    break;
+    case TUNIT_12HOURS:   factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS;   break;
+    case TUNIT_DAY:       factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY;       break;
+    default:              factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;      break;
     }
 
   return (factor);
@@ -30460,7 +29755,7 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
   int timerange = 0;
   int timeunit = TUNIT_HOUR;
 
-  if ( taxisID != -1 ) 
+  if ( taxisID != -1 )
     {
       timetype = taxisInqType(taxisID);
       timeunit = taxisInqTunit(taxisID);
@@ -31042,6 +30337,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 static
 void cgribexDefMask(int *isec3)
 {
+  UNUSED(isec3);
 }
 
 static
@@ -31096,23 +30392,25 @@ void cgribexDefEnsembleVar(int *isec1, int vlistID, int varID)
 #endif
 
 
-size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg,
 		     long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize)
 {
   size_t nbytes = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
-  long gribsize;
+  int gribsize;
   int iret = 0, iword = 0;
   int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
+  float fsec2f[512], fsec3f[2];
   double fsec2[512], fsec3[2];
   int datatype;
   int param;
 
   memset(isec1, 0, 256*sizeof(int));
   fsec2[0] = 0; fsec2[1] = 0;
+  fsec2f[0] = 0; fsec2f[1] = 0;
 
-  gribsize = gribbuffersize / sizeof(int);
+  gribsize = (int)(gribbuffersize / sizeof(int));
   param    = vlistInqVarParam(vlistID, varID);
 
   cgribexDefaultSec0(isec0);
@@ -31149,12 +30447,22 @@ size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
     }
   //printf("isec4[16] %d\n", isec4[16]);
 
-  gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
-	   datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
+  if ( memtype == MEMTYPE_FLOAT )
+    {
+      for ( int i = 0; i < ISEC2_NumVCP; ++i ) fsec2f[10+i] = fsec2[10+i];
+      fsec3f[ 1] = fsec3[ 1];
+    }
+
+  if ( memtype == MEMTYPE_FLOAT )
+    gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
+             (int)datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
+  else
+    gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
+             (int)datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
 
   if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
 
-  nbytes = iword*sizeof(int);
+  nbytes = (size_t)iword * sizeof (int);
 #else
   Error("CGRIBEX support not compiled in!");
 #endif
@@ -31187,6 +30495,7 @@ typedef struct {
   int level1;
   int level2;
   int ltype;
+  int tsteptype;
   char name[32];
 } compvar2_t;
 
@@ -31334,11 +30643,10 @@ double timeunit_factor(int tu1, int tu2)
 static
 int gribapiGetTimeUnits(grib_handle *gh)
 {
-  int status;
   int timeunits = -1;
   long unitsOfTime = -1;
 
-  status = grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
+  grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
 
   GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
 
@@ -31352,18 +30660,17 @@ int gribapiGetEndStep(grib_handle *gh, int startStep, int timeunits)
 {
   int endStep = startStep;
   int timeunits2 = timeunits;
-  int status;
-  long unitsOfTime;
-  long lpar;
 
-  status = grib_get_long(gh, "stepUnits", &unitsOfTime);
+  long unitsOfTime;
+  int status = grib_get_long(gh, "stepUnits", &unitsOfTime);
   if ( status == 0 ) timeunits2 = getTimeunits(unitsOfTime);
   //timeunits2 = gribapiGetTimeUnits(gh);
 
+  long lpar;
   status = grib_get_long(gh, "endStep", &lpar);
 
   if ( status == 0 )
-    endStep = (int) ((lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
+    endStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
   // printf("%d %d %d %d %d %g\n", startStep, endStep, lpar, timeunits, timeunits2, timeunit_factor(timeunits, timeunits2));
 
   return (endStep);
@@ -31416,7 +30723,7 @@ int gribapiGetTsteptype(grib_handle *gh)
 	  else if ( strncmp("ratio",   stepType, len) == 0 ) tsteptype = TSTEP_RATIO;
 	  else if ( lprint )
 	    {
-	      Message("stepType %s unsupported, set to instant!", stepType);
+	      Message("Time stepType %s unsupported, set to instant!", stepType);
 	      lprint = FALSE;
 	    }
 
@@ -31500,30 +30807,33 @@ int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
 	cdiDecodeDate(rdate, &ryear, &rmonth, &rday);
 	cdiDecodeTime(rtime, &rhour, &rminute, &rsecond);
 
-	encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
+        if ( rday > 0 )
+          {
+            encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
 
-	addsec = 0;
-	switch ( timeUnits )
-	  {
-	  case TUNIT_SECOND:  addsec =         time_period; break;
-	  case TUNIT_MINUTE:  addsec =    60 * time_period; break;
-	  case TUNIT_HOUR:    addsec =  3600 * time_period; break;
-	  case TUNIT_3HOURS:  addsec = 10800 * time_period; break;
-	  case TUNIT_6HOURS:  addsec = 21600 * time_period; break;
-	  case TUNIT_12HOURS: addsec = 43200 * time_period; break;
-	  case TUNIT_DAY:     addsec = 86400 * time_period; break;
-	  default:
-	    if ( lprint )
-	      {
-	        Warning("Time unit %d unsupported", timeUnits);
-		lprint = FALSE;
-	      }
-	    break;
-	  }
+            addsec = 0;
+            switch ( timeUnits )
+              {
+              case TUNIT_SECOND:  addsec =         time_period; break;
+              case TUNIT_MINUTE:  addsec =    60 * time_period; break;
+              case TUNIT_HOUR:    addsec =  3600 * time_period; break;
+              case TUNIT_3HOURS:  addsec = 10800 * time_period; break;
+              case TUNIT_6HOURS:  addsec = 21600 * time_period; break;
+              case TUNIT_12HOURS: addsec = 43200 * time_period; break;
+              case TUNIT_DAY:     addsec = 86400 * time_period; break;
+              default:
+                if ( lprint )
+                  {
+                    Warning("Time unit %d unsupported", timeUnits);
+                    lprint = FALSE;
+                  }
+                break;
+              }
 
-	julday_add_seconds(addsec, &julday, &secofday);
+            julday_add_seconds(addsec, &julday, &secofday);
 
-	decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
+            decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
+          }
 
 	*vdate = cdiEncodeDate(ryear, rmonth, rday);
 	*vtime = cdiEncodeTime(rhour, rminute, rsecond);
@@ -31537,14 +30847,9 @@ static
 void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 {
   long editionNumber;
-  int gridtype;
-  size_t datasize;
-  long numberOfPoints;
-  long lpar;
-
   GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
 
-  gridtype = gribapiGetGridType(gh);
+  int gridtype = gribapiGetGridType(gh);
   /*
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -31555,7 +30860,9 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
   */
   memset(grid, 0, sizeof(grid_t));
 
+  size_t datasize;
   GRIB_CHECK(grib_get_size(gh, "values", &datasize), 0);
+  long numberOfPoints;
   GRIB_CHECK(grib_get_long(gh, "numberOfPoints", &numberOfPoints), 0);
 
   switch (gridtype)
@@ -31563,23 +30870,25 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
       {
-	int nlon, nlat;
-
+        long lpar;
 	GRIB_CHECK(grib_get_long(gh, "Ni", &lpar), 0);
-	nlon = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlon = (int)lpar;
 	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
-	nlat = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlat = (int)lpar;
 
 	if ( gridtype == GRID_GAUSSIAN )
           {
             GRIB_CHECK(grib_get_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar), 0);
-            grid->np = lpar;
+            grid->np = (int)lpar;
           }
 
 	if ( numberOfPoints != nlon*nlat )
-	  Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat);
+	  Error("numberOfPoints (%ld) and gridSize (%d) differ!", numberOfPoints, nlon*nlat);
 
-	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size  = (int)numberOfPoints;
 	grid->xsize = nlon;
 	grid->ysize = nlat;
 	grid->xinc  = 0;
@@ -31633,23 +30942,27 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       }
     case GRID_GAUSSIAN_REDUCED:
       {
-	int nlat, i;
 	size_t dummy;
 	long *pl;
 
+        long lpar;
         GRIB_CHECK(grib_get_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar), 0);
-        grid->np = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+        grid->np = (int)lpar;
 
 	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
-	nlat = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlat = (int)lpar;
 
-	grid->size   = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size   = (int)numberOfPoints;
 
-        grid->rowlon = (int *) malloc(nlat*sizeof(int));
-        pl          = (long *) malloc(nlat*sizeof(long));
-	dummy       = nlat;
+        grid->rowlon = (int *) malloc((size_t)nlat * sizeof (int));
+        pl          = (long *) malloc((size_t)nlat * sizeof (long));
+	dummy       = (size_t)nlat;
 	GRIB_CHECK(grib_get_long_array(gh, "pl", pl, &dummy), 0);
-	for ( i = 0; i < nlat; ++i ) grid->rowlon[i] = pl[i];
+        /* 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;
@@ -31703,6 +31016,7 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LCC:
       {
 	int nlon, nlat;
+        long lpar;
 
 	GRIB_CHECK(grib_get_long(gh, "Nx", &lpar), 0);
 	nlon = lpar;
@@ -31745,19 +31059,28 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 	grid->lcomplex = 0;
 	if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1;
 
-	grid->size  = datasize;
+        /* FIXME: assert(datasize >= INT_MIN && datasize <= INT_MAX) */
+	grid->size  = (int)datasize;
+        long lpar;
 	GRIB_CHECK(grib_get_long(gh, "J", &lpar), 0);
-	grid->trunc = lpar;
+        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+	grid->trunc = (int)lpar;
 
 	break;
       }
     case GRID_GME:
       {
-	grid->size  = numberOfPoints;
-	if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->nd  = lpar;
-	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->ni  = lpar;
-	if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->ni2 = lpar;
-	if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->ni3 = lpar;
+        /* 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;
 
 	break;
       }
@@ -31768,11 +31091,16 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         size_t len = sizeof(reference_link);
         reference_link[0] = 0;
 
-    	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+    	grid->size  = (int)numberOfPoints;
+        long lpar;
         if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 )
           {
-            grid->number   = lpar;
-            if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 ) grid->position = lpar;
+            /* 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_string(gh, "gridDescriptionFile", reference_link, &len) == 0 )
               {
@@ -31791,11 +31119,14 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     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;
 
-	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = lpar;
-	if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = lpar;
-
-	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size  = (int)numberOfPoints;
 
 	if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size )
 	  {
@@ -31837,16 +31168,13 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 static
 void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2)
 {
-  int status;
-  long lpar;
-  double dlevel;
-
   *leveltype = 0;
-  *lbounds = 0;
-  *level1  = 0;
-  *level2  = 0;
+  *lbounds   = 0;
+  *level1    = 0;
+  *level2    = 0;
 
-  status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
+  long lpar;
+  int status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
   if ( status == 0 )
     {
       *leveltype = (int) lpar;
@@ -31861,6 +31189,7 @@ void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
 
       if ( *lbounds == 0 )
 	{
+          double dlevel;
 	  GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0);
 	  if ( *leveltype == 100 ) dlevel *= 100;
 	  if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;
@@ -31872,9 +31201,9 @@ void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       else
 	{
 	  GRIB_CHECK(grib_get_long(gh, "topLevel", &lpar), 0);
-	  *level1 = lpar;
+	  *level1 = (int)lpar;
 	  GRIB_CHECK(grib_get_long(gh, "bottomLevel", &lpar), 0);
-	  *level2 = lpar;
+	  *level2 = (int)lpar;
 	}
     }
 }
@@ -31899,14 +31228,15 @@ double grib2ScaleFactor(long factor)
 }
 
 static
-void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2, int *level_sf, int *level_unit)
+void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1, 
+                   int *level2, int *level_sf, int *level_unit)
 {
   int status;
-  int leveltype2 = -1;
   long lpar;
   long factor;
 
-  *leveltype  = 0;
+  *leveltype1 = 0;
+  *leveltype2 = -1;
   *lbounds    = 0;
   *level1     = 0;
   *level2     = 0;
@@ -31919,25 +31249,26 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       long llevel;
       double dlevel1 = 0, dlevel2 = 0;
 
-      *leveltype = (int) lpar;
+      *leveltype1 = (int) lpar;
 
       status = grib_get_long(gh, "typeOfSecondFixedSurface", &lpar);
-      if ( status == 0 ) leveltype2 = lpar;
+      /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+      if ( status == 0 ) *leveltype2 = (int)lpar;
 
-      if ( *leveltype != 255 && leveltype2 != 255 && leveltype2 > 0 ) *lbounds = 1;
-      if ( *leveltype == GRIB2_LTYPE_REFERENCE && leveltype2 == 1 ) *lbounds = 0;
+      if ( *leveltype1 != 255 && *leveltype2 != 255 && *leveltype2 > 0 ) *lbounds = 1;
+      if ( *leveltype1 == GRIB2_LTYPE_REFERENCE && *leveltype2 == 1 ) *lbounds = 0;
 
-      if ( *leveltype == GRIB2_LTYPE_LANDDEPTH )
+      if ( *leveltype1 == GRIB2_LTYPE_LANDDEPTH )
         {
           *level_sf = 1000;
           *level_unit = CDI_UNIT_M;
         }
-      else if ( *leveltype == GRIB2_LTYPE_ISOBARIC )
+      else if ( *leveltype1 == GRIB2_LTYPE_ISOBARIC )
         {
           *level_sf = 1000;
           *level_unit = CDI_UNIT_PA;
         }
-      else if ( *leveltype == GRIB2_LTYPE_SIGMA )
+      else if ( *leveltype1 == GRIB2_LTYPE_SIGMA )
         {
           *level_sf = 1000;
           *level_unit = 0;
@@ -31948,12 +31279,12 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       if ( llevel != GRIB_MISSING_LONG )
         {
           if ( factor != GRIB_MISSING_LONG )
-            dlevel1 = llevel*grib2ScaleFactor(factor);
+            dlevel1 = (double)llevel * grib2ScaleFactor(factor);
           else
-            dlevel1 = llevel;
+            dlevel1 = (double)llevel;
         }
 
-      if ( *level_sf != 0 ) dlevel1 *= (*level_sf);
+      if ( *level_sf != 0 ) dlevel1 *= (double)(*level_sf);
 
       if ( *lbounds == 1 )
 	{
@@ -31962,9 +31293,9 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
           if ( llevel != GRIB_MISSING_LONG )
             {
               if ( factor != GRIB_MISSING_LONG )
-                dlevel2 = llevel*grib2ScaleFactor(factor);
+                dlevel2 = (double)llevel * grib2ScaleFactor(factor);
               else
-                dlevel2 = llevel;
+                dlevel2 = (double)llevel;
             }
 
           if ( *level_sf != 0 ) dlevel2 *= (*level_sf);
@@ -31988,8 +31319,8 @@ void gribapiGetString(grib_handle *gh, const char *key, char *string, size_t len
 #if  defined  (HAVE_LIBGRIB_API)
 static
 void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
-		      long recsize, off_t position, int datatype, int comptype, size_t len, const char *varname,
-                      int leveltype, int lbounds, int level1, int level2, int level_sf, int level_unit)
+		      size_t recsize, off_t position, int datatype, int comptype, size_t len, const char *varname,
+                      int leveltype1, int leveltype2, int lbounds, int level1, int level2, int level_sf, int level_unit)
 {
   long editionNumber;
   int zaxistype;
@@ -32018,21 +31349,22 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
 
   GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
 
-  // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype);
+  // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype1);
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = leveltype;
+  (*record).size      = recsize;
+  (*record).position  = position;
+  (*record).param     = param;
+  (*record).ilevel    = level1;
+  (*record).ilevel2   = level2;
+  (*record).ltype     = leveltype1;
+  (*record).tsteptype = tsteptype;
   memcpy((*record).varname, varname, len);
 
   gribapiGetGrid(gh, &grid);
 
   gridID = varDefGrid(vlistID, grid, 0);
 
-  zaxistype = gribapiGetZaxisType(editionNumber, leveltype);
+  zaxistype = gribapiGetZaxisType(editionNumber, leveltype1);
 
   switch (zaxistype)
     {
@@ -32044,13 +31376,14 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
         double *vctptr;
 
         GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
-        vctsize = lpar;
+        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+        vctsize = (int)lpar;
         if ( vctsize > 0 )
           {
             vctptr = (double *) malloc(vctsize*sizeof(double));
-            dummy = vctsize;
+            dummy = (size_t)vctsize;
             GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
-            varDefVCT(vctsize, vctptr);
+            varDefVCT((size_t)vctsize, vctptr);
             free(vctptr);
           }
         break;
@@ -32103,11 +31436,11 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
   // fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units);
 
   varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, level_sf, level_unit,
-	       datatype, &varID, &levelID, tsteptype, numavg, leveltype,
+	       datatype, &varID, &levelID, tsteptype, numavg, leveltype1, leveltype2,
 	       varname, stdname, longname, units);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   varDefCompType(varID, comptype);
 
@@ -32130,6 +31463,11 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
   if ( status == 0 )
     varDefTypeOfGeneratingProcess(varID, (int) typeOfGeneratingProcess);
 
+  long productDefinitionTemplate = 0;
+  status = grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate);
+  if ( status == 0 )
+    varDefProductDefinitionTemplate(varID, (int) productDefinitionTemplate);
+
   int    i;
   long   lval;
   double dval;
@@ -32171,9 +31509,10 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
       status = grib_get_long(gh, "generatingProcessIdentifier", &processID);
       if ( status == 0 )
 	{
-	  modelID = modelInq(varInqInst(varID), processID, NULL);
+          /* FIXME: assert(processID >= INT_MIN && processID <= INT_MAX) */
+	  modelID = modelInq(varInqInst(varID), (int)processID, NULL);
 	  if ( modelID == CDI_UNDEFID )
-	    modelID = modelDef(varInqInst(varID), processID, NULL);
+	    modelID = modelDef(varInqInst(varID), (int)processID, NULL);
 	  varDefModel(varID, modelID);
 	}
     }
@@ -32229,17 +31568,18 @@ int gribapiGetParam(grib_handle *gh)
 }
 
 static
-compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, char *name)
+compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, int tsteptype, char *name)
 {
   compvar2_t compVar;
   size_t maxlen = sizeof(compVar.name);
   size_t len = strlen(name);
   if ( len > maxlen ) len = maxlen;
 
-  compVar.param  = param;
-  compVar.level1 = level1;
-  compVar.level2 = level2;
-  compVar.ltype  = leveltype;
+  compVar.param     = param;
+  compVar.level1    = level1;
+  compVar.level2    = level2;
+  compVar.ltype     = leveltype;
+  compVar.tsteptype = tsteptype;
   memset(compVar.name, 0, maxlen);
   memcpy(compVar.name, name, len);
 
@@ -32247,19 +31587,25 @@ compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, char
 }
 
 static
-int gribapiVarCompare(compvar2_t compVar, record_t record)
+int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
 {
-  int rstatus;
   compvar2_t compVar0;
   size_t maxlen = sizeof(compVar.name);
 
-  compVar0.param  = record.param;
-  compVar0.level1 = record.ilevel;
-  compVar0.level2 = record.ilevel2;
-  compVar0.ltype  = record.ltype;
+  compVar0.param     = record.param;
+  compVar0.level1    = record.ilevel;
+  compVar0.level2    = record.ilevel2;
+  compVar0.ltype     = record.ltype;
+  compVar0.tsteptype = record.tsteptype;
   memcpy(compVar0.name, record.varname, maxlen);
 
-  rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
+  if ( flag == 0 )
+    {
+      if ( compVar0.tsteptype == TSTEP_INSTANT  && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
+      if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT  ) compVar0.tsteptype = TSTEP_INSTANT;
+    }
+
+  int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
 
   return (rstatus);
 }
@@ -32273,7 +31619,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 #if  defined  (HAVE_LIBGRIB_API)
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int rstatus;
   int status;
   int fileID;
@@ -32288,7 +31634,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   int nrecords, nrecs, recID;
   int nrecs_scanned = 0;
   int datatype;
-  long recsize = 0;
+  size_t recsize = 0;
   int warn_time = TRUE;
   // int warn_numavg = TRUE;
   int taxisID = -1;
@@ -32299,7 +31645,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   long editionNumber;
   long lpar;
   size_t len;
@@ -32307,6 +31653,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   int lieee = FALSE;
   int lbounds;
   int level_sf, level_unit;
+  int tsteptype;
   char paramstr[32];
   char varname[256];
 
@@ -32325,7 +31672,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
     {
       level1 = 0;
       level2 = 0;
-      recsize = gribGetSize(fileID);
+      recsize = (size_t)gribGetSize(fileID);
       recpos  = fileGetPos(fileID);
 
       if ( recsize == 0 )
@@ -32346,13 +31693,13 @@ int gribapiScanTimestep1(stream_t * streamptr)
       lieee = FALSE;
 
       comptype = COMPRESS_NONE;
-      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+      if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  comptype = COMPRESS_SZIP;
 	  unzipsize += 100;
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
@@ -32372,7 +31719,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
 	  param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	  grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	  grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
           level_sf = 0;
           level_unit = 0;
 	}
@@ -32391,7 +31738,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
 	  param = gribapiGetParam(gh);
 
-	  grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	  grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	}
 
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -32402,9 +31749,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
       if ( len > 32 ) len = 32;
       //printf("param = %s  name = %s   l1 = %d  l2 = %d\n", paramstr, varname, level1, level2);
 
+      tsteptype = gribapiGetTsteptype(gh);
       gribapiGetValidityDateTime(gh, &vdate, &vtime);
       /*
-      printf("%d %d %d\n", vdate, vtime, leveltype);
+      printf("%d %d %d\n", vdate, vtime, leveltype1);
       */
       if ( lieee )
         {
@@ -32439,10 +31787,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+	  compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
 	  for ( recID = 0; recID < nrecs; recID++ )
-            if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID]) == 0 ) break;
+            if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
 
 	  if ( cdiInventoryMode == 1 )
 	    {
@@ -32497,10 +31845,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
       if ( CDI_Debug )
 	Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
-                nrecs, (int)recpos, varname, paramstr, leveltype, level1, level2, vdate, vtime);
+                nrecs, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
 
       gribapiAddRecord(streamptr, param, gh, recsize, recpos, datatype, comptype, len, varname,
-                       leveltype, lbounds, level1, level2, level_sf, level_unit);
+                       leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit);
 
       grib_handle_delete(gh);
       gh = NULL;
@@ -32528,8 +31876,8 @@ int gribapiScanTimestep1(stream_t * streamptr)
       taxis->type  = TAXIS_ABSOLUTE;
     }
 
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -32585,7 +31933,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 #if  defined  (HAVE_LIBGRIB_API)
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int rtabnum = 0;
   int rcode = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -32596,7 +31944,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   size_t readsize;
   int nrecords, nrecs, recID, rindex;
   int nrecs_scanned = 0;
-  long recsize = 0;
+  size_t recsize = 0;
   //  int warn_numavg = TRUE;
   int tsteptype;
   int taxisID = -1;
@@ -32605,7 +31953,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   int param = 0;
   long editionNumber;
   long lpar;
@@ -32652,7 +32000,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
     {
       if ( rindex > nrecords ) break;
 
-      recsize = gribGetSize(fileID);
+      recsize = (size_t)gribGetSize(fileID);
       recpos  = fileGetPos(fileID);
       if ( recsize == 0 )
 	{
@@ -32662,19 +32010,19 @@ int gribapiScanTimestep2(stream_t * streamptr)
       if ( recsize > buffersize )
 	{
 	  buffersize = recsize;
-	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
+	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
       readsize = recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
-      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+      if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
@@ -32694,7 +32042,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 
 	  param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	  grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	  grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
           level_sf = 0;
           level_unit = 0;
 	}
@@ -32702,7 +32050,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 	{
 	  param = gribapiGetParam(gh);
 
-	  grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	  grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	}
 
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -32751,10 +32099,10 @@ int gribapiScanTimestep2(stream_t * streamptr)
       datetime.date  = vdate;
       datetime.time  = vtime;
 
-      compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+      compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
       for ( recID = 0; recID < nrecords; recID++ )
-        if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+        if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 
       if ( recID == nrecords )
 	{
@@ -32779,11 +32127,11 @@ int gribapiScanTimestep2(stream_t * streamptr)
 
       if ( CDI_Debug )
 	Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
-                nrecs_scanned, (int)recpos, varname, paramstr, leveltype, level1, level2, vdate, vtime);
+                nrecs_scanned, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
 
       streamptr->tsteps[tsID].records[recID].size = recsize;
 
-      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
@@ -32853,10 +32201,10 @@ int gribapiScanTimestep(stream_t * streamptr)
 {
   int rstatus = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  long recsize = 0;
+  size_t recsize = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int rtabnum = 0;
   int rcode = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -32873,7 +32221,7 @@ int gribapiScanTimestep(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   int param = 0;
   long editionNumber;
   long lpar;
@@ -32919,7 +32267,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	{
 	  if ( rindex > nrecs ) break;
 
-	  recsize = gribGetSize(fileID);
+	  recsize = (size_t)gribGetSize(fileID);
 	  recpos  = fileGetPos(fileID);
 	  if ( recsize == 0 )
 	    {
@@ -32944,12 +32292,12 @@ int gribapiScanTimestep(stream_t * streamptr)
 	      break;
 	    }
 
-	  if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+	  if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	    {
 	      unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	      if ( (long) buffersize < unzipsize )
+	      if ( buffersize < (size_t)unzipsize )
 		{
-		  buffersize = unzipsize;
+		  buffersize = (size_t)unzipsize;
 		  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 		}
 	    }
@@ -32969,7 +32317,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 
 	      param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	      grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	      grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
               level_sf = 0;
               level_unit = 0;
 	    }
@@ -32977,7 +32325,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	    {
 	      param = gribapiGetParam(gh);
 
-	      grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	      grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	    }
 
           cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -33027,12 +32375,14 @@ int gribapiScanTimestep(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+          int tsteptype = gribapiGetTsteptype(gh);
+
+	  compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
 	  for ( vrecID = 0; vrecID < nrecs; vrecID++ )
 	    {
 	      recID   = streamptr->tsteps[1].recIDs[vrecID];
-	      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	    }
 
 	  if ( vrecID == nrecs )
@@ -33064,7 +32414,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	  if ( CDI_Debug )
 	    Message("%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
 
-	  if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+	  if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	    {
 	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		      tsID, recID,
@@ -33126,7 +32476,7 @@ int gribapiScanTimestep(stream_t * streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  rstatus = streamptr->ntsteps;
+  rstatus = (int)streamptr->ntsteps;
 #else
   Error("GRIB_API support not compiled in!");
 #endif
@@ -33139,7 +32489,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 #endif
 
 int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID)
+		  int unreduced, int *nmiss, double missval, int vlistID, int varID)
 {
   int status = 0;
 #if  defined  (HAVE_LIBGRIB_API)
@@ -33148,6 +32498,9 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
   size_t datasize, dummy, recsize;
   grib_handle *gh = NULL;
 
+  UNUSED(vlistID);
+  UNUSED(varID);
+
   if ( unreduced )
     {
       static int lwarn = 1;
@@ -33159,7 +32512,7 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
 	}
     }
 
-  recsize = gribsize;
+  recsize = (size_t)gribsize;
   gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
   GRIB_CHECK(my_grib_set_double(gh, "missingValue", missval), 0);
 
@@ -33304,7 +32657,7 @@ int getTimeunitFactor(int timeunit)
 }
 
 static
-void gribapiDefStepUnits(grib_handle *gh, int timeunit, int gcinit)
+void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
 {
   long unitsOfTime;
 
@@ -33323,12 +32676,14 @@ void gribapiDefStepUnits(grib_handle *gh, int timeunit, int gcinit)
   if ( !gcinit )
     {
       GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
+      if ( proDefTempNum == 8 || proDefTempNum == 11 )
+        GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
       GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
     }
 }
 
 static
-int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gcinit)
+int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
 {
   long proDefTempNum = 0;
   size_t len = 64;
@@ -33349,6 +32704,14 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gc
     default:             strcpy(stepType, "instant"); proDefTempNum = 0; break;
     }
 
+  if ( typeOfGeneratingProcess == 4 )
+    {
+      if ( proDefTempNum == 8 ) proDefTempNum = 11;
+      else                      proDefTempNum = 1;
+    }
+
+  if ( productDefinitionTemplate != -1 ) proDefTempNum = productDefinitionTemplate;
+
   if ( !gcinit )
     {
       if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "productDefinitionTemplateNumber", proDefTempNum), 0);
@@ -33360,9 +32723,9 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gc
 }
 
 static
-void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int tsteptype, int gcinit)
+void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
 {
-  (void ) gribapiDefSteptype(editionNumber, gh, tsteptype, gcinit);
+  (void ) gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
   if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 0), 0);
   if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
@@ -33373,7 +32736,7 @@ void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int tim
 
 static
 int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rtime, int vdate, int vtime,
-                          int tsteptype, int timeunit, int calendar, int gcinit)
+                          int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int timeunit, int calendar, int gcinit)
 {
   int status = -1;
   int year, month, day, hour, minute, second;
@@ -33397,9 +32760,9 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
 
   if ( !(int) fmod(days*86400.0 + secs, factor) )
     {
-      int proDefTempNum = gribapiDefSteptype(editionNumber, gh, tsteptype, gcinit);
+      int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
-      gribapiDefStepUnits(gh, timeunit, gcinit);
+      gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
 
       endStep = (int) ((days*86400.0 + secs)/factor);
 
@@ -33423,10 +32786,13 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
 }
 
 static
-void gribapiDefTime(int editionNumber, int typeOfGeneratingProcess, grib_handle *gh , int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
+void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOfGeneratingProcess, grib_handle *gh,
+                    int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
 {
   int taxistype = -1;
 
+  UNUSED(numavg);
+
   if ( taxisID != -1 ) taxistype = taxisInqType(taxisID);
 
   if ( typeOfGeneratingProcess == 196 )
@@ -33450,19 +32816,19 @@ void gribapiDefTime(int editionNumber, int typeOfGeneratingProcess, grib_handle
       int timeunit = taxisInqTunit(taxisID);
 
       status = gribapiDefDateTimeRel(editionNumber, gh, rdate, rtime, vdate, vtime,
-                                     tsteptype, timeunit, calendar, gcinit);
+                                     productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, timeunit, calendar, gcinit);
 
       if ( status != 0 ) taxistype = TAXIS_ABSOLUTE;
     }
 
   if ( taxistype == TAXIS_ABSOLUTE )
     {
-      gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, tsteptype, gcinit);
+      gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
     }
 }
 
 static
-void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, int lieee, int datatype, int nmiss, int gcinit)
+void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
 {
   int gridtype;
   int status;
@@ -33470,6 +32836,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
   size_t len;
   char *mesg;
 
+  UNUSED(nmiss);
+
   gridtype = gridInqType(gridID);
 
   if ( editionNumber <= 1 )
@@ -33517,17 +32885,22 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 
   if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
     {
-      if ( editionNumber != 2 || lieee ) { ljpeg = 0; }
+      if ( editionNumber != 2 || lieee ) { comptype = 0; }
 
-      if ( ljpeg )
+      if ( comptype )
         {
-          if ( nmiss > 0 ) ljpeg = 0;
+          //if ( nmiss > 0 ) comptype = 0;
 
-          if ( ljpeg )
+          if ( comptype == COMPRESS_JPEG )
             {
               mesg = "grid_jpeg"; len = strlen(mesg);
               GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
             }
+          else if ( comptype == COMPRESS_SZIP )
+            {
+              mesg = "grid_szip"; len = strlen(mesg);
+              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+            }
           else
             {
               mesg = "grid_simple"; len = strlen(mesg);
@@ -33681,7 +33054,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 	/* South -> North */
 	//if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
 
-        if ( editionNumber != 2 ) { lieee = 0; ljpeg = 0; }
+        if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
 
         if ( lieee )
           {
@@ -33693,15 +33066,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 	    else
 	      GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
           }
-        else if ( ljpeg )
+        else if ( comptype )
 	  {
-            if ( nmiss > 0 ) ljpeg = 0;
+            //if ( nmiss > 0 ) comptype = 0;
 
-            if ( ljpeg )
+            if ( comptype == COMPRESS_JPEG )
               {
                 mesg = "grid_jpeg"; len = strlen(mesg);
                 GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
               }
+            else if ( comptype == COMPRESS_SZIP )
+              {
+                mesg = "grid_szip"; len = strlen(mesg);
+                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+              }
             else
               {
                 mesg = "grid_simple"; len = strlen(mesg);
@@ -33847,6 +33225,7 @@ static
 void getLevelFactor(double level, long *factor, long *out_scaled_value)
 {
   double scaled_value  = level;
+  /* FIXME: lround might be better here */
   long   iscaled_value = (long) round(scaled_value);
   long   i;
 
@@ -33854,7 +33233,8 @@ void getLevelFactor(double level, long *factor, long *out_scaled_value)
   for ( i=0; (fabs(scaled_value - (double) iscaled_value) >= eps) && i < 7; i++ )
     {
       scaled_value *= 10.;
-      iscaled_value = round(scaled_value);
+      /* FIXME: lround might be better here */
+      iscaled_value = (long)round(scaled_value);
     }
 
   (*factor)           = i;
@@ -33868,13 +33248,13 @@ void gribapiDefLevelType(grib_handle *gh, int gcinit, const char *keyname, long
 }
 
 static
-void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype, int lbounds, double level, double dlevel1, double dlevel2)
+void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, int lbounds, double level, double dlevel1, double dlevel2)
 {
   long scaled_level;
   long factor;
 
-  gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype);
-  if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype);
+  gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype1);
+  if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype2);
 
   if ( !lbounds ) dlevel1 = level;
 
@@ -33890,22 +33270,19 @@ void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype, int lbounds, dou
     }
 }
 
+int zaxisInqLtype2(int zaxisID);
+
 static
 void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit)
 {
-  double level;
   int lbounds = 0;
-  int zaxistype, ltype;
   static int warning = 1;
-  char uuid[17];
-  size_t len;
-  double scalefactor;
   double dlevel1 = 0, dlevel2 = 0;
 
-
-  zaxistype = zaxisInqType(zaxisID);
-  ltype = zaxisInqLtype(zaxisID);
-  level = zaxisInqLevel(zaxisID, levelID);
+  int zaxistype = zaxisInqType(zaxisID);
+  int ltype = zaxisInqLtype(zaxisID);
+  int ltype2 = zaxisInqLtype2(zaxisID);
+  double level = zaxisInqLevel(zaxisID, levelID);
 
   if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
     {
@@ -33942,7 +33319,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
         else
           gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", zaxisTypeToGrib2ltype(zaxistype));
 
-        GRIB_CHECK(my_grib_set_long(gh, "level", level), 0);
+        GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
 
 	break;
       }
@@ -34020,7 +33397,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 warning = 0;
               }
             GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
-            GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), vctsize), 0);
+            GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
           }
 
 	break;
@@ -34054,7 +33431,8 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 	  }
 	else
 	  {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, lbounds, level, dlevel1, dlevel2);
+            if ( ltype2 == -1 ) ltype2 = GRIB2_LTYPE_ISOBARIC;
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, ltype2, lbounds, level, dlevel1, dlevel2);
 	  }
 
 	break;
@@ -34065,7 +33443,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
           ; // not available
 	else
           {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
           }
 
 	break;
@@ -34078,6 +33456,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 
 	if ( editionNumber <= 1 )
 	  {
+            double scalefactor;
 	    if      ( memcmp(units, "mm", 2) == 0 ) scalefactor =   0.1;
 	    else if ( memcmp(units, "cm", 2) == 0 ) scalefactor =   1; // cm
 	    else if ( memcmp(units, "dm", 2) == 0 ) scalefactor =  10;
@@ -34088,6 +33467,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 	  }
 	else
 	  {
+            double scalefactor;
 	    if      ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.001;
 	    else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 0.01;
 	    else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 0.1;
@@ -34097,13 +33477,14 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
             dlevel1 *= scalefactor;
             dlevel2 *= scalefactor;
 
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
 	  }
 
 	break;
       }
     case ZAXIS_REFERENCE:
       {
+        char uuid[16];
         int number;
 
         if ( !gcinit )
@@ -34123,7 +33504,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
-                len = 16;
+                size_t len = 16;
                 zaxisInqUUID(zaxisID, uuid);
                 if (grib_set_bytes(gh, "uuidOfVGrid", (unsigned char *) uuid, &len) != 0)
                   Warning("Can't write UUID!");
@@ -34142,7 +33523,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
-                len = 16;
+                size_t len = 16;
                 zaxisInqUUID(zaxisID, uuid);
                 if (grib_set_bytes(gh, "uuidOfVGrid", (unsigned char *) uuid, &len) != 0)
                   Warning("Can't write UUID!");
@@ -34201,7 +33582,7 @@ void gribHandleDelete(void *gh)
 size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
 		     long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
-		     int ljpeg, void *gribContainer)
+		     int comptype, void *gribContainer)
 {
   size_t nbytes = 0;
 #if  defined  (HAVE_LIBGRIB_API)
@@ -34212,6 +33593,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
   int lieee = FALSE;
   /*  int ensID, ensCount, forecast_type; *//* Ensemble Data */
   int typeOfGeneratingProcess;
+  int productDefinitionTemplate;
   long bitsPerValue;
   long editionNumber = 2;
   char name[256];
@@ -34222,6 +33604,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
   param    = vlistInqVarParam(vlistID, varID);
   datatype = vlistInqVarDatatype(vlistID, varID);
   typeOfGeneratingProcess = vlistInqVarTypeOfGeneratingProcess(vlistID, varID);
+  productDefinitionTemplate = vlistInqVarProductDefinitionTemplate(vlistID, varID);
 
   vlistInqVarName(vlistID, varID, name);
 
@@ -34239,10 +33622,6 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       if ( ! gc->init ) GRIB_CHECK(my_grib_set_long(gh, "typeOfGeneratingProcess", typeOfGeneratingProcess), 0);
     }
 
-  if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
-  if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
-
-  if ( ! gc->init ) gribapiDefParam(editionNumber, gh, param, name);
   /*
   if( vlistInqVarEnsemble( vlistID,  varID, &ensID, &ensCount, &forecast_type ) )
     {
@@ -34252,7 +33631,12 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
     }
   */
 
-  gribapiDefTime(editionNumber, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+  gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+
+  if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
+  if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
+
+  if ( ! gc->init ) gribapiDefParam(editionNumber, gh, param, name);
 
   if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = TRUE;
 
@@ -34263,9 +33647,9 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       GRIB_CHECK(my_grib_set_long(gh, "bitsPerValue", bitsPerValue), 0);
     }
 
-  gribapiDefGrid(editionNumber, gh, gridID, ljpeg, lieee, datatype, nmiss, gc->init);
+  gribapiDefGrid((int)editionNumber, gh, gridID, comptype, lieee, datatype, nmiss, gc->init);
 
-  gribapiDefLevel(editionNumber, gh, param, zaxisID, levelID, gc->init);
+  gribapiDefLevel((int)editionNumber, gh, param, zaxisID, levelID, gc->init);
 
   /* ---------------------------------- */
   /* Local change: 2013-01-28, FP (DWD) */
@@ -34273,29 +33657,37 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 
   vlist_t *vlistptr;
   vlistptr = vlist_to_pointer(vlistID);
-  if (!gc->init) {
-    int i;
-    for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  //if (!gc->init)
+  {
+    for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
       {
-	int ret = my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_dbl_keyword[i],
-                                  vlistptr->vars[varID].opt_grib_dbl_val[i]);
-	if (ret != 0) {
-	    fprintf(stderr, "key \"%s\"  :   value = %g\n",
-                    vlistptr->vars[varID].opt_grib_dbl_keyword[i],
-		    vlistptr->vars[varID].opt_grib_dbl_val[i]);
-	}
-	GRIB_CHECK(ret, 0);
+        if ( vlistptr->vars[varID].opt_grib_dbl_update[i] )
+          {
+            vlistptr->vars[varID].opt_grib_dbl_update[i] = FALSE;
+            int ret = my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_dbl_keyword[i],
+                                         vlistptr->vars[varID].opt_grib_dbl_val[i]);
+            if (ret != 0) {
+              fprintf(stderr, "key \"%s\"  :   value = %g\n",
+                      vlistptr->vars[varID].opt_grib_dbl_keyword[i],
+                      vlistptr->vars[varID].opt_grib_dbl_val[i]);
+            }
+            GRIB_CHECK(ret, 0);
+          }
       }
-    for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+    for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
       {
-	int ret = my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_int_keyword[i],
-	                        vlistptr->vars[varID].opt_grib_int_val[i]);
-	if (ret != 0) {
-	    fprintf(stderr, "key \"%s\"  :   value = %d\n",
-		    vlistptr->vars[varID].opt_grib_int_keyword[i],
-		    vlistptr->vars[varID].opt_grib_int_val[i]);
-	}
-	GRIB_CHECK(ret, 0);
+        if ( vlistptr->vars[varID].opt_grib_int_update[i] )
+          {
+            vlistptr->vars[varID].opt_grib_int_update[i] = FALSE;
+            int ret = my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_int_keyword[i],
+                                       vlistptr->vars[varID].opt_grib_int_val[i]);
+            if (ret != 0) {
+              fprintf(stderr, "key \"%s\"  :   value = %d\n",
+                      vlistptr->vars[varID].opt_grib_int_keyword[i],
+                      vlistptr->vars[varID].opt_grib_int_val[i]);
+            }
+            GRIB_CHECK(ret, 0);
+          }
       }
   }
 
@@ -34306,7 +33698,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       GRIB_CHECK(my_grib_set_double(gh, "missingValue", vlistInqVarMissval(vlistID, varID)), 0);
     }
 
-  GRIB_CHECK(grib_set_double_array(gh, "values", data, datasize), 0);
+  GRIB_CHECK(grib_set_double_array(gh, "values", data, (size_t)datasize), 0);
 
   /* get the size of coded message  */
   GRIB_CHECK(grib_get_message(gh, (const void **)&dummy, &recsize), 0);
@@ -34340,6 +33732,45 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
  * require-trailing-newline: t
  * End:
  */
+#include <stdlib.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 = xmalloc(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:
+ */
 #if defined (HAVE_CONFIG_H)
 #endif
 
@@ -34514,16 +33945,14 @@ int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
 }
 */
 
-int grbDefRecord(stream_t * streamptr)
+void grbDefRecord(stream_t * streamptr)
 {
-  int status = 0;
-
-  return (status);
+  UNUSED(streamptr);
 }
 
 static
 int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-	      int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID)
+	      int unreduced, int *nmiss, double missval, int vlistID, int varID)
 {
   int status = 0;
 
@@ -34535,61 +33964,101 @@ int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *dat
       if ( cdiNAdditionalGRIBKeys > 0 )
 	Error("CGRIBEX decode does not support reading of additional GRIB keys!");
 #endif
-      status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval);
+      status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval);
     }
   else
 #endif
     {
-      status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval, vlistID, varID);
+      status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval, vlistID, varID);
     }
 
   return (status);
 }
 
 
-int grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
+int grbUnzipRecord(unsigned char *gribbuffer, size_t *gribsize)
 {
-  int status = 0;
-  unsigned char *gribbuffer;
-  int fileID;
-  int recID, vrecID, tsID, gridID, varID;
-  long recsize;
-  off_t recpos;
-  int gridsize;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
+  int zip = 0;
+  int izip;
+  size_t igribsize;
+  size_t ogribsize;
+  long unzipsize;
 
-  filetype = streamptr->filetype;
+  igribsize = *gribsize;
+  ogribsize = *gribsize;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
+  if ( (izip = gribGetZip(igribsize, gribbuffer, &unzipsize)) > 0 )
+    {
+      zip = izip;
+      if ( izip == 128 ) /* szip */
+	{
+	  unsigned char *itmpbuffer = NULL;
+	  size_t itmpbuffersize = 0;
 
-  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;
-  recsize = streamptr->tsteps[tsID].records[recID].size;
-  varID   = streamptr->tsteps[tsID].records[recID].varID;
+	  if ( unzipsize < (long) igribsize )
+	    {
+	      fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
+	      return (0);
+	    }
 
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
+	  if ( itmpbuffersize < igribsize )
+	    {
+	      itmpbuffersize = igribsize;
+	      itmpbuffer = (unsigned char *) realloc(itmpbuffer, itmpbuffersize);
+	    }
+
+	  memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
+
+	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+
+	  ogribsize = gribUnzip(gribbuffer, unzipsize, itmpbuffer, igribsize);
+
+	  free(itmpbuffer);
+
+	  if ( ogribsize <= 0 ) Error("Decompression problem!");
+	}
+      else
+	{
+	  Error("Decompression for %d not implemented!", izip);
+	}
+    }
+
+  *gribsize = ogribsize;
+
+  return zip;
+}
+
+
+void grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
+{
+  int filetype = streamptr->filetype;
+
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
+
+  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];
+  off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+  size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+  int varID   = streamptr->tsteps[tsID].records[recID].varID;
+
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
 
   streamptr->numvals += gridsize;
 
   fileSetPos(fileID, recpos, SEEK_SET);
 
-  fileRead(fileID, gribbuffer, (size_t) recsize);
-
-  missval = vlistInqVarMissval(vlistID, varID);
+  if (fileRead(fileID, gribbuffer, recsize) != recsize)
+    Error("Failed to read GRIB record");
 
-  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
+  double missval = vlistInqVarMissval(vlistID, varID);
 
-  streamptr->tsteps[tsID].records[recID].zip = zip;
+  streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
 
-  return (status);
+  grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
 }
 
 static
@@ -34715,54 +34184,44 @@ int grbInqTimestep(stream_t * streamptr, int tsID)
 
 void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
 {
-  int fileID;
-  int levelID, nlevs, gridID, gridsize;
-  unsigned char *gribbuffer;
-  int tsID, recID;
-  long recsize;
-  off_t recpos, currentfilepos;
-  int imiss;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
-
-  filetype = streamptr->filetype;
+  int filetype = streamptr->filetype;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+  int tsID    = streamptr->curTsID;
 
-  nlevs    = streamptr->vars[varID].nlevs;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
+  int nlevs    = streamptr->vars[varID].nlevs;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
 
   if ( CDI_Debug )
     Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
 
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
   *nmiss = 0;
-  for ( levelID = 0; levelID < nlevs; levelID++ )
+  for (int levelID = 0; levelID < nlevs; levelID++ )
     {
-      recID   = streamptr->vars[varID].level[levelID];
-      recpos  = streamptr->tsteps[tsID].records[recID].position;
-      recsize = streamptr->tsteps[tsID].records[recID].size;
+      int recID   = streamptr->vars[varID].level[levelID];
+      off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+      size_t recsize = streamptr->tsteps[tsID].records[recID].size;
 
       fileSetPos(fileID, recpos, SEEK_SET);
 
       fileRead(fileID, gribbuffer, recsize);
 
-      missval = vlistInqVarMissval(vlistID, varID);
+      double missval = vlistInqVarMissval(vlistID, varID);
 
-      grbDecode(filetype, gribbuffer, recsize, &data[levelID*gridsize], gridsize,
-		streamptr->unreduced, &imiss, &zip, missval, vlistID, varID);
+      int imiss;
 
-      *nmiss += imiss;
+      streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
 
-      streamptr->tsteps[tsID].records[recID].zip = zip;
+      grbDecode(filetype, gribbuffer, (int)recsize, &data[levelID*gridsize], gridsize,
+		streamptr->unreduced, &imiss, missval, vlistID, varID);
+
+      *nmiss += imiss;
     }
 
   fileSetPos(fileID, currentfilepos, SEEK_SET);
@@ -34771,36 +34230,25 @@ void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
 
 void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss)
 {
-  int fileID;
-  int gridID, gridsize;
-  unsigned char *gribbuffer;
-  long recsize;
-  off_t recpos, currentfilepos;
-  int tsID, recID;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
+  int filetype = streamptr->filetype;
 
-  filetype = streamptr->filetype;
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
-
-  vlistID  = streamptr->vlistID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsID     = streamptr->curTsID;
+  int vlistID = streamptr->vlistID;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
+  int tsID = streamptr->curTsID;
 
   if ( CDI_Debug )
     Message("gridID = %d gridsize = %d", gridID, gridsize);
 
-  fileID = streamptr->fileID;
+  int fileID = streamptr->fileID;
 
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
-  recID   = streamptr->vars[varID].level[levelID];
-  recpos  = streamptr->tsteps[tsID].records[recID].position;
-  recsize = streamptr->tsteps[tsID].records[recID].size;
+  int recID   = streamptr->vars[varID].level[levelID];
+  off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+  size_t recsize = streamptr->tsteps[tsID].records[recID].size;
 
   if ( recsize == 0 )
     Error("Internal problem! Recordsize is zero for record %d at timestep %d",
@@ -34810,41 +34258,43 @@ void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *dat
 
   fileRead(fileID, gribbuffer, recsize);
 
-  missval = vlistInqVarMissval(vlistID, varID);
+  double missval = vlistInqVarMissval(vlistID, varID);
 
-  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
+  streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
 
-  fileSetPos(fileID, currentfilepos, SEEK_SET);
+  grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
 
-  streamptr->tsteps[tsID].records[recID].zip = zip;
+  fileSetPos(fileID, currentfilepos, SEEK_SET);
 }
 
 static
-size_t grbEncode(int filetype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		 int date, int time, int tsteptype, int numavg,
-		 long datasize, const double *data, int nmiss, unsigned char **gribbuffer,
-		 int ljpeg, void *gribContainer)
+		 size_t datasize, const double *data, int nmiss, unsigned char **gribbuffer,
+		 int comptype, void *gribContainer)
 {
   size_t nbytes;
-  size_t gribbuffersize;
 
 #if  defined  (HAVE_LIBCGRIBEX)
   if ( filetype == FILETYPE_GRB )
     {
-      gribbuffersize = datasize*4+3000;
+      size_t gribbuffersize = datasize*4+3000;
       *gribbuffer = (unsigned char *) malloc(gribbuffersize);
 
-      nbytes = cgribexEncode(varID, levelID, vlistID, gridID, zaxisID,
+      nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
 			     date, time, tsteptype, numavg,
-			     datasize, data, nmiss, *gribbuffer, gribbuffersize);
+			     (long)datasize, data, nmiss, *gribbuffer, gribbuffersize);
     }
   else
 #endif
     {
+      if ( memtype == MEMTYPE_FLOAT ) Error("gribapiEncode() not implemented for memtype float!");
+
+      size_t gribbuffersize;
       nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
 			     date, time, tsteptype, numavg,
-			     datasize, data, nmiss, gribbuffer, &gribbuffersize,
-			     ljpeg, gribContainer);
+			     (long)datasize, data, nmiss, gribbuffer, &gribbuffersize,
+			     comptype, gribContainer);
     }
 
   return (nbytes);
@@ -34865,7 +34315,7 @@ size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
 
   if ( filetype == FILETYPE_GRB )
     {
-      nbytes = gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
+      nbytes = (size_t)gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
     }
   else
     {
@@ -34880,14 +34330,13 @@ size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
 }
 
 
-int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
   size_t nwrite;
   int fileID;
   int gridID;
   int zaxisID;
   unsigned char *gribbuffer = NULL;
-  long datasize;
   int tsID;
   int vlistID;
   int date, time;
@@ -34895,12 +34344,8 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int numavg = 0;
   size_t nbytes;
   int filetype;
-  int ljpeg = 0;
-  int ljpeg_warn = 1;
   void *gc = NULL;
 
-  if ( memtype == MEMTYPE_FLOAT ) Error("grb_write_var_slice not implemented for memtype float!");
-
   filetype  = streamptr->filetype;
   fileID    = streamptr->fileID;
   vlistID   = streamptr->vlistID;
@@ -34908,6 +34353,8 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   zaxisID   = vlistInqVarZaxis(vlistID, varID);
   tsteptype = vlistInqVarTsteptype(vlistID, varID);
 
+  int comptype  = streamptr->comptype;
+
   tsID      = streamptr->curTsID;
   date      = streamptr->tsteps[tsID].taxis.vdate;
   time      = streamptr->tsteps[tsID].taxis.vtime;
@@ -34917,7 +34364,7 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   if ( CDI_Debug )
     Message("gridID = %d zaxisID = %d", gridID, zaxisID);
 
-  datasize = gridInqSize(gridID);
+  size_t datasize = (size_t)gridInqSize(gridID);
   /*
   gribbuffersize = datasize*4+3000;
   gribbuffer = (unsigned char *) malloc(gribbuffersize);
@@ -34938,23 +34385,19 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
 #endif
     }
 
-  if ( streamptr->comptype == COMPRESS_JPEG )
+  if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
+
+  if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
     {
-      if ( filetype == FILETYPE_GRB2 )
-	{
-	  ljpeg = 1;
-	}
-      else
-	{
-	  if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
-	  ljpeg_warn = 0;
-	}
+      static int ljpeg_warn = 1;
+      if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
+      ljpeg_warn = 0;
     }
 
-  nbytes = grbEncode(filetype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg, 
-		     datasize, (const double*) data, nmiss, &gribbuffer, ljpeg, gc);
+  nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
+		     datasize, (const double*) data, nmiss, &gribbuffer, comptype, gc);
 
-  if ( streamptr->comptype == COMPRESS_SZIP )
+  if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
     nbytes = grbSzip(filetype, gribbuffer, nbytes);
 
   {
@@ -34965,11 +34408,13 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
     nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
   }
 
-  if ( nwrite != nbytes ) perror(__func__);
+  if ( nwrite != nbytes )
+    {
+      perror(__func__);
+      Error("Failed to write GRIB slice!");
+    }
 
   if ( gribbuffer ) free(gribbuffer);
-
-  return ((int)nwrite);
 }
 
 
@@ -34994,103 +34439,88 @@ void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data
 }
 
 
-int grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
+void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  size_t gribbuffersize;
-  off_t recpos;
-  size_t nwrite;
-  unsigned char *gribbuffer;
-  int filetype;
-  size_t nbytes;
-  long unzipsize;
-  int izip;
+  int filetype = streamptr1->filetype;
 
-  filetype = streamptr1->filetype;
+  int fileID1 = streamptr1->fileID;
+  int fileID2 = streamptr2->fileID;
 
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
+  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;
 
   fileSetPos(fileID1, recpos, SEEK_SET);
 
-  gribbuffersize = recsize == (recsize>>3)<<3 ? recsize : (1+(recsize>>3))<<3;
+  /* round up recsize to next multiple of 8 */
+  size_t gribbuffersize = ((recsize + 7U) & ~7U);
 
-  gribbuffer = (unsigned char *) malloc(gribbuffersize);
+  unsigned char *gribbuffer = xmalloc(gribbuffersize);
 
-  fileRead(fileID1, gribbuffer, recsize);
+  if (fileRead(fileID1, gribbuffer, recsize) != recsize)
+    Error("Could not read GRIB record for copying!");
 
-  nbytes = recsize;
+  size_t nbytes = recsize;
 
-  izip = gribGetZip(recsize, gribbuffer, &unzipsize);
+  if ( filetype == FILETYPE_GRB )
+    {
+      long unzipsize;
+      int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
 
-  if ( izip == 0 )
-    if ( streamptr2->comptype == COMPRESS_SZIP )
-      nbytes = grbSzip(filetype, gribbuffer, nbytes);
+      if ( izip == 0 )
+        if ( streamptr2->comptype == COMPRESS_SZIP )
+          nbytes = grbSzip(filetype, gribbuffer, nbytes);
+    }
 
   while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
 
-  nwrite = fileWrite(fileID2, gribbuffer, nbytes);
-  if ( nwrite != nbytes ) perror(__func__);
+  size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
+  if ( nwrite != nbytes )
+    {
+      perror(__func__);
+      Error("Could not write record for copying!");
+    }
 
   free(gribbuffer);
-
-  return ((int)nwrite);
 }
 
 
-int grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
+void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
 {
-  int status = 0;
   int varID, levelID;
 
   varID   = streamptr->record->varID;
   levelID = streamptr->record->levelID;
 
-  status = grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-
-  return (status);
+  grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
 }
 
 
-void streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
+void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
 {
-  int recID, vrecID, tsID;
-  int filetype;
-  void *gribbuffer;
-  long gribbuffersize;
-  off_t recpos;
-  int zip;
-  stream_t *streamptr;
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
+  int filetype = streamptr->filetype;
 
   if ( filetype == FILETYPE_GRB )
     {
-      tsID    = streamptr->curTsID;
-      vrecID  = streamptr->tsteps[tsID].curRecID;
-      recID   = streamptr->tsteps[tsID].recIDs[vrecID];
-      recpos  = streamptr->tsteps[tsID].records[recID].position;
-      zip     = streamptr->tsteps[tsID].records[recID].zip;
+      int tsID     = streamptr->curTsID;
+      int vrecID   = streamptr->tsteps[tsID].curRecID;
+      int recID    = streamptr->tsteps[tsID].recIDs[vrecID];
+      off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+      int zip      = streamptr->tsteps[tsID].records[recID].zip;
 
-      gribbuffer = streamptr->record->buffer;
-      gribbuffersize = streamptr->record->buffersize;
+      void *gribbuffer = streamptr->record->buffer;
+      size_t gribbuffersize = streamptr->record->buffersize;
 
       if ( zip > 0 )
 	Error("Compressed GRIB records unsupported!");
       else
-	gribGinfo(recpos, gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
+        grib_info_for_grads(recpos, (long)gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
     }
 }
 /*
@@ -35105,7 +34535,9 @@ void streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
 #if defined (HAVE_CONFIG_H)
 #endif
 
+#include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 
@@ -35190,7 +34622,7 @@ int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -35213,7 +34645,8 @@ int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = srvRead(fileID, srvp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Failed to read record from SRV file");
 
   srvInqHeader(srvp, header);
   srvInqDataDP(srvp, data);
@@ -35231,48 +34664,19 @@ int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	data[i] = missval;
 	(*nmiss)++;
       }
-
-  return (1);
 }
 
 
-int srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "SRV");
 }
 
 
-int srvDefRecord(stream_t *streamptr)
+void srvDefRecord(stream_t *streamptr)
 {
   int gridID;
   int header[8];
-  int status = 0;
   int xsize, ysize;
   int datatype;
   int pdis, pcat, pnum;
@@ -35307,30 +34711,25 @@ int srvDefRecord(stream_t *streamptr)
   srvp->dprec = srvDefDatatype(datatype);
 
   srvDefHeader(srvp, header);
-
-  return (status);
 }
 
 
-int srvWriteRecord(stream_t *streamptr, const double *data)
+void srvWriteRecord(stream_t *streamptr, const double *data)
 {
-  int status = 0;
   int fileID = streamptr->fileID;
   srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
 
   srvDefDataDP(srvp, data);
 
   srvWrite(fileID, srvp);
-
-  return (status);
 }
 
 static
 void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ysize,
-                    long recsize, off_t position, int prec)
+                    size_t recsize, off_t position, int prec)
 {
   int leveltype;
-  int gridID = UNDEFID;
+  int gridID = CDI_UNDEFID;
   int levelID = 0;
   int tsID, recID, varID;
   int datatype;
@@ -35365,10 +34764,11 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
   datatype = srvInqDatatype(prec);
 
   varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
-	       datatype, &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -35378,33 +34778,6 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
 	    varID, gridID, levelID);
 }
 
-
-void srvCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
-		  int level, int xsize, int ysize)
-{
-  int varID = 0;
-  int levelID = 0;
-  record_t *record;
-
-  record  = &streamptr->tsteps[tsID].records[recID];
-
-  if ( param != (*record).param || level != (*record).ilevel )
-    Error("inconsistent timestep");
-
-  (*record).position = position;
-  /*
-  varID   = (*record).varID;
-  levelID = (*record).levelID;
-
-  streamptr->vars[varID].level[levelID] = recID;
-
-  streamptr->tsteps[tsID].nallrecs++;
-  streamptr->nrecs++;
-  */
-  if ( CDI_Debug )
-    Message("varID = %d levelID = %d", varID, levelID);
-}
-
 static
 void srvScanTimestep1(stream_t *streamptr)
 {
@@ -35418,7 +34791,6 @@ void srvScanTimestep1(stream_t *streamptr)
   DateTime datetime, datetime0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos;
   int nrecords, nrecs, recID;
   int taxisID = -1;
@@ -35447,7 +34819,7 @@ void srvScanTimestep1(stream_t *streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       srvInqHeader(srvp, header);
 
@@ -35498,8 +34870,8 @@ void srvScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -35511,10 +34883,11 @@ void srvScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-	(record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+	(record_t *)xrealloc(streamptr->tsteps[0].records,
+                             (size_t)nrecords * sizeof(record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -35552,7 +34925,6 @@ int srvScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -35577,7 +34949,7 @@ int srvScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -35600,7 +34972,7 @@ int srvScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       srvInqHeader(srvp, header);
 
@@ -35718,23 +35090,20 @@ int srvInqContents(stream_t *streamptr)
 }
 
 static
-int srvScanTimestep(stream_t *streamptr)
+long srvScanTimestep(stream_t *streamptr)
 {
   int header[8];
   int status;
   int fileID;
-  int tsID;
   /* int rxsize = 0, rysize = 0; */
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
   off_t recpos = 0;
   int recID;
-  taxis_t *taxis;
   int rindex, nrecs = 0;
   SRVCOMPVAR compVar, compVar0;
   srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
-
+  /*
   if ( CDI_Debug )
     {
       Message("streamID = %d", streamptr->self);
@@ -35742,12 +35111,10 @@ int srvScanTimestep(stream_t *streamptr)
       Message("rts = %d", streamptr->rtsteps);
       Message("nts = %d", streamptr->ntsteps);
     }
+  */
 
-  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;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -35756,7 +35123,7 @@ int srvScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -35773,7 +35140,7 @@ int srvScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  srvInqHeader(srvp, header);
 
@@ -35796,9 +35163,7 @@ int srvScanTimestep(stream_t *streamptr)
 	      taxis->vdate = vdate;
 	      taxis->vtime = vtime;
 	    }
-	  /*
-	  srvCmpRecord(streamptr, tsID, nrecs, recpos, param, rlevel, rxsize, rysize);
-	  */
+
 	  compVar.param  = param;
           compVar.level  = rlevel;
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
@@ -35810,7 +35175,7 @@ int srvScanTimestep(stream_t *streamptr)
 		      tsID, recID,
 		      streamptr->tsteps[tsID].records[recID].param, param,
 		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	      Error("Invalid, unsupported or inconsistent record structure");
+	      Error("Invalid, unsupported or inconsistent record structure!");
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
@@ -35848,7 +35213,8 @@ int srvScanTimestep(stream_t *streamptr)
 
 int srvInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  long ntsteps;
+  int nrecs;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
@@ -35860,7 +35226,7 @@ int srvInqTimestep(stream_t *streamptr, int tsID)
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = srvScanTimestep(streamptr);
 
-  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
+  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID )
     {
       nrecs = 0;
     }
@@ -36197,7 +35563,7 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -36220,7 +35586,8 @@ int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = extRead(fileID, extp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Failed to read EXTRA record");
 
   extInqHeader(extp, header);
   extInqDataDP(extp, data);
@@ -36250,48 +35617,19 @@ int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	    (*nmiss)++;
 	  }
     }
-
-  return (1);
 }
 
 
-int extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
 }
 
 
-int extDefRecord(stream_t *streamptr)
+void extDefRecord(stream_t *streamptr)
 {
   int gridID;
   int header[4];
-  int status = 0;
   int pdis, pcat, pnum;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
 
@@ -36306,30 +35644,24 @@ int extDefRecord(stream_t *streamptr)
   extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
 
   extDefHeader(extp, header);
-
-  return (status);
 }
 
 
-int extWriteRecord(stream_t *streamptr, const double *data)
+void extWriteRecord(stream_t *streamptr, const double *data)
 {
-  int status = 0;
   int fileID = streamptr->fileID;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
 
   extDefDataDP(extp, data);
-
   extWrite(fileID, extp);
-
-  return (status);
 }
 
 static
 void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
-		  long recsize, off_t position, int prec, int number)
+		  size_t recsize, off_t position, int prec, int number)
 {
   int leveltype;
-  int gridID = UNDEFID;
+  int gridID = CDI_UNDEFID;
   int levelID = 0;
   int tsID, recID, varID;
   record_t *record;
@@ -36361,10 +35693,10 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
   leveltype = ZAXIS_GENERIC;
 
   varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
-	       extInqDatatype(prec, number), &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -36374,33 +35706,6 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
 	    varID, gridID, levelID);
 }
 
-
-void extCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
-		  int level, int xysize)
-{
-  int varID = 0;
-  int levelID = 0;
-  record_t *record;
-
-  record  = &streamptr->tsteps[tsID].records[recID];
-
-  if ( param != (*record).param || level != (*record).ilevel )
-    Error("inconsistent timestep");
-
-  (*record).position = position;
-  /*
-  varID   = (*record).varID;
-  levelID = (*record).levelID;
-
-  streamptr->vars[varID].level[levelID] = recID;
-
-  streamptr->tsteps[tsID].nallrecs++;
-  streamptr->nrecs++;
-  */
-  if ( CDI_Debug )
-    Message("varID = %d levelID = %d", varID, levelID);
-}
-
 static
 void extScanTimestep1(stream_t *streamptr)
 {
@@ -36482,7 +35787,7 @@ void extScanTimestep1(stream_t *streamptr)
       if ( CDI_Debug )
 	Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
 
-      extAddRecord(streamptr, param, rlevel, rxysize, recsize, recpos, extp->prec, extp->number);
+      extAddRecord(streamptr, param, rlevel, rxysize, (size_t)recsize, recpos, extp->prec, extp->number);
     }
 
   streamptr->rtsteps = 1;
@@ -36491,8 +35796,8 @@ void extScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -36504,10 +35809,10 @@ void extScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-      (record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+        (record_t *)xrealloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -36546,7 +35851,6 @@ int extScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -36571,7 +35875,7 @@ int extScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -36594,7 +35898,7 @@ int extScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       extInqHeader(extp, header);
 
@@ -36618,7 +35922,7 @@ int extScanTimestep2(stream_t *streamptr)
       nextstep = FALSE;
       for ( recID = 0; recID < nrecords; recID++ )
 	{
-	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
+	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
 	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
 	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
@@ -36713,23 +36017,20 @@ int extInqContents(stream_t *streamptr)
 }
 
 static
-int extScanTimestep(stream_t *streamptr)
+long extScanTimestep(stream_t *streamptr)
 {
   int header[4];
   int status;
   int fileID;
-  int tsID;
   // int rxysize = 0;
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
   off_t recpos = 0;
   int recID;
-  taxis_t *taxis;
   int rindex, nrecs = 0;
   extcompvar_t compVar, compVar0;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
-
+  /*
   if ( CDI_Debug )
     {
       Message("streamID = %d", streamptr->self);
@@ -36737,12 +36038,10 @@ int extScanTimestep(stream_t *streamptr)
       Message("rts = %d", streamptr->rtsteps);
       Message("nts = %d", streamptr->ntsteps);
     }
+  */
 
-  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;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -36751,7 +36050,7 @@ int extScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -36768,7 +36067,7 @@ int extScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  extInqHeader(extp, header);
 
@@ -36790,9 +36089,7 @@ int extScanTimestep(stream_t *streamptr)
 	      taxis->vdate = vdate;
 	      taxis->vtime = vtime;
 	    }
-	  /*
-	  extCmpRecord(streamptr, tsID, nrecs, recpos, param, rlevel, rxysize);
-	  */
+
 	  compVar.param  = param;
           compVar.level  = rlevel;
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
@@ -36804,7 +36101,7 @@ int extScanTimestep(stream_t *streamptr)
 		      tsID, recID,
 		      streamptr->tsteps[tsID].records[recID].param, param,
 		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	      Error("Invalid, unsupported or inconsistent record structure");
+	      Error("Invalid, unsupported or inconsistent record structure!");
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
@@ -36842,7 +36139,8 @@ int extScanTimestep(stream_t *streamptr)
 
 int extInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  int nrecs;
+  long ntsteps;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
@@ -37078,6 +36376,7 @@ void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <float.h>
 #include <math.h>
@@ -37164,7 +36463,7 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -37186,7 +36485,8 @@ int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = iegRead(fileID, iegp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Could not read IEG record!");
 
   iegInqDataDP(iegp, data);
 
@@ -37203,8 +36503,6 @@ int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	data[i] = missval;
 	(*nmiss)++;
       }
-
-  return (1);
 }
 
 static
@@ -37484,8 +36782,8 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 	else
 	  {
 	    IEG_G_Size(gdb) += (vctsize*4);
-	    memcpy(vct, zaxisInqVctPtr(zaxisID), vctsize/2*sizeof(double));
-	    memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, vctsize/2*sizeof(double));
+	    memcpy(vct, zaxisInqVctPtr(zaxisID), (size_t)vctsize/2*sizeof(double));
+	    memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, (size_t)vctsize/2*sizeof(double));
 	  }
 	break;
       }
@@ -37590,41 +36888,14 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 }
 
 
-int iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "IEG");
 }
 
 
-int iegDefRecord(stream_t *streamptr)
+void iegDefRecord(stream_t *streamptr)
 {
-  int status = 0;
   int vlistID;
   int gridID;
   int date, time;
@@ -37664,15 +36935,12 @@ int iegDefRecord(stream_t *streamptr)
   datatype = streamptr->record->prec;
 
   iegp->dprec = iegDefDatatype(datatype);
-
-  return (status);
 }
 
 
-int iegWriteRecord(stream_t *streamptr, const double *data)
+void iegWriteRecord(stream_t *streamptr, const double *data)
 {
   int fileID;
-  int status = 0;
   int i, gridsize, gridID;
   double refval;
   iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
@@ -37691,13 +36959,11 @@ int iegWriteRecord(stream_t *streamptr, const double *data)
   iegDefDataDP(iegp, data);
 
   iegWrite(fileID, iegp);
-
-  return (status);
 }
 
 static
 void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
-		  long recsize, off_t position, int prec)
+		  size_t recsize, off_t position, int prec)
 {
   int leveltype;
   int gridID = UNDEFID;
@@ -37728,12 +36994,12 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
       if ( IEG_P_LevelType(pdb) == 100 ) level1 *= 100;
     }
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = IEG_P_LevelType(pdb);
+  record->size     = recsize;
+  record->position = position;
+  record->param    = param;
+  record->ilevel   = level1;
+  record->ilevel2  = level2;
+  record->ltype    = IEG_P_LevelType(pdb);
 
   if ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 )
     gridtype = GRID_LONLAT;
@@ -37763,7 +37029,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
 	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 )
 	      {
 		grid.xinc = xinc;
@@ -37817,12 +37083,11 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
 
   if ( leveltype == ZAXIS_HYBRID )
     {
-      int i;
       double tmpvct[100];
-      int vctsize = IEG_G_NumVCP(gdb);
+      size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
 
-      for ( i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
-      for ( 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);
     }
@@ -37832,10 +37097,10 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
   datatype = iegInqDatatype(prec);
 
   varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
-	       datatype, &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  record->varID   = (short)varID;
+  record->levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -37904,7 +37169,7 @@ void iegScanTimestep1(stream_t *streamptr)
   DateTime datetime, datetime0;
   int tsID;
   int varID;
-  long recsize;
+  size_t recsize;
   off_t recpos;
   int nrecords, nrecs, recID;
   int taxisID = -1;
@@ -37933,7 +37198,7 @@ void iegScanTimestep1(stream_t *streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       prec   = iegp->dprec;
       rcode  = IEG_P_Parameter(iegp->ipdb);
@@ -37986,8 +37251,8 @@ void iegScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -37999,10 +37264,11 @@ void iegScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-	(record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+	(record_t *)xrealloc(streamptr->tsteps[0].records,
+                             (size_t)nrecords * sizeof (record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -38040,7 +37306,7 @@ int iegScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
+  size_t recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -38065,7 +37331,7 @@ int iegScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = (int *)xmalloc((size_t)nrecords * sizeof(int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -38088,7 +37354,7 @@ int iegScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       rcode  = IEG_P_Parameter(iegp->ipdb);
       tabnum = IEG_P_CodeTable(iegp->ipdb);
@@ -38212,7 +37478,7 @@ int iegInqContents(stream_t *streamptr)
 }
 
 static
-int iegScanTimestep(stream_t *streamptr)
+long iegScanTimestep(stream_t *streamptr)
 {
   int status;
   int fileID;
@@ -38220,7 +37486,7 @@ int iegScanTimestep(stream_t *streamptr)
   int tabnum;
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
+  size_t recsize = 0;
   off_t recpos = 0;
   int recID;
   taxis_t *taxis;
@@ -38249,7 +37515,8 @@ int iegScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs
+        = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -38266,7 +37533,7 @@ int iegScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  rcode  = IEG_P_Parameter(iegp->ipdb);
 	  tabnum = IEG_P_CodeTable(iegp->ipdb);
@@ -38341,7 +37608,7 @@ int iegScanTimestep(stream_t *streamptr)
 
 int iegInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  int nrecs;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
@@ -38349,7 +37616,7 @@ int iegInqTimestep(stream_t *streamptr, int tsID)
   if ( CDI_Debug )
     Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
 
-  ntsteps = UNDEFID;
+  long ntsteps = UNDEFID;
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = iegScanTimestep(streamptr);
 
@@ -38584,6 +37851,8 @@ void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
 #define UNDEFID  CDI_UNDEFID
 
 
+void    vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]);
+
 void cdfDefGlobalAtts(stream_t *streamptr);
 void cdfDefLocalAtts(stream_t *streamptr);
 
@@ -38678,18 +37947,13 @@ ncvar_t;
 static
 void strtolower(char *str)
 {
-  int i, len;
-
   if ( str )
-    {
-      len = (int) strlen(str);
-      for ( i = 0; i < len; i++ )
-        str[i] = tolower((int) str[i]);
-    }
+    for (size_t i = 0; str[i]; ++i)
+      str[i] = (char)tolower((int)str[i]);
 }
 
 static
-int get_timeunit(int len, const char *ptu)
+int get_timeunit(size_t len, const char *ptu)
 {
   int timeunit = -1;
 
@@ -38728,18 +37992,17 @@ int isTimeUnits(const char *timeunits)
 static
 int isTimeAxisUnits(const char *timeunits)
 {
-  int len, i;
   char *ptu, *tu;
   int timetype = -1;
   int timeunit;
   int status = FALSE;
 
-  len = (int) strlen(timeunits);
-  tu = (char *) malloc((len+1)*sizeof(char));
-  memcpy(tu, timeunits, (len+1)*sizeof(char));
+  size_t len = strlen(timeunits);
+  tu = xmalloc((len+1)*sizeof(char));
+  memcpy(tu, timeunits, (len+1) * sizeof(char));
   ptu = tu;
 
-  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);
+  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
 
   timeunit = get_timeunit(len, ptu);
   if ( timeunit != -1 )
@@ -38847,18 +38110,17 @@ void setForecastTime(const char *timestr, taxis_t *taxis)
 static
 int setBaseTime(const char *timeunits, taxis_t *taxis)
 {
-  int len, i;
   char *ptu, *tu;
   int timetype = TAXIS_ABSOLUTE;
   int rdate = -1, rtime = -1;
   int timeunit;
 
-  len = (int) strlen(timeunits);
-  tu = (char *) malloc((len+1)*sizeof(char));
-  memcpy(tu, timeunits, (len+1)*sizeof(char));
+  size_t len = strlen(timeunits);
+  tu = xmalloc((len+1) * sizeof (char));
+  memcpy(tu, timeunits, (len+1) * sizeof (char));
   ptu = tu;
 
-  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);
+  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
 
   timeunit = get_timeunit(len, ptu);
   if ( timeunit == -1 )
@@ -38928,7 +38190,7 @@ void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attin
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
   if ( (int)nc_attlen > attlen )
-    pintatt = (int *) malloc(nc_attlen*sizeof(int));
+    pintatt = (int *) malloc(nc_attlen * sizeof (int));
   else
     pintatt = attint;
 
@@ -38936,7 +38198,7 @@ void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attin
 
   if ( (int)nc_attlen > attlen )
     {
-      memcpy(attint, pintatt, attlen*sizeof(int));
+      memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
       free(pintatt);
     }
 }
@@ -38950,7 +38212,7 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
   if ( (int)nc_attlen > attlen )
-    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
+    pdoubleatt = (double *) malloc(nc_attlen * sizeof (double));
   else
     pdoubleatt = attdouble;
 
@@ -38958,7 +38220,7 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
 
   if ( (int)nc_attlen > attlen )
     {
-      memcpy(attdouble, pdoubleatt, attlen*sizeof(double));
+      memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
       free(pdoubleatt);
     }
 }
@@ -38966,31 +38228,75 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
 static
 void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
 {
+  nc_type atttype;
   size_t nc_attlen;
-  char attbuf[65636];
 
+  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
-  if ( nc_attlen < sizeof(attbuf) )
+  if ( atttype == NC_CHAR )
     {
-      cdf_get_att_text(fileID, ncvarid, attname, attbuf);
+      char attbuf[65636];
+      if ( nc_attlen < sizeof(attbuf) )
+        {
+          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
 
-      attbuf[nc_attlen++] = 0;
+          attbuf[nc_attlen++] = 0;
 
-      if ( (int) nc_attlen > attlen ) nc_attlen = attlen;
-      memcpy(atttext, attbuf, nc_attlen);
+          if ( (int) nc_attlen > attlen ) nc_attlen = (size_t)attlen;
+          memcpy(atttext, attbuf, nc_attlen);
+        }
+      else
+        {
+          atttext[0] = 0;
+        }
     }
-  else
+#if  defined  (HAVE_NETCDF4)
+  else if ( atttype == NC_STRING )
     {
-      atttext[0] = 0;
+      if ( nc_attlen == 1 )
+        {
+          char *attbuf = NULL;
+          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
+
+          int slen = (int) strlen(attbuf);
+          slen++;
+
+          if ( slen > attlen ) slen = attlen;
+          memcpy(atttext, attbuf, slen);
+
+          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 = FALSE;
+
   if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
+
   return isFloat;
 }
 
@@ -39079,19 +38385,17 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
 
       if ( atttype == DATATYPE_TXT )
         {
-          char *atttxt;
-          atttxt = (char *) malloc(attlen*sizeof(char));
+          char *atttxt = (char *)xmalloc((size_t)attlen*sizeof(char));
           vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
-          len = attlen;
+          len = (size_t)attlen;
           cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
           free(atttxt);
         }
       else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
         {
-          int *attint;
-          attint = (int *) malloc(attlen*sizeof(int));
+          int *attint = (int *)xmalloc((size_t)attlen*sizeof(int));
           vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
-          len = attlen;
+          len = (size_t)attlen;
           if ( atttype == DATATYPE_INT16 )
             cdf_put_att_int(fileID, ncvarID, attname, NC_SHORT, len, attint);
           else
@@ -39100,10 +38404,9 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
         }
       else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
         {
-          double *attflt;
-          attflt = (double *) malloc(attlen*sizeof(double));
+          double *attflt = (double *)xmalloc((size_t)attlen*sizeof(double));
           vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
-          len = attlen;
+          len = (size_t)attlen;
           if ( atttype == DATATYPE_FLT32 )
             cdf_put_att_double(fileID, ncvarID, attname, NC_FLOAT, len, attflt);
           else
@@ -39114,39 +38417,30 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
 }
 #endif
 
-int cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  double *data;
-  int datasize;
-  int tsID1, recID1;
-  int ivarID, gridID;
-  int nmiss;
-  int ierr = 0;
   int memtype = MEMTYPE_DOUBLE;
-  int vlistID1;
-
-  vlistID1 = streamptr1->vlistID;
+  int vlistID1 = streamptr1->vlistID;
 
-  tsID1 = streamptr1->curTsID;
+  int tsID1 = streamptr1->curTsID;
 
-  recID1 = streamptr1->tsteps[tsID1].curRecID;
+  int recID1 = streamptr1->tsteps[tsID1].curRecID;
 
-  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;
+  int ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;
 
-  gridID = vlistInqVarGrid(vlistID1, ivarID);
+  int gridID = vlistInqVarGrid(vlistID1, ivarID);
 
-  datasize = gridInqSize(gridID);
+  int datasize = gridInqSize(gridID);
   /* bug fix for constant netCDF fields */
   if ( datasize < 1048576 ) datasize = 1048576;
 
-  data = (double *) malloc(datasize*sizeof(double));
+  double *data = xmalloc((size_t)datasize * sizeof (double));
 
+  int nmiss;
   cdfReadRecord(streamptr1, data, &nmiss);
   cdf_write_record(streamptr2, memtype, data, nmiss);
 
   free(data);
-
-  return (ierr);
 }
 
 /* not used
@@ -39177,36 +38471,25 @@ int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
 */
 
 
-int cdfDefRecord(stream_t *streamptr)
+void cdfDefRecord(stream_t *streamptr)
 {
-  int ierr = 0;
-
-  if ( streamptr->fileID < 0 ) ierr = 1;
-
-  return (ierr);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
 static
 void cdfWriteGridTraj(stream_t *streamptr, int gridID)
 {
-  int tsID, fileID;
-  int lonID, latID, gridindex;
-  size_t index;
-  double xlon, xlat;
-  int vlistID;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  lonID = streamptr->xdimID[gridindex];
-  latID = streamptr->ydimID[gridindex];
+  int gridindex = vlistGridIndex(vlistID, gridID);
+  int lonID = streamptr->xdimID[gridindex],
+    latID = streamptr->ydimID[gridindex];
 
-  xlon = gridInqXval(gridID, 0);
-  xlat = gridInqYval(gridID, 0);
-  tsID = streamptr->curTsID;
-  index = tsID;
+  double xlon = gridInqXval(gridID, 0),
+    xlat = gridInqYval(gridID, 0);
+  int tsID = streamptr->curTsID;
+  size_t index = (size_t)tsID;
 
   cdf_put_var1_double(fileID, lonID, &index, &xlon);
   cdf_put_var1_double(fileID, latID, &index, &xlat);
@@ -39215,22 +38498,17 @@ void cdfWriteGridTraj(stream_t *streamptr, int gridID)
 static
 void cdfReadGridTraj(stream_t *streamptr, int gridID)
 {
-  int tsID, fileID;
-  int lonID, latID, gridindex;
-  size_t index;
-  double xlon, xlat;
-  int vlistID;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  lonID = streamptr->xdimID[gridindex];
-  latID = streamptr->ydimID[gridindex];
+  int gridindex = vlistGridIndex(vlistID, gridID);
+  int lonID = streamptr->xdimID[gridindex];
+  int latID = streamptr->ydimID[gridindex];
 
-  tsID = streamptr->curTsID;
-  index = tsID;
+  int tsID = streamptr->curTsID;
+  size_t index = (size_t)tsID;
 
+  double xlon, xlat;
   cdf_get_var1_double(fileID, lonID, &index, &xlon);
   cdf_get_var1_double(fileID, latID, &index, &xlat);
 
@@ -39342,10 +38620,8 @@ void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nm
 #endif
 }
 
-
-int cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
-  int ierr = 0;
   int levelID, varID, tsID, recID, vrecID;
 
   if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
@@ -39357,8 +38633,6 @@ int cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
   levelID = streamptr->tsteps[tsID].records[recID].levelID;
 
   cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
-
-  return (ierr);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
@@ -39366,9 +38640,7 @@ static
 void cdfDefTimeValue(stream_t *streamptr, int tsID)
 {
   int fileID;
-  double timevalue;
   int ncvarid;
-  size_t index;
   taxis_t *taxis;
 
   fileID = streamptr->fileID;
@@ -39384,9 +38656,9 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       streamptr->ncmode = 2;
     }
 
-  index = tsID;
+  size_t index = (size_t)tsID;
 
-  timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
+  double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
   if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
 
   ncvarid = streamptr->basetime.ncvarid;
@@ -39399,11 +38671,11 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       ncvarid = streamptr->basetime.ncvarboundsid;
 
       timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
-      start[0] = tsID; count[0] = 1; start[1] = 0; count[1] = 1;
+      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] = tsID; count[0] = 1; start[1] = 1; count[1] = 1;
+      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
       cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
     }
 
@@ -39486,7 +38758,8 @@ void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
       cdiDecodeDate(rdate, &year, &month, &day);
       cdiDecodeTime(rtime, &hour, &minute, &second);
 
-      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
+      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;
@@ -39503,7 +38776,8 @@ void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
 
   if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
 
-  if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
+  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;
@@ -39649,7 +38923,6 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
   int gridID0, gridtype0, gridindex;
   int ngrids;
   int fileID;
-  int dimlen;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -39673,7 +38946,7 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      dimlen = 2;
+      size_t dimlen = 2;
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
@@ -39701,7 +38974,6 @@ void cdfDefSP(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -39709,7 +38981,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID)/2;
+  size_t dimlen = (size_t)gridInqSize(gridID)/2;
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -39719,7 +38991,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_SPECTRAL )
             {
-              dimlen0 = gridInqSize(gridID0)/2;
+              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
                 {
                   dimID = streamptr->ydimID[index];
@@ -39759,7 +39031,6 @@ void cdfDefFC(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -39767,7 +39038,7 @@ void cdfDefFC(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID)/2;
+  size_t dimlen = (size_t)gridInqSize(gridID)/2;
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -39777,7 +39048,7 @@ void cdfDefFC(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_FOURIER )
             {
-              dimlen0 = gridInqSize(gridID0)/2;
+              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
                 {
                   dimID = streamptr->ydimID[index];
@@ -39937,7 +39208,7 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
   checkname = TRUE;
   iz = 0;
 
-  while ( checkname )
+  do
     {
       strcpy(axisname2, axisname);
       if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%d", iz+1);
@@ -39975,9 +39246,9 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
         }
 
       if ( checkname ) iz++;
-
-      if ( iz > 99 ) break;
     }
+  while (checkname && iz <= 99);
+
 
   if ( iz ) sprintf(&axisname[strlen(axisname)], "_%d", iz+1);
 
@@ -40000,10 +39271,9 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
   int dimIDs[2];
   int ngrids = 0;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -40014,7 +39284,7 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqXsize(gridID);
+  size_t dimlen = (size_t)gridInqXsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, axisname);
@@ -40035,10 +39305,10 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqXsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
               if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, dimlen-1), gridInqXval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
                   {
                     dimID = streamptr->xdimID[index];
                     break;
@@ -40068,6 +39338,7 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
 
           if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
             {
+              size_t nvertex = 2;
               if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
                 cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
             }
@@ -40131,10 +39402,9 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
   int dimIDs[2];
   int ngrids = 0;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -40145,7 +39415,7 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqYsize(gridID);
+  size_t dimlen = (size_t)gridInqYsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqYname(gridID, axisname);
@@ -40166,10 +39436,10 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqYsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqYsize(gridID0);
               if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, dimlen-1), gridInqYval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
                   {
                     dimID = streamptr->ydimID[index];
                     break;
@@ -40199,6 +39469,7 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
 
           if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
             {
+              size_t nvertex = 2;
               if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
                 cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
             }
@@ -40282,11 +39553,10 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
   int dimIDs[3];
   int ngrids;
   int fileID;
-  int xdimlen, ydimlen, dimlen0;
   size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvertex = 4, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -40297,8 +39567,8 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  xdimlen = gridInqXsize(gridID);
-  ydimlen = gridInqYsize(gridID);
+  size_t xdimlen = (size_t)gridInqXsize(gridID);
+  size_t ydimlen = (size_t)gridInqYsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, xaxisname);
@@ -40321,19 +39591,19 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqXsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
               if ( xdimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, xdimlen-1), gridInqXval(gridID, xdimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)xdimlen-1), gridInqXval(gridID, (int)xdimlen-1)) )
                   {
                     xdimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
                     break;
                   }
-              dimlen0 = gridInqYsize(gridID0);
+              dimlen0 = (size_t)gridInqYsize(gridID0);
               if ( ydimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, xdimlen-1), gridInqYval(gridID, xdimlen-1)) )
+                     IS_EQUAL(gridInqYval(gridID0, (int)xdimlen-1), gridInqYval(gridID, (int)xdimlen-1)) )
                   {
                     ydimID = streamptr->ydimID[index];
                     ncyvarid = streamptr->ncyvarID[index];
@@ -40357,6 +39627,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
       if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
         {
+          size_t nvertex = 4;
           if ( nc_inq_dimid(fileID, "nv4", &nvdimID) != NC_NOERR )
             cdf_def_dim(fileID, "nv4", nvertex, &nvdimID);
         }
@@ -40367,7 +39638,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
       if ( gridInqXvalsPtr(gridID) )
         {
           cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(xstdname)) )
             cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
@@ -40386,7 +39657,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
               dimIDs[1] = xdimID;
               dimIDs[2] = nvdimID;
               cdf_def_var(fileID, xaxisname, (nc_type) xtype, 3, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
             }
@@ -40395,7 +39666,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
       if ( gridInqYvalsPtr(gridID) )
         {
           cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(ystdname)) )
             cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
@@ -40414,7 +39685,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
               dimIDs[1] = xdimID;
               dimIDs[2] = nvdimID;
               cdf_def_var(fileID, yaxisname, (nc_type) xtype, 3, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
             }
@@ -40462,7 +39733,6 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
   int lwarn = TRUE;
 
@@ -40471,7 +39741,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -40481,7 +39751,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
             {
-              dimlen0 = gridInqSize(gridID0);
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
 
               if ( dimlen == dimlen0 )
                 {
@@ -40528,7 +39798,6 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -40536,7 +39805,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
 
   if ( gridInqYsize(gridID) == 0 )
     for ( index = 0; index < ngrids; index++ )
@@ -40547,7 +39816,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
             gridtype0 = gridInqType(gridID0);
             if ( gridtype0 == GRID_GENERIC )
               {
-                dimlen0 = gridInqSize(gridID0);
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
                 if ( dimlen == dimlen0 )
                   {
                     dimID = streamptr->xdimID[index];
@@ -40568,7 +39837,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
             gridtype0 = gridInqType(gridID0);
             if ( gridtype0 == GRID_GENERIC )
               {
-                dimlen0 = gridInqSize(gridID0);
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
                 if ( dimlen == dimlen0 )
                   {
                     dimID = streamptr->ydimID[index];
@@ -40682,11 +39951,10 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvertex, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -40697,7 +39965,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, xaxisname);
@@ -40717,11 +39985,11 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_UNSTRUCTURED )
             {
-              dimlen0 = gridInqSize(gridID0);
+              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, dimlen-1), gridInqXval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
 		  {
 		    dimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
@@ -40749,7 +40017,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
       cdf_def_dim(fileID, axisname, dimlen, &dimID);
 
-      nvertex = gridInqNvertex(gridID);
+      size_t nvertex = (size_t)gridInqNvertex(gridID);
       if ( nvertex > 0 ) cdf_def_dim(fileID, vertname, nvertex, &nvdimID);
 
       cdfDefGridReference(streamptr, gridID);
@@ -40759,7 +40027,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
       if ( gridInqXvalsPtr(gridID) )
         {
           cdf_def_var(fileID, xaxisname, (nc_type) xtype, 1, &dimID, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, dimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(xstdname)) )
             cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
@@ -40775,7 +40043,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               dimIDs[1] = nvdimID;
               strcat(xaxisname, "_vertices");
               cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, dimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
             }
@@ -40784,7 +40052,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
       if ( gridInqYvalsPtr(gridID) )
         {
           cdf_def_var(fileID, yaxisname, (nc_type) xtype, 1, &dimID, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, dimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(ystdname)) )
             cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
@@ -40800,7 +40068,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               dimIDs[1] = nvdimID;
               strcat(yaxisname, "_vertices");
               cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, dimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
             }
@@ -40874,8 +40142,8 @@ void cdfDefVCT(stream_t *streamptr, int zaxisID)
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      cdf_def_dim(fileID, "nhym", mlev, &ncdimid);
-      cdf_def_dim(fileID, "nhyi", ilev, &ncdimid2);
+      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;
@@ -40914,7 +40182,7 @@ void cdfDefVCT(stream_t *streamptr, int zaxisID)
 
       for ( i = 0; i < mlev; i++ )
         {
-          start = 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;
@@ -40939,10 +40207,9 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
   int dimID = UNDEFID;
   int dimIDs[2];
   int fileID;
-  int dimlen;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int type;
   int nzaxis;
   int ilevel = 0;
@@ -40960,22 +40227,27 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
   nzaxis = vlistNzaxis(vlistID);
 
-  dimlen = zaxisInqSize(zaxisID);
+  size_t dimlen = (size_t)zaxisInqSize(zaxisID);
   type   = zaxisInqType(zaxisID);
 
-  if ( dimlen == 1 && type == ZAXIS_SURFACE            ) return;
-  if ( dimlen == 1 && type == ZAXIS_CLOUD_BASE         ) return;
-  if ( dimlen == 1 && type == ZAXIS_CLOUD_TOP          ) return;
-  if ( dimlen == 1 && type == ZAXIS_ISOTHERM_ZERO      ) return;
-  if ( dimlen == 1 && type == ZAXIS_TOA                ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEA_BOTTOM         ) return;
-  if ( dimlen == 1 && type == ZAXIS_ATMOSPHERE         ) return;
-  if ( dimlen == 1 && type == ZAXIS_MEANSEA            ) return;
-  if ( dimlen == 1 && type == ZAXIS_LAKE_BOTTOM        ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM    ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM_TA ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM_TW ) return;
-  if ( dimlen == 1 && type == ZAXIS_MIX_LAYER          ) return;
+  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);
   /*
@@ -41140,6 +40412,7 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
 	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
             {
+              size_t nvertex = 2;
 	      if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
 		cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
 
@@ -41160,7 +40433,6 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
           if ( ncbvarid != UNDEFID )
 	    {
-	      int i;
 	      double *zbounds, *lbounds, *ubounds;
 
 	      lbounds = (double *) malloc(dimlen*sizeof(double));
@@ -41170,7 +40442,7 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 	      zaxisInqLbounds(zaxisID, lbounds);
 	      zaxisInqUbounds(zaxisID, ubounds);
 
-	      for ( i = 0; i < dimlen; ++i )
+	      for (size_t i = 0; i < dimlen; ++i )
 		{
 		  zbounds[2*i  ] = lbounds[i];
 		  zbounds[2*i+1] = ubounds[i];
@@ -41439,7 +40711,6 @@ int cdfDefVar(stream_t *streamptr, int varID)
   size_t chunks[4] = {0,0,0,0};
   int tableID;
   int ndims = 0;
-  int len;
   int tsteptype;
   int xtype, dtype;
   int gridtype, gridsize;
@@ -41447,8 +40718,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
   int tablenum;
   int vlistID;
   int dimorder[3];
-  int ixyz;
-  int iax = 0;
+  size_t iax = 0;
   char axis[5];
   int ensID, ensCount, forecast_type;
   int retval;
@@ -41471,8 +40741,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   chunktype = vlistInqVarChunkType(vlistID, varID);
 
-  ixyz    = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
+  vlistInqVarDimorder(vlistID, varID, &dimorder);
 
   gridsize  = gridInqSize(gridID);
   if ( gridsize > 1 ) lchunk = TRUE;
@@ -41489,14 +40758,11 @@ int cdfDefVar(stream_t *streamptr, int varID)
   zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
   zid = streamptr->zaxisID[zaxisindex];
 
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
   if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
 
   if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
     {
-      printf("xyz=%d  zid=%d  yid=%d  xid=%d\n", ixyz, zid, yid, xid);
+      printf("zid=%d  yid=%d  xid=%d\n", zid, yid, xid);
       Error("Internal problem, dimension order missing!");
     }
 
@@ -41728,7 +40994,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT  && gridtype != GRID_CURVILINEAR )
     {
-      len = strlen(gridNamePtr(gridtype));
+      size_t len = strlen(gridNamePtr(gridtype));
       if ( len > 0 )
         cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
     }
@@ -41913,9 +41179,8 @@ int cdfDefVar(stream_t *streamptr, int varID)
 }
 
 static
-void scale_add(long size, double *data, double addoffset, double scalefactor)
+void scale_add(size_t size, double *data, double addoffset, double scalefactor)
 {
-  long i;
   int laddoffset;
   int lscalefactor;
 
@@ -41924,7 +41189,7 @@ void scale_add(long size, double *data, double addoffset, double scalefactor)
 
   if ( laddoffset || lscalefactor )
     {
-      for ( i = 0; i < size; ++i )
+      for (size_t i = 0; i < size; ++i )
         {
           if ( lscalefactor ) data[i] *= scalefactor;
           if ( laddoffset )   data[i] += addoffset;
@@ -41933,38 +41198,376 @@ void scale_add(long size, double *data, double addoffset, double scalefactor)
 }
 #endif
 
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+#if defined (HAVE_LIBNETCDF)
+static
+void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
 {
+  int vlistID = streamptr->vlistID;
+  int tsID = streamptr->curTsID;
+  int gridID    = vlistInqVarGrid(vlistID, varID);
+  int zaxisID   = vlistInqVarZaxis(vlistID, varID);
+  int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+  int gridindex = vlistGridIndex(vlistID, gridID);
+
+  if ( CDI_Debug ) Message("tsID = %d", tsID);
+
+  int xid = UNDEFID, yid = UNDEFID;
+  if ( gridInqType(gridID) == GRID_TRAJECTORY )
+    {
+      cdfReadGridTraj(streamptr, gridID);
+    }
+  else
+    {
+      xid = streamptr->xdimID[gridindex];
+      yid = streamptr->ydimID[gridindex];
+    }
+  int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+  int zid = streamptr->zaxisID[zaxisindex];
+
+  int ndims = 0;
+#define addDimension(startCoord, length) do \
+    { \
+      (*start)[ndims] = startCoord; \
+      (*count)[ndims] = length; \
+      ndims++; \
+    } while(0)
+  if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+  if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
+  if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
+  if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
+#undef addDimension
+
+  assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+  assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+
+  if ( CDI_Debug )
+    for (int idim = 0; idim < ndims; idim++)
+      Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
+}
+
+//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
+//Returns the number of missVals encountered.
+static
+size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissval, double missVal, double scaleFactor, double offset)
+ {
+  const bool haveOffset   = IS_NOT_EQUAL(offset, 0);
+  const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+  size_t missValCount = 0;
+
+  switch ((int)haveMissval | ((int)haveScaleFactor << 1) | ((int)haveOffset << 2))
+    {
+    case 7: /* haveMissval & haveScaleFactor & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 6: /* haveOffset & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 5: /* haveMissval & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] += offset;
+      break;
+    case 4: /* haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] += offset;
+      break;
+    case 3: /* haveMissval & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] *= scaleFactor;
+      break;
+    case 2: /* haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] *= scaleFactor;
+      break;
+    case 1: /* haveMissval */
+      for ( size_t i = 0; i < valueCount; i++ )
+        missValCount += DBL_IS_EQUAL(data[i], missVal);
+      break;
+    }
+
+  return missValCount;
+}
+
+static
+size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissval, double missVal, double scaleFactor, double offset)
+ {
+  const bool haveOffset   = IS_NOT_EQUAL(offset, 0);
+  const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+  size_t missValCount = 0;
+
+  switch ((int)haveMissval | ((int)haveScaleFactor << 1) | ((int)haveOffset << 2))
+    {
+    case 7: /* haveMissval & haveScaleFactor & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 6: /* haveOffset & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 5: /* haveMissval & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] += offset;
+      break;
+    case 4: /* haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] += offset;
+      break;
+    case 3: /* haveMissval & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] *= scaleFactor;
+      break;
+    case 2: /* haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] *= scaleFactor;
+      break;
+    case 1: /* haveMissval */
+      for ( size_t i = 0; i < valueCount; i++ )
+        missValCount += DBL_IS_EQUAL(data[i], missVal);
+      break;
+    }
+
+  return missValCount;
+}
+#endif
+
+#if defined(HAVE_LIBNETCDF)
+static void
+cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
+{
+  const double *pdata_dp = (const double *) data;
+  double *mdata_dp = NULL;
+  double *sdata_dp = NULL;
+  const float *pdata_sp = (const float *) data;
+  float *mdata_sp = NULL;
+  float *sdata_sp = NULL;
+  extern int CDF_Debug;
+
+  /*  if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
+    {
+      bool laddoffset, lscalefactor;
+      double addoffset, scalefactor;
+      double missval;
+
+      addoffset    = vlistInqVarAddoffset(vlistID, varID);
+      scalefactor  = vlistInqVarScalefactor(vlistID, varID);
+      laddoffset   = IS_NOT_EQUAL(addoffset, 0);
+      lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+      missval      = vlistInqVarMissval(vlistID, varID);
+
+      if ( laddoffset || lscalefactor )
+        {
+          if ( memtype == MEMTYPE_FLOAT )
+            {
+              mdata_sp = (float *) malloc((size_t)nvals*sizeof(float));
+              memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof (float));
+              pdata_sp = mdata_sp;
+
+              if ( nmiss > 0 )
+                {
+                  for (long i = 0; i < nvals; i++ )
+                    {
+                      double temp = mdata_sp[i];
+                      if ( !DBL_IS_EQUAL(temp, missval) )
+                        {
+                          if ( laddoffset )   temp -= addoffset;
+                          if ( lscalefactor ) temp /= scalefactor;
+                          mdata_sp[i] = temp;
+                        }
+                    }
+                }
+              else
+                {
+                  for (long i = 0; i < nvals; i++ )
+                    {
+                      double temp = mdata_sp[i];
+                      if ( laddoffset )   temp -= addoffset;
+                      if ( lscalefactor ) temp /= scalefactor;
+                      mdata_sp[i] = temp;
+                    }
+                }
+            }
+          else
+            {
+              mdata_dp = (double *) malloc((size_t)nvals * sizeof(double));
+              memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof(double));
+              pdata_dp = mdata_dp;
+
+              if ( nmiss > 0 )
+                {
+                  for (long i = 0; i < nvals; i++ )
+                    {
+                      if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
+                        {
+                          if ( laddoffset )   mdata_dp[i] -= addoffset;
+                          if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+                        }
+                    }
+                }
+              else
+                {
+                  for (long i = 0; i < nvals; i++ )
+                    {
+                      if ( laddoffset )   mdata_dp[i] -= addoffset;
+                      if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+                    }
+                }
+            }
+        }
+
+      if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
+           dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
+        {
+          if ( memtype == MEMTYPE_FLOAT )
+            {
+              if ( mdata_sp == NULL )
+                {
+                  mdata_sp = (float *) malloc((size_t)nvals * sizeof(float));
+                  memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof(float));
+                  pdata_sp = mdata_sp;
+                }
+
+              for (long i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
+
+              if ( dtype == DATATYPE_UINT8 )
+                {
+                  nc_type xtype;
+                  cdf_inq_vartype(fileID, ncvarid, &xtype);
+                  if ( xtype == NC_BYTE )
+                    {
+                      for ( long i = 0; i < nvals; ++i )
+                        if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
+                    }
+                }
+            }
+          else
+            {
+              if ( mdata_dp == NULL )
+                {
+                  mdata_dp = (double *) malloc((size_t)nvals * sizeof (double));
+                  memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof (double));
+                  pdata_dp = mdata_dp;
+                }
+
+              for (long i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
+
+              if ( dtype == DATATYPE_UINT8 )
+                {
+                  nc_type xtype;
+                  cdf_inq_vartype(fileID, ncvarid, &xtype);
+                  if ( xtype == NC_BYTE )
+                    {
+                      for (long i = 0; i < nvals; ++i )
+                        if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
+                    }
+                }
+            }
+        }
+
+      if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
+        {
+          double fmin, fmax;
+          fmin =  1.0e200;
+          fmax = -1.0e200;
+          for ( long i = 0; i < nvals; ++i )
+            {
+              if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
+                {
+                  if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
+                  if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
+                }
+            }
+          Message("nvals = %d, nmiss = %d, missval = %g, minval = %g, maxval = %g",
+                  nvals, nmiss, missval, fmin, fmax);
+        }
+    }
+
+  if ( swapxy )
+    {
+      if ( memtype == MEMTYPE_FLOAT )
+        {
+          /* malloc and the loop imply nvals >= ysize * xsize,
+           * but that is not checked and the types don't match */
+          sdata_sp = (float *)xmalloc((size_t)nvals * sizeof (float));
+          for ( size_t j = 0; j < ysize; ++j )
+            for ( size_t i = 0; i < xsize; ++i )
+              sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
+          pdata_sp = sdata_sp;
+        }
+      else
+        {
+          sdata_dp = (double *)xmalloc((size_t)nvals * sizeof (double));
+          for ( size_t j = 0; j < ysize; ++j )
+            for ( size_t i = 0; i < xsize; ++i )
+              sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
+          pdata_dp = sdata_dp;
+        }
+    }
+
+  if ( memtype == MEMTYPE_FLOAT )
+    cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
+  else
+    cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
+
+  if ( mdata_dp ) free(mdata_dp);
+  if ( sdata_dp ) free(sdata_dp);
+  if ( mdata_sp ) free(mdata_sp);
+  if ( sdata_sp ) free(sdata_sp);
+}
+#endif
+
 #if  defined  (HAVE_LIBNETCDF)
+void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
+{
   int fileID;
   int gridID;
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int tsID;
+  size_t xsize = 0, ysize = 0;
   size_t size;
   size_t start[5];
   size_t count[5];
+  long nvals;
+  int swapxy = FALSE;
   int ndims = 0;
   int idim;
   int tsteptype;
   int gridindex, zaxisindex;
+  int dtype;
   int vlistID;
-  int i;
-  double missval;
-  int laddoffset, lscalefactor;
-  double addoffset, scalefactor;
 
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
   vlistID = streamptr->vlistID;
   fileID  = streamptr->fileID;
 
-  tsID = streamptr->curTsID;
+  long ntsteps = streamptr->ntsteps;
+  if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
 
-  if ( CDI_Debug ) Message("tsID = %d", tsID);
+  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
-  ncvarid = streamptr->vars[varID].ncvarid;
+  ncvarid = cdfDefVar(streamptr, varID);
 
   gridID    = vlistInqVarGrid(vlistID, varID);
   zaxisID   = vlistInqVarZaxis(vlistID, varID);
@@ -41973,7 +41576,7 @@ void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
   gridindex = vlistGridIndex(vlistID, gridID);
   if ( gridInqType(gridID) == GRID_TRAJECTORY )
     {
-      cdfReadGridTraj(streamptr, gridID);
+      cdfWriteGridTraj(streamptr, gridID);
     }
   else
     {
@@ -41986,323 +41589,14 @@ void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = tsID;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
   if ( zid != UNDEFID )
     {
       start[ndims] = 0;
-      count[ndims] = zaxisInqSize(zaxisID);
-      ndims++;
-    }
-  if ( yid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = gridInqYsize(gridID);
-      ndims++;
-    }
-  if ( xid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = gridInqXsize(gridID);
-      ndims++;
-    }
-
-  if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
-      Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
-
-  cdf_get_vara_double(fileID, ncvarid, start, count, data);
-
-  *nmiss = 0;
-  if ( vlistInqVarMissvalUsed(vlistID, varID) == TRUE  )
-    {
-      size    = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-      missval = vlistInqVarMissval(vlistID, varID);
-
-      for ( i = 0; i < (int) size; i++ )
-        if ( DBL_IS_EQUAL(data[i], missval) ) *nmiss += 1;
-    }
-
-  addoffset    = vlistInqVarAddoffset(vlistID, varID);
-  scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-  laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-  lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
-  if ( laddoffset || lscalefactor )
-    {
-      size    = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-      missval = vlistInqVarMissval(vlistID, varID);
-
-      if ( *nmiss > 0 )
-        {
-          for ( i = 0; i < (int) size; i++ )
-            {
-              if ( !DBL_IS_EQUAL(data[i], missval) )
-                {
-                  if ( lscalefactor ) data[i] *= scalefactor;
-                  if ( laddoffset )   data[i] += addoffset;
-                }
-            }
-        }
-      else
-        {
-          for ( i = 0; i < (int) size; i++ )
-            {
-              if ( lscalefactor ) data[i] *= scalefactor;
-              if ( laddoffset )   data[i] += addoffset;
-            }
-        }
-    }
-#endif
-}
-
-#if defined(HAVE_LIBNETCDF)
-static
-int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
-{
-  long i, j;
-  const double *pdata_dp = (const double *) data;
-  double *mdata_dp = NULL;
-  double *sdata_dp = NULL;
-  const float *pdata_sp = (const float *) data;
-  float *mdata_sp = NULL;
-  float *sdata_sp = NULL;
-  extern int CDF_Debug;
-
-  /*  if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
-    {
-      int laddoffset, lscalefactor;
-      double addoffset, scalefactor;
-      double missval;
-
-      addoffset    = vlistInqVarAddoffset(vlistID, varID);
-      scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-      laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-      lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
-      missval      = vlistInqVarMissval(vlistID, varID);
-
-      if ( laddoffset || lscalefactor )
-        {
-          if ( memtype == MEMTYPE_FLOAT )
-            {
-              mdata_sp = (float *) malloc(nvals*sizeof(float));
-              memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
-              pdata_sp = mdata_sp;
-
-              if ( nmiss > 0 )
-                {
-                  for ( i = 0; i < nvals; i++ )
-                    {
-                      if ( !DBL_IS_EQUAL(mdata_sp[i], missval) )
-                        {
-                          if ( laddoffset )   mdata_sp[i] -= addoffset;
-                          if ( lscalefactor ) mdata_sp[i] /= scalefactor;
-                        }
-                    }
-                }
-              else
-                {
-                  for ( i = 0; i < nvals; i++ )
-                    {
-                      if ( laddoffset )   mdata_sp[i] -= addoffset;
-                      if ( lscalefactor ) mdata_sp[i] /= scalefactor;
-                    }
-                }
-            }
-          else
-            {
-              mdata_dp = (double *) malloc(nvals*sizeof(double));
-              memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
-              pdata_dp = mdata_dp;
-
-              if ( nmiss > 0 )
-                {
-                  for ( i = 0; i < nvals; i++ )
-                    {
-                      if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
-                        {
-                          if ( laddoffset )   mdata_dp[i] -= addoffset;
-                          if ( lscalefactor ) mdata_dp[i] /= scalefactor;
-                        }
-                    }
-                }
-              else
-                {
-                  for ( i = 0; i < nvals; i++ )
-                    {
-                      if ( laddoffset )   mdata_dp[i] -= addoffset;
-                      if ( lscalefactor ) mdata_dp[i] /= scalefactor;
-                    }
-                }
-            }
-        }
-
-      if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
-           dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
-        {
-          if ( memtype == MEMTYPE_FLOAT )
-            {
-              if ( mdata_sp == NULL )
-                {
-                  mdata_sp = (float *) malloc(nvals*sizeof(float));
-                  memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
-                  pdata_sp = mdata_sp;
-                }
-
-              for ( i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
-
-              if ( dtype == DATATYPE_UINT8 )
-                {
-                  nc_type xtype;
-                  cdf_inq_vartype(fileID, ncvarid, &xtype);
-                  if ( xtype == NC_BYTE )
-                    {
-                      for ( i = 0; i < nvals; ++i )
-                        if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
-                    }
-                }
-            }
-          else
-            {
-              if ( mdata_dp == NULL )
-                {
-                  mdata_dp = (double *) malloc(nvals*sizeof(double));
-                  memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
-                  pdata_dp = mdata_dp;
-                }
-
-              for ( i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
-
-              if ( dtype == DATATYPE_UINT8 )
-                {
-                  nc_type xtype;
-                  cdf_inq_vartype(fileID, ncvarid, &xtype);
-                  if ( xtype == NC_BYTE )
-                    {
-                      for ( i = 0; i < nvals; ++i )
-                        if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
-                    }
-                }
-            }
-        }
-
-      if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
-        {
-          double fmin, fmax;
-          fmin =  1.0e200;
-          fmax = -1.0e200;
-          for ( i = 0; i < nvals; ++i )
-            {
-              if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
-                {
-                  if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
-                  if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
-                }
-            }
-          Message("nvals = %d, nmiss = %d, missval = %g, minval = %g, maxval = %g",
-                  nvals, nmiss, missval, fmin, fmax);
-        }
-    }
-
-  if ( swapxy )
-    {
-      if ( memtype == MEMTYPE_FLOAT )
-        {
-          sdata_sp = (float *) malloc(nvals*sizeof(float));
-          for ( j = 0; j < (long)ysize; ++j )
-            for ( i = 0; i < (long)xsize; ++i )
-              sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
-          pdata_sp = sdata_sp;
-        }
-      else
-        {
-          sdata_dp = (double *) malloc(nvals*sizeof(double));
-          for ( j = 0; j < (long)ysize; ++j )
-            for ( i = 0; i < (long)xsize; ++i )
-              sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
-          pdata_dp = sdata_dp;
-        }
-    }
-
-  if ( memtype == MEMTYPE_FLOAT )
-    cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
-  else
-    cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
-
-  if ( mdata_dp ) free(mdata_dp);
-  if ( sdata_dp ) free(sdata_dp);
-  if ( mdata_sp ) free(mdata_sp);
-  if ( sdata_sp ) free(sdata_sp);
-
-  return (0);
-}
-#endif
-
-#if  defined  (HAVE_LIBNETCDF)
-void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
-{
-  int fileID;
-  int gridID;
-  int zaxisID;
-  int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-  int ncvarid;
-  int ntsteps;
-  size_t xsize = 0, ysize = 0;
-  size_t size;
-  size_t start[5];
-  size_t count[5];
-  long nvals;
-  int swapxy = FALSE;
-  int ndims = 0;
-  int idim;
-  int tsteptype;
-  int gridindex, zaxisindex;
-  int dtype;
-  int vlistID;
-
-  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  ntsteps = streamptr->ntsteps;
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
-
-  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
-  ncvarid = cdfDefVar(streamptr, varID);
-
-  gridID    = vlistInqVarGrid(vlistID, varID);
-  zaxisID   = vlistInqVarZaxis(vlistID, varID);
-  tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
-  gridindex = vlistGridIndex(vlistID, gridID);
-  if ( gridInqType(gridID) == GRID_TRAJECTORY )
-    {
-      cdfWriteGridTraj(streamptr, gridID);
-    }
-  else
-    {
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
-    }
-
-  zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-  zid = streamptr->zaxisID[zaxisindex];
-
-  if ( tsteptype != TSTEP_CONSTANT )
-    {
-      start[ndims] = ntsteps - 1;
-      count[ndims] = 1;
-      ndims++;
-    }
-  if ( zid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = zaxisInqSize(zaxisID);
+      count[ndims] = (size_t)zaxisInqSize(zaxisID);
       ndims++;
     }
   if ( yid != UNDEFID )
@@ -42352,7 +41646,6 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int ntsteps;
   size_t xsize = 0, ysize = 0;
   size_t start[5];
   size_t count[5];
@@ -42372,9 +41665,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
   vlistID = streamInqVlist(streamID);
   fileID  = streamInqFileID(streamID);
 
-  ntsteps = streamptr->ntsteps;
+  long ntsteps = streamptr->ntsteps;
   if ( CDI_Debug )
-    Message("ntsteps = %d", ntsteps);
+    Message("ntsteps = %ld", ntsteps);
 
   if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
@@ -42400,34 +41693,37 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = ntsteps - 1;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
   if ( zid != UNDEFID )
     {
       int size = zaxisInqSize(zaxisID);
-      xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1] && rect[2][1] <= size);
-      start[ndims] = rect[2][0];
-      count[ndims] = rect[2][1] - rect[2][0] + 1;
+      xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
+              && rect[2][1] <= size);
+      start[ndims] = (size_t)rect[2][0];
+      count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
       ndims++;
     }
   if ( yid != UNDEFID )
     {
       size_t size;
       cdf_inq_dimlen(fileID, yid, &size);
-      xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1] && rect[1][1] <= (int)size);
-      start[ndims] = rect[1][0];
-      count[ndims] = rect[1][1] - rect[1][0] + 1;
+      xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
+              && rect[1][1] <= (int)size);
+      start[ndims] = (size_t)rect[1][0];
+      count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
       ndims++;
     }
   if ( xid != UNDEFID )
     {
       size_t size;
       cdf_inq_dimlen(fileID, xid, &size);
-      xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1] && rect[0][1] <= (int)size);
-      start[ndims] = rect[0][0];
-      count[ndims] = rect[0][1] - rect[0][0] + 1;
+      xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
+              && rect[0][1] <= (int)size);
+      start[ndims] = (size_t)rect[0][0];
+      count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
       ndims++;
     }
 
@@ -42452,8 +41748,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 }
 #endif
 
+#if  defined  (HAVE_LIBNETCDF)
 static
-int set_validrange(long gridsize, double *data, double missval, double validmin, double validmax)
+int set_validrangeDP(long gridsize, double *data, double missval, double validmin, double validmax)
 {
   long i;
   int nmiss = 0;
@@ -42501,184 +41798,350 @@ int set_validrange(long gridsize, double *data, double missval, double validmin,
   return (nmiss);
 }
 
-
-int cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
+static
+int set_validrangeSP(long gridsize, float *data, double missval, double validmin, double validmax)
 {
-#if  defined  (HAVE_LIBNETCDF)
-  int fileID;
-  int gridID;
-  int zaxisID;
-  int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-  int ncvarid;
-  int tsID;
-  int gridsize, xsize, ysize;
-  size_t size;
-  size_t start[5];
-  size_t count[5];
-  int ndims = 0;
-  int nvdims;
-  int idim;
-  int tsteptype;
-  int gridindex;
-  int zaxisindex;
-  int vlistID;
-  int i, j;
-  int dimorder[3];
-  int ixyz;
-  int swapxy = FALSE;
-  int lvalidrange;
-  double validrange[2];
-  double missval;
-  int laddoffset, lscalefactor;
-  double addoffset, scalefactor;
-
-  if ( CDI_Debug )
-    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  tsID = streamptr->curTsID;
-  if ( CDI_Debug ) Message("tsID = %d", tsID);
-
-  ncvarid = streamptr->vars[varID].ncvarid;
-  cdf_inq_varndims(fileID, ncvarid, &nvdims);
-
-  gridID    = vlistInqVarGrid(vlistID, varID);
-  zaxisID   = vlistInqVarZaxis(vlistID, varID);
-  tsteptype = vlistInqVarTsteptype(vlistID, varID);
-  ixyz      = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
-
-  gridsize = gridInqSize(gridID);
-  xsize = gridInqXsize(gridID);
-  ysize = gridInqYsize(gridID);
-
-  streamptr->numvals += gridsize;
+  long i;
+  int nmiss = 0;
+  /*
+  for ( i = 0; i < gridsize; i++, data++ )
+    {
+      if ( IS_NOT_EQUAL(validmin, VALIDMISS) && (*data) < validmin ) *data = missval;
+      if ( IS_NOT_EQUAL(validmax, VALIDMISS) && (*data) > validmax ) *data = missval;
+      if ( DBL_IS_EQUAL((*data), missval) ) nmiss++;
+    }
+  */
+  // 21/01/2014 Florian Prill: SX-9 vectorization
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  if ( gridInqType(gridID) == GRID_TRAJECTORY )
+  if ( IS_NOT_EQUAL(validmin, VALIDMISS) && !IS_NOT_EQUAL(validmax, VALIDMISS) )
     {
-      cdfReadGridTraj(streamptr, gridID);
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if ( (*data) < validmin )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
     }
-  else if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
+  else if ( IS_NOT_EQUAL(validmax, VALIDMISS) && !IS_NOT_EQUAL(validmin, VALIDMISS))
     {
-      xid = streamptr->xdimID[gridindex];
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if ( (*data) > validmax )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
+    }
+  else if ( IS_NOT_EQUAL(validmin, VALIDMISS) && IS_NOT_EQUAL(validmax, VALIDMISS))
+    {
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if      ( (*data) < validmin )  { (*data) = missval; nmiss++; }
+          else if ( (*data) > validmax )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
     }
   else
     {
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      for ( i = 0; i < gridsize; i++, data++ )
+        if ( DBL_IS_EQUAL((*data), missval) ) nmiss++;
     }
 
-  zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-  zid = streamptr->zaxisID[zaxisindex];
+  return (nmiss);
+}
+#endif
+
+#if  defined  (HAVE_LIBNETCDF)
+static
+size_t min_size(size_t a, size_t b)
+{
+  return a < b ? a : b;
+}
 
-  int skipdim = 0;
-  if ( xid == -1 && yid == -1 && nvdims == 3 )
+static
+void transpose2dArrayDP(size_t inWidth, size_t inHeight, double* data)
+{
+  const size_t cacheBlockSize = 32;    // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+                                       // which should be a decent compromise on many architectures.
+  double (*temp)[inWidth] = malloc(inHeight*sizeof(*temp));
+  double (*out)[inHeight] = (double (*)[inHeight])data;
+  memcpy(temp, data, inHeight*sizeof(*temp));
+  for ( size_t yBlock = 0; yBlock < inHeight; yBlock++ )
     {
-      int dimids[3];
-      cdf_inq_vardimid(fileID, ncvarid, dimids);
-      size = 0;
-      if ( zid == dimids[2] )
+      for ( size_t xBlock = 0; xBlock < inWidth; xBlock++ )
         {
-          cdf_inq_dimlen(fileID, dimids[1], &size);
-          if ( size == 1 ) skipdim = 1;
+          for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+            {
+              for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+                {
+                  out[x][y] = temp[y][x];
+                }
+            }
         }
-      else if ( zid == dimids[1] )
+    }
+  free(temp);
+}
+
+static
+void transpose2dArraySP(size_t inWidth, size_t inHeight, float* data)
+{
+  const size_t cacheBlockSize = 32;    // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+                                       // which should be a decent compromise on many architectures.
+  float (*temp)[inWidth] = malloc(inHeight*sizeof(*temp));
+  float (*out)[inHeight] = (float (*)[inHeight])data;
+  memcpy(temp, data, inHeight*sizeof(*temp));
+  for ( size_t yBlock = 0; yBlock < inHeight; yBlock++ )
+    {
+      for ( size_t xBlock = 0; xBlock < inWidth; xBlock++ )
         {
-          cdf_inq_dimlen(fileID, dimids[2], &size);
-          if ( size == 1 ) skipdim = 2;
+          for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+            {
+              for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+                {
+                  out[x][y] = temp[y][x];
+                }
+            }
         }
     }
-  /*
-  printf("2 %p %d %d %s\n", streamptr, zaxisindex, streamptr->zaxisID[zaxisindex], vlistInqVarNamePtr(vlistID, varID));
-  */
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
+  free(temp);
+}
 
-  if ( (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID ) swapxy = TRUE;
-  /*
-  printf("swapxy %d\n", swapxy);
-  printf("ixyz %d\n", ixyz);
-  printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
-  */
+static
+void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
+{
+  int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
+  int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
 
-  if ( tsteptype != TSTEP_CONSTANT )
+  (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
+  switch ( gridInqType(gridId) )
     {
-      start[ndims] = tsID;
-      count[ndims] = 1;
-      ndims++;
+      case GRID_TRAJECTORY:
+        cdfReadGridTraj(streamptr, gridId);
+        break;
+
+      case GRID_UNSTRUCTURED:
+        (*outDimIds)[0] = streamptr->xdimID[gridindex];
+        break;
+
+      default:
+        (*outDimIds)[0] = streamptr->xdimID[gridindex];
+        (*outDimIds)[1] = streamptr->ydimID[gridindex];
+        break;
     }
 
-  if ( skipdim == 1 )
+  int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
+  int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
+  (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
+}
+
+static
+int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
+{
+  if((*dimIds)[0] != UNDEFID) return 0;
+  if((*dimIds)[1] != UNDEFID) return 0;
+  int nvdims;
+  cdf_inq_varndims(fileId, ncvarid, &nvdims);
+  if(nvdims != 3) return 0;
+
+  int varDimIds[3];
+  cdf_inq_vardimid(fileId, ncvarid, varDimIds);
+  size_t size = 0;
+  if ( (*dimIds)[2] == varDimIds[2] )
     {
-      start[ndims] = 0;
-      count[ndims] = 1;
-      ndims++;
+      cdf_inq_dimlen(fileId, varDimIds[1], &size);
+      if ( size == 1 ) return 1;
+    }
+  else if ( (*dimIds)[2] == varDimIds[1] )
+    {
+      cdf_inq_dimlen(fileId, varDimIds[2], &size);
+      if ( size == 1 ) return 2;
     }
+  return 0;
+}
+
+
+static
+void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
+{
+  int tsID = streamptr->curTsID;
+  if ( CDI_Debug ) Message("tsID = %d", tsID);
+
+  int fileId = streamptr->fileID;
+  int vlistId = streamptr->vlistID;
+  int ncvarid = streamptr->vars[varId].ncvarid;
+
+  int gridId = vlistInqVarGrid(vlistId, varId);
+  int tsteptype = vlistInqVarTsteptype(vlistId, varId);
+  int gridsize = gridInqSize(gridId);
+
+  streamptr->numvals += gridsize;
+
+  int dimIds[3];    //this array joins the old variables xid, yid, and zid
+  cdfInqDimIds(streamptr, varId, &dimIds);
+
+  int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
+
+  int dimorder[3];
+  vlistInqVarDimorder(vlistId, varId, &dimorder);
+
+  *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
+
+  int ndims = 0;
+
+#define addDimension(startIndex, extent) do {   \
+      (*start)[ndims] = startIndex; \
+      (*count)[ndims] = extent; \
+      ndims++; \
+  } while(0)
+
+  if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+  if ( skipdim == 1 ) addDimension(0, 1);
 
   for ( int id = 0; id < 3; ++id )
     {
-      if ( dimorder[id] == 3 && zid != UNDEFID )
-        {
-          start[ndims] = levelID;
-          count[ndims] = 1;
-          ndims++;
-        }
-      else if ( dimorder[id] == 2 && yid != UNDEFID )
-        {
-          start[ndims] = 0;
-          cdf_inq_dimlen(fileID, yid, &size);
-          count[ndims] = size;
-          ndims++;
-        }
-      else if ( dimorder[id] == 1 && xid != UNDEFID )
+      size_t size;
+      int curDimId = dimIds[dimorder[id]-1];
+      if ( curDimId == UNDEFID ) continue;
+      switch ( dimorder[id] )
         {
-          start[ndims] = 0;
-          cdf_inq_dimlen(fileID, xid, &size);
-          count[ndims] = size;
-          ndims++;
+          Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+          case 1:
+          case 2:
+            cdf_inq_dimlen(fileId, curDimId, &size);
+            addDimension(0, size);
+            break;
+
+          case 3:
+            addDimension((size_t)levelId, 1);
+            break;
+
+          default:
+            Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
         }
     }
 
-  if ( skipdim == 2 )
-    {
-      start[ndims] = 0;
-      count[ndims] = 1;
-      ndims++;
-    }
+  if ( skipdim == 2 ) addDimension(0, 1);
+
+  assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+  assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+
+#undef addDimension
 
   if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
+    for (int idim = 0; idim < ndims; idim++)
       Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
 
+  int nvdims;
+  cdf_inq_varndims(fileId, ncvarid, &nvdims);
+
   if ( nvdims != ndims )
-    Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistID, varID));
+    Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
+}
+#endif
 
-  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+  size_t start[4];
+  size_t count[4];
+  cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+  cdf_get_vara_double(fileID, ncvarid, start, count, data);
+
+  size_t size = (size_t)gridInqSize(gridID)*zaxisInqSize(zaxisID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      float *data_fp = (float *) data;
-      cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
-      for ( i = gridsize-1; i >=0; i-- )
-        data[i] = (double) data_fp[i];
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeDP(size, data, missval, validrange[0], validrange[1]);
+      else
+        *nmiss = cdfDoInputDataTransformationDP(size, data, haveMissval, missval, 1, 0);
     }
-  else
-    cdf_get_vara_double(fileID, ncvarid, start, count, data);
 
-  if ( swapxy )
+  double addoffset   = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationDP(size, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
+
+
+void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+  size_t start[4];
+  size_t count[4];
+  cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+  cdf_get_vara_float(fileID, ncvarid, start, count, data);
+
+  size_t size = (size_t)gridInqSize(gridID)*zaxisInqSize(zaxisID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      double *tdata;
-      tdata = (double *) malloc(gridsize*sizeof(double));
-      memcpy(tdata, data, gridsize*sizeof(double));
-      for ( j = 0; j < ysize; ++j )
-        for ( i = 0; i < xsize; ++i )
-          data[j*xsize+i] = tdata[i*ysize+j];
-      free(tdata);
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeSP(size, data, missval, validrange[0], validrange[1]);
+      else
+        *nmiss = cdfDoInputDataTransformationSP(size, data, haveMissval, missval, 1, 0);
     }
 
-  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+  double addoffset    = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor  = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationSP(size, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
+
+void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  int i;
+  size_t start[4];
+  size_t count[4];
+
+  if ( CDI_Debug )
+    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID = streamptr->fileID;
+
+  bool swapxy;
+  cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+  int gridId = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridId);
+  int xsize = gridInqXsize(gridId);
+  int ysize = gridInqYsize(gridId);
+
+  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+    {
+      float *data_fp = malloc(gridsize*sizeof(*data_fp));
+      cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
+      for ( i = 0; i < gridsize; i++ )
+        data[i] = (double) data_fp[i];
+      free(data_fp);
+    }
+  else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
     {
       nc_type xtype;
       cdf_inq_vartype(fileID, ncvarid, &xtype);
@@ -42688,62 +42151,99 @@ int cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data,
             if ( data[i] < 0 ) data[i] += 256;
         }
     }
+  else
+    {
+      cdf_get_vara_double(fileID, ncvarid, start, count, data);
+    }
+
+  if ( swapxy ) transpose2dArrayDP(xsize, ysize, data);
 
   *nmiss = 0;
-  if ( vlistInqVarMissvalUsed(vlistID, varID) == TRUE )
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      missval = vlistInqVarMissval(vlistID, varID);
-
-      lvalidrange = vlistInqVarValidrange(vlistID, varID, validrange);
-      // printf("readvarslice: validrange %d %g %g\n", lvalidrange, validrange[0], validrange[1]);
-      if ( lvalidrange )
-        {
-          *nmiss = set_validrange(gridsize, data, missval, validrange[0], validrange[1]);
-        }
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeDP(gridsize, data, missval, validrange[0], validrange[1]);
       else
-        {
-          double *data_ptr = data;
-          for ( i = 0; i < gridsize; i++, data_ptr++ )
-            if ( DBL_IS_EQUAL((*data_ptr), missval) ) (*nmiss)++;
-        }
+        *nmiss = cdfDoInputDataTransformationDP(gridsize, data, haveMissval, missval, 1, 0);
     }
 
-  addoffset    = vlistInqVarAddoffset(vlistID, varID);
-  scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-  laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-  lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+  double addoffset = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationDP(gridsize, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
 
-  if ( laddoffset || lscalefactor )
-    {
-      missval = vlistInqVarMissval(vlistID, varID);
 
-      if ( *nmiss > 0 )
+void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  int i;
+  size_t start[4];
+  size_t count[4];
+
+  if ( CDI_Debug )
+    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID = streamptr->fileID;
+
+  bool swapxy;
+  cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+  int gridId = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridId);
+  int xsize = gridInqXsize(gridId);
+  int ysize = gridInqYsize(gridId);
+
+  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
+    {
+      double *data_dp = malloc(gridsize*sizeof(*data_dp));
+      cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
+      for ( i = 0; i < gridsize; i++ )
+        data[i] = (float) data_dp[i];
+      free(data_dp);
+    }
+  else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+    {
+      nc_type xtype;
+      cdf_inq_vartype(fileID, ncvarid, &xtype);
+      if ( xtype == NC_BYTE )
         {
           for ( i = 0; i < gridsize; i++ )
-            {
-              if ( !DBL_IS_EQUAL(data[i], missval) )
-                {
-                  if ( lscalefactor ) data[i] *= scalefactor;
-                  if ( laddoffset )   data[i] += addoffset;
-                }
-            }
+            if ( data[i] < 0 ) data[i] += 256;
         }
+    }
+  else
+    {
+      cdf_get_vara_float(fileID, ncvarid, start, count, data);
+    }
+
+  if ( swapxy ) transpose2dArraySP(xsize, ysize, data);
+
+  *nmiss = 0;
+  double missval = vlistInqVarMissval(vlistID, varID);
+  bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
+    {
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeSP(gridsize, data, missval, validrange[0], validrange[1]);
       else
-        {
-          for ( i = 0; i < gridsize; i++ )
-            {
-              if ( lscalefactor ) data[i] *= scalefactor;
-              if ( laddoffset )   data[i] += addoffset;
-            }
-        }
+        *nmiss = cdfDoInputDataTransformationSP(gridsize, data, haveMissval, missval, 1, 0);
     }
 
+  double addoffset = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void ) cdfDoInputDataTransformationSP(gridsize, data, haveMissval, missval, scalefactor, addoffset);
 #endif
-  return (0);
 }
 
 
-int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
 #if  defined  (HAVE_LIBNETCDF)
   int fileID;
@@ -42751,7 +42251,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int ntsteps;
   long nvals;
   size_t xsize = 0, ysize = 0;
   size_t start[5];
@@ -42761,7 +42260,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int tsteptype;
   int gridindex, zaxisindex;
   int dimorder[3];
-  int ixyz;
   int swapxy = FALSE;
   int dtype;
   int vlistID;
@@ -42772,8 +42270,8 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   vlistID = streamptr->vlistID;
   fileID  = streamptr->fileID;
 
-  ntsteps = streamptr->ntsteps;
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+  long ntsteps = streamptr->ntsteps;
+  if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
 
   if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
@@ -42782,8 +42280,8 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   gridID    = vlistInqVarGrid(vlistID, varID);
   zaxisID   = vlistInqVarZaxis(vlistID, varID);
   tsteptype = vlistInqVarTsteptype(vlistID, varID);
-  ixyz      = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
+  vlistInqVarDimorder(vlistID, varID, &dimorder);
+
 
   gridindex = vlistGridIndex(vlistID, gridID);
   if ( gridInqType(gridID) == GRID_TRAJECTORY )
@@ -42799,20 +42297,15 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
   zid = streamptr->zaxisID[zaxisindex];
 
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
-
   if ( (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID ) swapxy = TRUE;
   /*
   printf("swapxy %d\n", swapxy);
-  printf("ixyz %d\n", ixyz);
   printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
   */
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = ntsteps - 1;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
@@ -42821,7 +42314,7 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
     {
       if ( dimorder[id] == 3 && zid != UNDEFID )
         {
-          start[ndims] = levelID;
+          start[ndims] = (size_t)levelID;
           count[ndims] = 1;
           ndims++;
         }
@@ -42854,7 +42347,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
 
 #endif
-  return (0);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
@@ -42880,7 +42372,8 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nrecs;
 
-      if ( nrecs > 0 ) records = (record_t *) malloc(nrecs*sizeof(record_t));
+      if ( nrecs > 0 )
+        records = (record_t *)xmalloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -42888,7 +42381,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
       streamptr->tsteps[tsID].curRecID   = UNDEFID;
 
       nvrecs = nrecs; /* use all records at first timestep */
-      if ( nvrecs > 0 ) recIDs = (int *) malloc(nvrecs*sizeof(int));
+      if ( nvrecs > 0 ) recIDs = (int *)xmalloc((size_t)nvrecs * sizeof (int));
       streamptr->tsteps[tsID].recIDs     = recIDs;
       for ( recID = 0; recID < nvrecs; recID++ )
         recIDs[recID] = recID;
@@ -42901,8 +42394,8 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
           for ( levelID = 0; levelID < nlev; levelID++ )
             {
               recordInitEntry(&records[recID]);
-              records[recID].varID   = varID;
-              records[recID].levelID = levelID;
+              records[recID].varID   = (short)varID;
+              records[recID].levelID = (short)levelID;
               recID++;
             }
         }
@@ -42924,7 +42417,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nvrecs;
 
-      records = (record_t *) malloc(nrecs*sizeof(record_t));
+      records = (record_t *) malloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nvrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -42933,11 +42426,11 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       memcpy(streamptr->tsteps[tsID].records,
              streamptr->tsteps[0].records,
-             nrecs*sizeof(record_t));
+             (size_t)nrecs * sizeof (record_t));
 
       if ( nvrecs )
         {
-          recIDs = (int *) malloc(nvrecs*sizeof(int));
+          recIDs = (int *) malloc((size_t)nvrecs * sizeof (int));
           streamptr->tsteps[tsID].recIDs     = recIDs;
           vrecID = 0;
           for ( recID = 0; recID < nrecs; recID++ )
@@ -42959,7 +42452,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nvrecs;
 
-      records = (record_t *) malloc(nrecs*sizeof(record_t));
+      records = (record_t *)xmalloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nvrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -42968,14 +42461,14 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       memcpy(streamptr->tsteps[tsID].records,
              streamptr->tsteps[0].records,
-             nrecs*sizeof(record_t));
+             (size_t)nrecs * sizeof (record_t));
 
-      recIDs = (int *) malloc(nvrecs*sizeof(int));
+      recIDs = (int *) malloc((size_t)nvrecs * sizeof(int));
       streamptr->tsteps[tsID].recIDs     = recIDs;
 
       memcpy(streamptr->tsteps[tsID].recIDs,
              streamptr->tsteps[1].recIDs,
-             nvrecs*sizeof(int));
+             (size_t)nvrecs * sizeof (int));
     }
 }
 #endif
@@ -43249,14 +42742,14 @@ int unitsIsPressure(const char *units)
 }
 
 static
-int isGaussGrid(long ysize, double yinc, double *yvals)
+int isGaussGrid(size_t ysize, double yinc, double *yvals)
 {
   int lgauss = FALSE;
-  long i;
   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);
@@ -43325,7 +42818,7 @@ void printNCvars(ncvar_t *ncvars, int nvars, const char *oname)
   char axis[7];
   int ncvarid, i;
   int ndim;
-  int iaxis[] = {'t', 'z', 'y', 'x'};
+  static const char iaxis[] = {'t', 'z', 'y', 'x'};
 
   fprintf(stderr, "%s:\n", oname);
 
@@ -43434,7 +42927,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( storage_in == NC_CHUNKED )
                 {
                   ncvars[ncvarid].chunked = 1;
-                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = chunks[i];
+                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
                   if ( CDI_Debug )
                     {
                       fprintf(stderr, "\nchunking %d %d %d\nchunks ", storage_in, NC_CONTIGUOUS, NC_CHUNKED);
@@ -43480,15 +42973,15 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
           cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
           cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
 
-          if ( strcmp(attname, "long_name") == 0 && atttype == NC_CHAR )
+          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 && atttype == NC_CHAR )
+          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 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
             }
@@ -43496,7 +42989,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             {
               ncvars[ncvarid].calendar = TRUE;
             }
-          else if ( strcmp(attname, "param") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
             {
 	      char paramstr[32];
 	      int pnum = 0, pcat = 255, pdis = 255;
@@ -43505,12 +42998,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "code") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
             {
               cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
               if ( tablenum > 0 )
@@ -43522,13 +43015,13 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 }
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "trunc_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               if ( memcmp(attstring, "Triangular", attlen) == 0 )
                 ncvars[ncvarid].gridtype = GRID_SPECTRAL;
             }
-          else if ( strcmp(attname, "grid_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -43571,7 +43064,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "level_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -43610,19 +43103,19 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "trunc_count") == 0 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
             {
               cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
             }
-          else if ( strcmp(attname, "truncation") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
 	      /*
@@ -43632,7 +43125,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      */
 	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "scale_factor") == 0 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
 	      /*
@@ -43642,7 +43135,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      */
 	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "climatology") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
             {
               int status, ncboundsid;
 
@@ -43660,7 +43153,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
             }
-          else if ( strcmp(attname, "bounds") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "bounds") == 0 && xtypeIsText(atttype) )
             {
               int status, ncboundsid;
 
@@ -43677,7 +43170,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
             }
-          else if ( strcmp(attname, "cell_measures") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
             {
               char *pstring, *cell_measures = NULL, *cell_var = NULL;
 
@@ -43742,7 +43235,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
           */
-          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && atttype == NC_CHAR )
+          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
             {
               int status;
               char *pstring, *varname = NULL;
@@ -43780,7 +43273,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( (strcmp(attname, "auxiliary_variable") == 0) && atttype == NC_CHAR )
+          else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
             {
               int status;
               char *pstring, *varname = NULL;
@@ -43818,7 +43311,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "grid_mapping") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
             {
               int status;
               int nc_gmap_id;
@@ -43836,7 +43329,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "positive") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -43851,13 +43344,13 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                   ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
                 }
             }
-          else if ( strcmp(attname, "_FillValue") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
 	      ncvars[ncvarid].defmissval = TRUE;
@@ -43920,7 +43413,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                     }
                 }
             }
-          else if ( strcmp(attname, "_Unsigned") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -43936,7 +43429,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 }
 	      /* cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "cdi") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
             {
 	      cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 	      strtolower(attstring);
@@ -43947,7 +43440,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 		  cdfSetVar(ncvars, ncvarid, FALSE);
 		}
             }
-          else if ( strcmp(attname, "axis") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 	      attlen = strlen(attstring);
@@ -43977,12 +43470,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  if ( (int) attstring[attlen] == 't' )
 			    {
 			      if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
-			      cdfSetDim(ncvars, ncvarid, attlen, T_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS);
 			    }
 			  else if ( (int) attstring[attlen] == 'z' )
 			    {
 			      ncvars[ncvarid].zdim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, Z_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -43993,7 +43486,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  else if ( (int) attstring[attlen] == 'y' )
 			    {
 			      ncvars[ncvarid].ydim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, Y_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -44004,7 +43497,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  else if ( (int) attstring[attlen] == 'x' )
 			    {
 			      ncvars[ncvarid].xdim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, X_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -44039,7 +43532,8 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	  else
 	    {
 	      if ( ncvars[ncvarid].natts == 0 )
-		ncvars[ncvarid].atts = (int *) malloc(nvatts*sizeof(int));
+		ncvars[ncvarid].atts
+                  = (int *)xmalloc((size_t)nvatts * sizeof (int));
 
 	      ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
 	      /*
@@ -44498,7 +43992,27 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		    }
 		}
 
-	      if ( xvarid != 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 )
 		{
                   skipvar = TRUE;
 		  islon = ncvars[xvarid].islon;
@@ -44695,10 +44209,10 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	    case GRID_UNSTRUCTURED:
 	    case GRID_CURVILINEAR:
 	      {
-		grid.size  = size;
-		grid.xsize = xsize;
-		grid.ysize = ysize;
-                grid.np    = np;
+		grid.size  = (int)size;
+		grid.xsize = (int)xsize;
+		grid.ysize = (int)ysize;
+                grid.np    = (int)np;
 		if ( xvarid != UNDEFID )
 		  {
 		    grid.xdef  = 1;
@@ -44744,13 +44258,13 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	      }
 	    case GRID_SPECTRAL:
 	      {
-		grid.size = size;
+		grid.size = (int)size;
 		grid.lcomplex = 1;
 		break;
 	      }
 	    case GRID_FOURIER:
 	      {
-		grid.size = size;
+		grid.size = (int)size;
 		break;
 	      }
 	    case GRID_TRAJECTORY:
@@ -44765,8 +44279,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	  if ( grid.size == 0 )
 	    {
 	      if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
-		   (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS &&
-		    ncvars[ncvarid].dimtype[1] == Z_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;
@@ -45052,7 +44566,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 /* 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, double *vct)
+		      size_t vctsize, double *vct, char *uuidOfVGrid)
 {
   int ncvarid, ncvarid2;
   int i, ilev, ndims;
@@ -45087,12 +44601,12 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	  if ( zdimid != UNDEFID )
 	    {
 	      zvarid = ncdims[zdimid].ncvarid;
-	      zsize  = ncdims[zdimid].len;
+	      zsize  = (int)ncdims[zdimid].len;
 	    }
 
 	  if ( CDI_Debug ) Message("nlevs = %d", zsize);
 
-	  zvar = (double *) malloc(zsize*sizeof(double));
+	  zvar = (double *)xmalloc((size_t)zsize * sizeof (double));
 
 	  zaxisType = UNDEFID;
 
@@ -45122,15 +44636,15 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		  nbdims = ncvars[ncvars[zvarid].bounds].ndims;
 		  if ( nbdims == 2 )
 		    {
-		      nlevel  = ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
-		      nvertex = ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
+		      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 )
 			{
 			  double *zbounds;
 			  with_bounds = TRUE;
-			  zbounds = (double *) malloc(2*nlevel*sizeof(double));
-			  lbounds = (double *) malloc(nlevel*sizeof(double));
-			  ubounds = (double *) malloc(nlevel*sizeof(double));
+			  zbounds = (double *) malloc(2*(size_t)nlevel*sizeof(double));
+			  lbounds = (double *) malloc((size_t)nlevel*sizeof(double));
+			  ubounds = (double *) malloc((size_t)nlevel*sizeof(double));
 			  cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
 			  for ( i = 0; i < nlevel; ++i )
 			    {
@@ -45165,12 +44679,18 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		}
 	      else
 		{
-		  for ( ilev = 0; ilev < (int)zsize; ilev++ ) zvar[ilev] = ilev + 1;
+		  for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
 		}
 	    }
 
       	  ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds,
-						vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+						(int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+
+	  if ( uuidOfVGrid[0] != 0 )
+            {
+              // printf("uuidOfVGrid: defined\n");
+              zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid);
+            }
 
           if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
 
@@ -45219,8 +44739,8 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
     {
       int index;
       varinfo_t **varInfo;
-      varInfo    = (varinfo_t **) malloc(nvars*sizeof(varinfo_t *));
-      varInfo[0] = (varinfo_t *)  malloc(nvars*sizeof(varinfo_t));
+      varInfo    = (varinfo_t **)xmalloc((size_t)nvars * sizeof (varinfo_t *));
+      varInfo[0] = (varinfo_t *)xmalloc((size_t)nvars * sizeof (varinfo_t));
 
       for ( index = 1; index < nvars; index++ )
 	varInfo[index] = varInfo[0] + index;
@@ -45231,7 +44751,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 	  varInfo[varID]->ncvarid = ncvarid;
 	  strcpy(varInfo[varID]->name, ncvars[ncvarid].name);
 	}
-      qsort(varInfo[0], nvars, sizeof(varinfo_t), cmpvarname);
+      qsort(varInfo[0], (size_t)nvars, sizeof(varinfo_t), cmpvarname);
       for ( varID = 0; varID < nvars; varID++ )
 	{
 	  varids[varID] = varInfo[varID]->ncvarid;
@@ -45358,7 +44878,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
           ncvars[ncvarid].ensdata = NULL;
         }
 
-      if ( ncvars[ncvarid].extra != NULL && ncvars[ncvarid].extra[0] != 0 )
+      if ( ncvars[ncvarid].extra[0] != 0 )
         {
           vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
         }
@@ -45386,11 +44906,12 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 	      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;
 		  attint = (int *) malloc(attlen*sizeof(int));
-		  cdfGetAttInt(ncid, ncvarid, attname, attlen, attint);
+		  cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
 		  if ( attrtype == NC_SHORT )
 		    vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint);
 		  else
@@ -45403,7 +44924,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 		{
 		  double *attflt;
 		  attflt = (double *) malloc(attlen*sizeof(double));
-		  cdfGetAttDouble(ncid, ncvarid, attname, attlen, attflt);
+		  cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
 		  if ( attrtype == NC_FLOAT )
 		    vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt);
 		  else
@@ -45412,7 +44933,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 		    printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attflt[0]);
 		  free(attflt);
 		}
-	      else if ( attrtype == NC_CHAR )
+	      else if ( xtypeIsText(attrtype) )
 		{
 		  cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 		  vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring);
@@ -45511,7 +45032,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 
 static
 void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts,
-                            int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid,
+                            int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid, char *uuidOfVGrid,
                             char *gridfile, int *number_of_grid_used, char *fcreftime)
 {
   nc_type xtype;
@@ -45526,7 +45047,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
       cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
       cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
 
-      if ( xtype == NC_CHAR )
+      if ( xtypeIsText(xtype) )
 	{
 	  cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen-1, attstring);
 
@@ -45582,6 +45103,11 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
                   str2uuid(attstring, uuidOfHGrid);
                   //   printf("uuid: %d %s\n", attlen, attstring);
 		}
+	      else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
+		{
+                  attstring[36] = 0;
+                  str2uuid(attstring, uuidOfVGrid);
+		}
 	      else
 		{
                   if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
@@ -45604,7 +45130,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
             {
               int *attint;
               attint = (int *) malloc(attlen*sizeof(int));
-              cdfGetAttInt(fileID, NC_GLOBAL, attname, attlen, attint);
+              cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
               if ( xtype == NC_SHORT )
                 vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint);
               else
@@ -45616,7 +45142,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
 	{
 	  double *attflt;
 	  attflt = (double *) malloc(attlen*sizeof(double));
-	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, attlen, attflt);
+	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
 	  if ( xtype == NC_FLOAT )
 	    vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt);
 	  else
@@ -45689,7 +45215,7 @@ void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid,
         if ( ncvarid != streamptr->basetime.ncvarid &&
              ncvars[ncvarid].ndims == 1 &&
              timedimid == ncvars[ncvarid].dimids[0] &&
-             ncvars[ncvarid].xtype != NC_CHAR &&
+             !xtypeIsText(ncvars[ncvarid].xtype) &&
              isTimeAxisUnits(ncvars[ncvarid].units) )
           {
             ncvars[ncvarid].isvar = FALSE;
@@ -45713,7 +45239,7 @@ void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid,
             if ( ncvarid != streamptr->basetime.ncvarid &&
                  ncvars[ncvarid].ndims == 2 &&
                  timedimid == ncvars[ncvarid].dimids[0] &&
-                 ncvars[ncvarid].xtype == NC_CHAR &&
+                 !xtypeIsText(ncvars[ncvarid].xtype) &&
                  ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
               {
                 streamptr->basetime.ncvarid = ncvarid;
@@ -45787,11 +45313,13 @@ int cdfInqContents(stream_t *streamptr)
   int format = 0;
   int ucla_les = FALSE;
   char uuidOfHGrid[17];
+  char uuidOfVGrid[17];
   char gridfile[8912];
   char fcreftime[CDI_MAX_NAME];
   int number_of_grid_used = UNDEFID;
 
   uuidOfHGrid[0] = 0;
+  uuidOfVGrid[0] = 0;
   gridfile[0]    = 0;
   fcreftime[0]   = 0;
 
@@ -45816,13 +45344,13 @@ int cdfInqContents(stream_t *streamptr)
     }
 
   /* alloc ncdims */
-  ncdims = (ncdim_t *) malloc(ndims*sizeof(ncdim_t));
+  ncdims = (ncdim_t *)xmalloc((size_t)ndims * sizeof (ncdim_t));
   init_ncdims(ndims, ncdims);
 
   if ( nvars > 0 )
     {
       /* alloc ncvars */
-      ncvars = (ncvar_t *) malloc(nvars*sizeof(ncvar_t));
+      ncvars = (ncvar_t *)xmalloc((size_t)nvars * sizeof (ncvar_t));
       init_ncvars(nvars, ncvars);
 
       for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
@@ -45863,7 +45391,8 @@ int cdfInqContents(stream_t *streamptr)
     }
 
   /* scan global attributes */
-  scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, uuidOfHGrid, gridfile, &number_of_grid_used, fcreftime);
+  scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, 
+                         uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used, fcreftime);
 
   /* find time dim */
   if ( unlimdimid >= 0 )
@@ -45970,7 +45499,7 @@ int cdfInqContents(stream_t *streamptr)
 	  continue;
 	}
 
-      if ( ncvars[ncvarid].xtype == NC_CHAR )
+      if ( xtypeIsText(ncvars[ncvarid].xtype) )
 	{
 	  ncvars[ncvarid].isvar = 0;
 	  continue;
@@ -46110,13 +45639,13 @@ int cdfInqContents(stream_t *streamptr)
 
 
   /* define all zaxes */
-  define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct);
+  define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
 
 
   if ( vct ) free(vct);
 
   /* select vars */
-  varids = (int *) malloc(nvars*sizeof(int));
+  varids = (int *)xmalloc((size_t)nvars * sizeof (int));
   nvarids = 0;
   for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
     if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
@@ -46137,7 +45666,7 @@ int cdfInqContents(stream_t *streamptr)
   if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
     ntsteps = 1;
 
-  streamptr->ntsteps = ntsteps;
+  streamptr->ntsteps = (long)ntsteps;
 
   /* define all data variables */
   define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
@@ -46181,10 +45710,9 @@ int cdfInqContents(stream_t *streamptr)
   if ( ncvarid != UNDEFID )
     {
       taxis_t *taxis = &streamptr->tsteps[0].taxis;
-
-      taxis->name = strdup(ncvars[ncvarid].name);
+      ptaxisDefName(taxis, ncvars[ncvarid].name);
       if ( ncvars[ncvarid].longname[0] )
-        taxis->longname = strdup(ncvars[ncvarid].longname);
+        ptaxisDefLongname(taxis, ncvars[ncvarid].longname);
     }
 
   if ( ncvarid != UNDEFID )
@@ -46263,6 +45791,63 @@ int cdfInqContents(stream_t *streamptr)
   return (0);
 }
 
+#if  defined  (HAVE_LIBNETCDF)
+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;
+}
+#endif
 
 int cdfInqTimestep(stream_t * streamptr, int tsID)
 {
@@ -46270,7 +45855,6 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
 #if  defined  (HAVE_LIBNETCDF)
   double timevalue;
   int fileID;
-  size_t index;
   taxis_t *taxis;
 
   if ( CDI_Debug ) Message("streamID = %d  tsID = %d", streamptr->self, tsID);
@@ -46291,31 +45875,23 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
       if ( nctimevarid != UNDEFID )
 	{
 	  fileID = streamptr->fileID;
-	  index  = tsID;
+	  size_t index  = (size_t)tsID;
 
 	  if ( streamptr->basetime.lwrf )
 	    {
-	      size_t start[2], count[2];
-	      char stvalue[32];
-	      start[0] = index; 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;
-	      }
+              wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
 	    }
 	  else
 	    {
-	      cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
-              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-
+#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);
 	    }
 
@@ -46323,13 +45899,13 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
 	  if ( nctimeboundsid != UNDEFID )
 	    {
 	      size_t start[2], count[2];
-	      start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
+              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;
+              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;
 
@@ -46339,7 +45915,7 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
           int leadtimeid = streamptr->basetime.leadtimeid;
           if ( leadtimeid != UNDEFID )
             {
-	      cdf_get_var1_double(fileID, leadtimeid, &index, &timevalue);
+              timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
               cdiSetForecastPeriod(timevalue, taxis);
             }
 	}
@@ -46748,25 +46324,22 @@ int stream_new_var(stream_t *streamptr, int gridID, int zaxisID)
 
 void recordInitEntry(record_t *record)
 {
-  (*record).position = CDI_UNDEFID;
-  (*record).size     = 0;
-  (*record).param    = 0;
-  (*record).ilevel   = CDI_UNDEFID;
-  (*record).used     = FALSE;
-  (*record).varID    = CDI_UNDEFID;
-  (*record).levelID  = CDI_UNDEFID;
-  memset((*record).varname, 0, sizeof((*record).varname));
+  record->position = CDI_UNDEFID;
+  record->size     = 0;
+  record->param    = 0;
+  record->ilevel   = CDI_UNDEFID;
+  record->used     = FALSE;
+  record->varID    = CDI_UNDEFID;
+  record->levelID  = CDI_UNDEFID;
+  memset(record->varname, 0, sizeof(record->varname));
 }
 
 
 int recordNewEntry(stream_t *streamptr, int tsID)
 {
   int recordID = 0;
-  int recordSize;
-  record_t *records;
-
-  recordSize = streamptr->tsteps[tsID].recordSize;
-  records    = streamptr->tsteps[tsID].records;
+  int recordSize = streamptr->tsteps[tsID].recordSize;
+  record_t *records = streamptr->tsteps[tsID].records;
   /*
     Look for a free slot in record.
     (Create the table the first time through).
@@ -46775,7 +46348,7 @@ int recordNewEntry(stream_t *streamptr, int tsID)
     {
       int i;
       recordSize = 1;   /*  <<<<----  */
-      records = (record_t *) malloc(recordSize*sizeof(record_t));
+      records = (record_t *)xmalloc((size_t)recordSize * sizeof (record_t));
       if ( records == NULL )
 	{
           Message("recordSize = %d", recordSize);
@@ -46801,7 +46374,8 @@ int recordNewEntry(stream_t *streamptr, int tsID)
       int i;
 
       recordSize = 2*recordSize;
-      records    = (record_t *) realloc(records, recordSize*sizeof(record_t));
+      records    = (record_t *)xrealloc(records,
+                                        (size_t)recordSize * sizeof (record_t));
       if ( records == NULL )
 	{
           Message("recordSize = %d", recordSize);
@@ -46849,95 +46423,46 @@ void cdiInitRecord(stream_t *streamptr)
 
 void streamInqRecord(int streamID, int *varID, int *levelID)
 {
-  /* int rec = 0; */
-  int recID, tsID, rindex;
-  int lindex;
-  stream_t *streamptr;
-
   check_parg(varID);
   check_parg(levelID);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
   cdiDefAccesstype(streamID, TYPE_REC);
 
   if ( ! streamptr->record ) cdiInitRecord(streamptr);
 
-  tsID   = streamptr->curTsID;
-  rindex = streamptr->tsteps[tsID].curRecID + 1;
+  int tsID   = streamptr->curTsID;
+  int rindex = streamptr->tsteps[tsID].curRecID + 1;
 
   if ( rindex >= streamptr->tsteps[tsID].nrecs )
     Error("record %d not available at timestep %d", rindex+1, tsID+1);
 
-  recID  = streamptr->tsteps[tsID].recIDs[rindex];
+  int recID  = streamptr->tsteps[tsID].recIDs[rindex];
 
   if ( recID == -1 || recID >= streamptr->tsteps[tsID].nallrecs )
     Error("Internal problem! tsID = %d recID = %d", tsID, recID);
 
   *varID   = streamptr->tsteps[tsID].records[recID].varID;
-  lindex   = streamptr->tsteps[tsID].records[recID].levelID;
+  int lindex = streamptr->tsteps[tsID].records[recID].levelID;
 
   *levelID = streamptr->vars[*varID].lindex[lindex];
 
   if ( CDI_Debug )
-    Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n",
-	    tsID, recID, *varID, *levelID);
+    Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n", tsID, recID, *varID, *levelID);
 
   streamptr->curTsID = tsID;
   streamptr->tsteps[tsID].curRecID = rindex;
-
-  /*
-  rec = recID + 1;
-  filetype = streamptr->filetype;
-
-  switch ( filetype )
-    {
-    case FILETYPE_GRB:
-      {
-        rec = grbInqRecord(streamID, varID, levelID);
-	break;
-      }
-    case FILETYPE_SRV:
-      {
-        rec = srvInqRecord(streamptr, varID, levelID);
-	break;
-      }
-#if  defined  (HAVE_LIBNETCDF)
-    case FILETYPE_NC:
-    case FILETYPE_NC2:
-    case FILETYPE_NC4:
-    case FILETYPE_NC4C:
-      {
-	rec = cdfInqRecord(streamID, varID, levelID);
-	break;
-      }
-#endif
-    default:
-      {
-	Error("%s support not compiled in!", strfiletype(filetype));
-	break;
-      }
-    }
-  */
 }
 
 
 void streamDefRecord(int streamID, int varID, int levelID)
 {
-  int status = 0;
-  int filetype;
-  int param, gridID, zaxisID, level;
-  int tsID;
-  int vlistID;
-  stream_t *streamptr;
-
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  tsID = streamptr->curTsID;
+  int tsID = streamptr->curTsID;
 
   if ( tsID == CDI_UNDEFID )
     {
@@ -46947,11 +46472,11 @@ void streamDefRecord(int streamID, int varID, int levelID)
 
   if ( ! streamptr->record ) cdiInitRecord(streamptr);
 
-  vlistID = streamptr->vlistID;
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  zaxisID = vlistInqVarZaxis(vlistID, varID);
-  param   = vlistInqVarParam(vlistID, varID);
-  level   = (int) zaxisInqLevel(zaxisID, levelID);
+  int vlistID = streamptr->vlistID;
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+  int param   = vlistInqVarParam(vlistID, varID);
+  int level   = (int) zaxisInqLevel(zaxisID, levelID);
 
   streamptr->record->varID    = varID;
   streamptr->record->levelID  = levelID;
@@ -46963,182 +46488,127 @@ void streamDefRecord(int streamID, int varID, int levelID)
   streamptr->record->zaxisID  = zaxisID;
   streamptr->record->prec     = vlistInqVarDatatype(vlistID, varID);
 
-  filetype = streamptr->filetype;
-
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-        status = grbDefRecord(streamptr);
-	break;
-      }
+      grbDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-        status = srvDefRecord(streamptr);
-	break;
-      }
+      srvDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-        status = extDefRecord(streamptr);
-	break;
-      }
+      extDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-        status = iegDefRecord(streamptr);
-	break;
-      }
+      iegDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-	if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
-	status = cdfDefRecord(streamptr);
-	break;
-      }
+      if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+      cdfDefRecord(streamptr);
+      break;
 #endif
     default:
-      {
-	Error("%s support not compiled in!", strfiletype(filetype));
-	break;
-      }
+      Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+      break;
     }
 }
 
 
 void streamReadRecord(int streamID, double *data, int *nmiss)
 {
-  int status = 0;
-  int filetype;
-  stream_t *streamptr;
-
   check_parg(data);
   check_parg(nmiss);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
-
   *nmiss = 0;
 
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-        status = grbReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      grbReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-        status = srvReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      srvReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-        status = extReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      extReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-        status = iegReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      iegReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        /* FIXME: return value not inspected */
-	status = cdfReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      cdfReadRecord(streamptr, data, nmiss);
+      break;
 #endif
     default:
       {
-	Error("%s support not compiled in!", strfiletype(filetype));
+	Error("%s support not compiled in!", strfiletype(streamptr->filetype));
 	break;
       }
     }
 }
 
-
-void stream_write_record(int streamID, int memtype, const void *data, int nmiss)
+static void
+stream_write_record(int streamID, int memtype, const void *data, int nmiss)
 {
-  int status = 0;
-  int filetype;
-  stream_t *streamptr;
-
   check_parg(data);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
-
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        status = grb_write_record(streamptr, memtype, data, nmiss);
-	break;
-      }
+      grb_write_record(streamptr, memtype, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
-        status = srvWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
+      srvWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
-        status = extWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
+      extWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
-        status = iegWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
+      iegWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
@@ -47152,7 +46622,7 @@ void stream_write_record(int streamID, int memtype, const void *data, int nmiss)
 #endif
     default:
       {
-	Error("%s support not compiled in!", strfiletype(filetype));
+	Error("%s support not compiled in!", strfiletype(streamptr->filetype));
 	break;
       }
     }
@@ -47172,19 +46642,15 @@ void streamWriteRecordF(int streamID, const float *data, int nmiss)
 
 void streamCopyRecord(int streamID2, int streamID1)
 {
-  int status = 0;
-  int filetype = CDI_UNDEFID, filetype1, filetype2;
-  stream_t *streamptr1;
-  stream_t *streamptr2;
-
-  streamptr1 = stream_to_pointer(streamID1);
-  streamptr2 = stream_to_pointer(streamID2);
+  stream_t *streamptr1 = stream_to_pointer(streamID1);
+  stream_t *streamptr2 = stream_to_pointer(streamID2);
 
   stream_check_ptr(__func__, streamptr1);
   stream_check_ptr(__func__, streamptr2);
 
-  filetype1 = streamptr1->filetype;
-  filetype2 = streamptr2->filetype;
+  int filetype1 = streamptr1->filetype;
+  int filetype2 = streamptr2->filetype;
+  int filetype  = FILETYPE_UNDEF;
 
   if ( filetype1 == filetype2 ) filetype = filetype2;
   else
@@ -47209,7 +46675,7 @@ void streamCopyRecord(int streamID2, int streamID1)
         }
     }
 
-  if ( filetype == CDI_UNDEFID )
+  if ( filetype == FILETYPE_UNDEF )
     Error("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
 
   switch (filetype)
@@ -47217,46 +46683,31 @@ void streamCopyRecord(int streamID2, int streamID1)
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-	status = grbCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      grbCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-	status = srvCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      srvCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-	status = extCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      extCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-	status = iegCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      iegCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        /* FIXME: return value not inspected */
-	status = cdfCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      cdfCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
     default:
       {
@@ -47269,24 +46720,22 @@ void streamCopyRecord(int streamID2, int streamID1)
 
 void cdi_create_records(stream_t *streamptr, int tsID)
 {
-  int nrecords, maxrecords;
-  int nvars, varID, recID;
+  unsigned nrecords, maxrecords;
   record_t *records;
-  int vlistID;
 
   if ( streamptr->tsteps[tsID].records ) return;
 
-  vlistID  = streamptr->vlistID;
+  int vlistID  = streamptr->vlistID;
 
   if ( tsID == 0 )
     {
       maxrecords = 0;
-      nvars = streamptr->nvars;
-      for ( varID = 0; varID < nvars; varID++)
-	maxrecords += streamptr->vars[varID].nlevs;
+      int nvars = streamptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++)
+	maxrecords += (unsigned)streamptr->vars[varID].nlevs;
     }
   else
-    maxrecords = streamptr->tsteps[0].recordSize;
+    maxrecords = (unsigned)streamptr->tsteps[0].recordSize;
 
   if ( tsID == 0 )
     {
@@ -47295,42 +46744,41 @@ void cdi_create_records(stream_t *streamptr, int tsID)
   else if ( tsID == 1 )
     {
       nrecords = 0;
-      maxrecords = streamptr->tsteps[0].recordSize;
-      for ( recID = 0; recID < maxrecords; recID++ )
+      maxrecords = (unsigned)streamptr->tsteps[0].recordSize;
+      for (unsigned recID = 0; recID < maxrecords; recID++ )
 	{
-	  varID = streamptr->tsteps[0].records[recID].varID;
-	  if ( varID != -1 ) /* varID = -1 for write mode !!! */
-	    if ( vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT )
-	      continue;
-	  nrecords++;
+	  int varID = streamptr->tsteps[0].records[recID].varID;
+	  nrecords +=
+            (varID == -1 /* varID = -1 for write mode !!! */
+             || vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT);
 	}
     }
   else
-    nrecords = streamptr->tsteps[1].nallrecs;
+    nrecords = (unsigned)streamptr->tsteps[1].nallrecs;
 
   if ( maxrecords > 0 )
-    records = (record_t *) malloc(maxrecords*sizeof(record_t));
+    records = (record_t *) malloc(maxrecords * sizeof(record_t));
   else
     records = NULL;
 
   streamptr->tsteps[tsID].records    = records;
-  streamptr->tsteps[tsID].recordSize = maxrecords;
-  streamptr->tsteps[tsID].nallrecs   = nrecords;
+  streamptr->tsteps[tsID].recordSize = (int)maxrecords;
+  streamptr->tsteps[tsID].nallrecs   = (int)nrecords;
 
   if ( tsID == 0 )
     {
-      for ( recID = 0; recID < maxrecords; recID++ )
+      for ( unsigned recID = 0; recID < maxrecords; recID++ )
 	recordInitEntry(&streamptr->tsteps[tsID].records[recID]);
     }
   else
     {
       memcpy(streamptr->tsteps[tsID].records,
 	     streamptr->tsteps[0].records,
-	     maxrecords*sizeof(record_t));
+	     (size_t)maxrecords * sizeof(record_t));
 
-      for ( recID = 0; recID < maxrecords; recID++ )
+      for ( unsigned recID = 0; recID < maxrecords; recID++ )
 	{
-	  varID = streamptr->tsteps[0].records[recID].varID;
+	  int varID = streamptr->tsteps[0].records[recID].varID;
 	  if ( varID != -1 ) /* varID = -1 for write mode !!! */
 	    if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
 	      {
@@ -47389,7 +46837,8 @@ int tstepsNewEntry(stream_t *streamptr)
     {
       if ( tstepsTableSize == 0 ) tstepsTableSize = 1;
       tstepsTableSize = 2*tstepsTableSize;
-      tstepsTable = (tsteps_t *) realloc(tstepsTable, tstepsTableSize*sizeof(tsteps_t));
+      tstepsTable = (tsteps_t *)xrealloc(tstepsTable,
+                                         (size_t)tstepsTableSize * sizeof (tsteps_t));
       if ( tstepsTable == NULL )
 	{
           Message("tstepsTableSize = %d", tstepsTableSize);
@@ -47410,8 +46859,8 @@ int tstepsNewEntry(stream_t *streamptr)
 
 void cdiCreateTimesteps(stream_t *streamptr)
 {
-  int ntsteps;
-  int tsID;
+  long ntsteps;
+  long tsID;
 
   if ( streamptr->ntsteps < 0 || streamptr->tstepsTableSize > 0 )
     return;
@@ -47419,16 +46868,14 @@ void cdiCreateTimesteps(stream_t *streamptr)
   if ( streamptr->ntsteps == 0 ) ntsteps = 1;    /* <<<<<-------- */
   else ntsteps = streamptr->ntsteps;
 
-  streamptr->tsteps = (tsteps_t *) malloc(ntsteps*sizeof(tsteps_t));
-  if ( streamptr->tsteps == NULL )
-    SysError("Allocation of tsteps_t failed");
+  streamptr->tsteps = (tsteps_t *)xmalloc((size_t)ntsteps*sizeof(tsteps_t));
 
-  streamptr->tstepsTableSize = ntsteps;
-  streamptr->tstepsNextID    = ntsteps;
+  streamptr->tstepsTableSize = (int)ntsteps;
+  streamptr->tstepsNextID    = (int)ntsteps;
 
   for ( tsID = 0; tsID < ntsteps; tsID++ )
     {
-      tstepsInitEntry(streamptr, tsID);
+      tstepsInitEntry(streamptr, (int)tsID);
       streamptr->tsteps[tsID].taxis.used = TRUE;
     }
 }
@@ -47445,16 +46892,17 @@ void cdiCreateTimesteps(stream_t *streamptr)
 #endif
 
 #include <assert.h>
-#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
-#include <errno.h>
-#include <ctype.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>  // gettimeofday()
-#include <fcntl.h>
 
 
 
@@ -47627,7 +47075,7 @@ void file_list_new(void)
 {
   assert(_fileList == NULL);
 
-  _fileList = (filePtrToIdx *) malloc(_file_max*sizeof(filePtrToIdx));
+  _fileList = (filePtrToIdx *)xmalloc((size_t)_file_max * sizeof (filePtrToIdx));
 }
 
 static
@@ -47969,7 +47417,6 @@ off_t fileGetPos(int fileID)
 int fileSetPos(int fileID, off_t offset, int whence)
 {
   int status = 0;
-  off_t position;
   bfile_t *fileptr;
 
   fileptr = file_to_pointer(fileID);
@@ -47987,7 +47434,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
     case SEEK_SET:
       if ( fileptr->mode == 'r' && fileptr->type == FILE_TYPE_OPEN )
 	{
-	  position = offset;
+	  off_t position = offset;
 	  fileptr->position = position;
 	  if ( position < fileptr->bufferStart || position > fileptr->bufferEnd )
 	    {
@@ -48009,7 +47456,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
 
 		  fileptr->bufferPos = fileptr->bufferEnd + 1;
 		}
-	      fileptr->bufferCnt = fileptr->bufferEnd - position + 1;
+	      fileptr->bufferCnt = (size_t)(fileptr->bufferEnd - position) + 1;
 	      fileptr->bufferPtr = fileptr->buffer + position - fileptr->bufferStart;
 	    }
 	}
@@ -48022,7 +47469,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
       if ( fileptr->mode == 'r' && fileptr->type == FILE_TYPE_OPEN )
 	{
 	  fileptr->position += offset;
-	  position = fileptr->position;
+	  off_t position = fileptr->position;
 	  if ( position < fileptr->bufferStart || position > fileptr->bufferEnd )
 	    {
 	      if ( fileptr->bufferType == FILE_BUFTYPE_STD )
@@ -48043,7 +47490,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
 
 		  fileptr->bufferPos = fileptr->bufferEnd + 1;
 		}
-	      fileptr->bufferCnt -= offset;
+	      fileptr->bufferCnt -= (size_t)offset;
 	      fileptr->bufferPtr += offset;
 	    }
 	}
@@ -48218,7 +47665,7 @@ void file_initialize(void)
 	{
 	case FILE_TYPE_OPEN:
 	case FILE_TYPE_FOPEN:
-	  FileTypeRead = value;
+	  FileTypeRead = (int)value;
 	  break;
 	default:
 	  Warning("File type %d not implemented!", value);
@@ -48232,13 +47679,16 @@ void file_initialize(void)
 	{
 	case FILE_TYPE_OPEN:
 	case FILE_TYPE_FOPEN:
-	  FileTypeWrite = value;
+	  FileTypeWrite = (int)value;
 	  break;
 	default:
 	  Warning("File type %d not implemented!", value);
 	}
     }
 
+#if defined (O_NONBLOCK)
+  FileFlagWrite = O_NONBLOCK;
+#endif
   envString = getenv("FILE_FLAG_WRITE");
   if ( envString )
     {
@@ -48261,7 +47711,7 @@ void file_initialize(void)
 	{
 	case FILE_BUFTYPE_STD:
 	case FILE_BUFTYPE_MMAP:
-	  FileBufferTypeEnv = value;
+	  FileBufferTypeEnv = (int)value;
 	  break;
 	default:
 	  Warning("File buffer type %d not implemented!", value);
@@ -48354,7 +47804,7 @@ void file_set_buffer(bfile_t *fileptr)
 static
 int file_fill_buffer(bfile_t *fileptr)
 {
-  long nread;
+  ssize_t nread;
   int fd;
   long offset = 0;
   off_t retseek;
@@ -48379,7 +47829,8 @@ int file_fill_buffer(bfile_t *fileptr)
 	}
       else
 	{
-	  nread = fileptr->bufferSize;
+          xassert(fileptr->bufferSize <= SSIZE_MAX);
+	  nread = (ssize_t)fileptr->bufferSize;
 	  if ( (nread + fileptr->bufferPos) > fileptr->size )
 	    nread = fileptr->size - fileptr->bufferPos;
 
@@ -48391,7 +47842,7 @@ int file_fill_buffer(bfile_t *fileptr)
 	      fileptr->buffer = NULL;
 	    }
 
-	  fileptr->mappedSize = (size_t) nread;
+	  fileptr->mappedSize = (size_t)nread;
 
 	  fileptr->buffer = (char*) mmap(NULL, (size_t) nread, PROT_READ, MAP_PRIVATE, fd, fileptr->bufferPos);
 
@@ -48407,7 +47858,7 @@ int file_fill_buffer(bfile_t *fileptr)
       if ( retseek == (off_t)-1 )
 	SysError("lseek error at pos %ld file %s", (long) fileptr->bufferPos, fileptr->name);
 
-      nread = (long) read(fd, fileptr->buffer, fileptr->bufferSize);
+      nread = read(fd, fileptr->buffer, fileptr->bufferSize);
     }
 
   if ( nread <= 0 )
@@ -48422,7 +47873,7 @@ int file_fill_buffer(bfile_t *fileptr)
     }
 
   fileptr->bufferPtr = fileptr->buffer;
-  fileptr->bufferCnt = nread;
+  fileptr->bufferCnt = (size_t)nread;
 
   fileptr->bufferStart = fileptr->bufferPos;
   fileptr->bufferPos  += nread;
@@ -48445,7 +47896,7 @@ int file_fill_buffer(bfile_t *fileptr)
 	Error("Internal problem with buffer handling. nread = %d offset = %d", nread, offset);
 
       fileptr->bufferPtr += offset;
-      fileptr->bufferCnt -= offset;
+      fileptr->bufferCnt -= (size_t)offset;
     }
 
   fileptr->bufferNumFill++;
@@ -48522,11 +47973,9 @@ size_t file_read_from_buffer(bfile_t *fileptr, void *ptr, size_t size)
 
 void fileSetBufferSize(int fileID, long buffersize)
 {
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
-
-  if ( fileptr ) fileptr->bufferSize = buffersize;
+  bfile_t *fileptr = file_to_pointer(fileID);
+  xassert(buffersize >= 0);
+  if ( fileptr ) fileptr->bufferSize = (size_t)buffersize;
 }
 
 /*
@@ -48668,8 +48117,10 @@ int fileClose_serial(int fileID)
       if ( fileptr->type == FILE_TYPE_FOPEN )
 	fprintf(stderr, " file pointer     : %p\n",  (void *) fileptr->fp);
       else
-        fprintf(stderr, " file descriptor  : %d\n",  fileptr->fd);
-
+        {
+          fprintf(stderr, " file descriptor  : %d\n",  fileptr->fd);
+          fprintf(stderr, " file flag        : %d\n", FileFlagWrite);
+        }
       fprintf(stderr, " file mode        : %c\n",  fileptr->mode);
 
       if ( sizeof(off_t) > sizeof(long) )
@@ -48696,8 +48147,7 @@ int fileClose_serial(int fileID)
 
       if ( fileptr->time_in_sec > 0 )
         {
-          rout = fileptr->byteTrans;
-          rout /= 1024.*1014.*fileptr->time_in_sec;
+          rout = (double)fileptr->byteTrans / (1024.*1024.*fileptr->time_in_sec);
         }
 
       fprintf(stderr, " wall time [s]    : %.2f\n", fileptr->time_in_sec);
@@ -48818,8 +48268,8 @@ size_t filePtrRead(void *vfileptr, void *restrict ptr, size_t size)
 	    }
 	}
 
-      fileptr->position  += nread;
-      fileptr->byteTrans += nread;
+      fileptr->position  += (off_t)nread;
+      fileptr->byteTrans += (off_t)nread;
       fileptr->access++;
     }
 
@@ -48858,8 +48308,8 @@ size_t fileRead(int fileID, void *restrict ptr, size_t size)
 
       if ( FileInfo ) fileptr->time_in_sec += file_time() - t_begin;
 
-      fileptr->position  += nread;
-      fileptr->byteTrans += nread;
+      fileptr->position  += (off_t)nread;
+      fileptr->byteTrans += (off_t)nread;
       fileptr->access++;
     }
 
@@ -48887,12 +48337,21 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
       if ( fileptr->type == FILE_TYPE_FOPEN )
         nwrite = fwrite(ptr, 1, size, fileptr->fp);
       else
-        nwrite =  write(fileptr->fd, ptr, size);
+        {
+          ssize_t temp = write(fileptr->fd, ptr, size);
+          if (temp == -1)
+            {
+              perror("error writing to file");
+              nwrite = 0;
+            }
+          else
+            nwrite = (size_t)temp;
+        }
 
       if ( FileInfo ) fileptr->time_in_sec += file_time() - t_begin;
 
-      fileptr->position  += nwrite;
-      fileptr->byteTrans += nwrite;
+      fileptr->position  += (off_t)nwrite;
+      fileptr->byteTrans += (off_t)nwrite;
       fileptr->access++;
     }
 
@@ -48908,9 +48367,19 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
  * End:
  */
 
-/* Automatically generated by m214003 at 2014-06-27, do not edit */
+/* Automatically generated by m214003 at 2014-09-30, do not edit */
+
+/* CGRIBEXLIB_VERSION="1.7.0" */
 
-/* CGRIBEXLIB_VERSION="1.6.4" */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic warning "-Wstrict-overflow"
+#endif
 
 #ifdef _ARCH_PWR6
 #pragma options nostrict
@@ -48927,6 +48396,13 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
 
 
 
+#ifndef _TEMPLATES_H
+#define _TEMPLATES_H
+
+#define CAT(X,Y)      X##_##Y
+#define TEMPLATE(X,Y) CAT(X,Y)
+
+#endif 
 #ifndef _GRIB_INT_H
 #define _GRIB_INT_H
 
@@ -49007,6 +48483,8 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
 #  define IS_EQUAL(x,y)     (!IS_NOT_EQUAL(x,y))
 #endif
 
+/* dummy use of unused parameters to silence compiler warnings */
+#define  UNUSED(x) (void)x
 
 #define  JP23SET    0x7FFFFF  /* 2**23 - 1 (---> 8388607)  */
 
@@ -49055,19 +48533,20 @@ void   confp3(double pval, int *kexp, int *kmant, int kbits, int kround);
 double decfp2(int kexp, int kmant);
 void   ref2ibm(double *pref, int kbits);
 
-void   scaleComplex(double *fpdata, int pcStart, int pcScale, int trunc, int inv);
-void   scatterComplex(double *fpdata, int pcStart, int trunc, int nsp);
-void   gatherComplex(double *fpdata, int pcStart, int trunc, int nsp);
+void   scale_complex_double(double *fpdata, int pcStart, int pcScale, int trunc, int inv);
+void   scale_complex_float(float *fpdata, int pcStart, int pcScale, int trunc, int inv);
+void   scatter_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
+void   scatter_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
+void   gather_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
+void   gather_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
 
-void   scm0(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
-int    rowina2(double *p, int ko, int ki, double *pw,
-	       int kcode, double msval, int *kret);
-int    rowina3(double *p, int ko, int ki, double *pw,
-	       int kcode, double msval, int *kret, int omisng, int operio, int oveggy);
+void   scm0_double(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
 int    qu2reg2(double *pfield, int *kpoint, int klat, int klon,
 	       double *ztemp, double msval, int *kret);
-int    qu2reg3(double *pfield, int *kpoint, int klat, int klon,
-	       double msval, int *kret, int omisng, int operio, int oveggy);
+int    qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
+		      double msval, int *kret, int omisng, int operio, int oveggy);
+int    qu2reg3_float(float *pfield, int *kpoint, int klat, int klon,
+		     float msval, int *kret, int omisng, int operio, int oveggy);
 
 #if  defined  (INT32)
 long   packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc);
@@ -49078,13 +48557,26 @@ long   unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc
 #endif
 long   unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc);
 
-void  gribEncode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		 int kleng, int *kword, int efunc, int *kret);
+void  grib_encode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
+			 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
+			 int kleng, int *kword, int efunc, int *kret);
+void  grib_encode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+			float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
+			int kleng, int *kword, int efunc, int *kret);
+
+void  grib_decode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
+			 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
+			 int kleng, int *kword, int dfunc, int *kret);
+void  grib_decode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+			float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
+			int kleng, int *kword, int dfunc, int *kret);
 
-void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		 int kleng, int *kword, int dfunc, int *kret);
+
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
+		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize);
+int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
+		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
+		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
 
 #endif  /* _GRIB_INT_H */
 #ifndef _GRIBDECODE_H
@@ -49228,8 +48720,8 @@ void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
 #define  GRIB2_SECNUM(section)   (GET_UINT1(section[4]))
 
 #endif  /* _GRIBDECODE_H */
-#ifndef _GRIBENCODE_H
-#define _GRIBENCODE_H
+#ifndef _GRIB_ENCODE_H
+#define _GRIB_ENCODE_H
 
 
 #define PutnZero(n) \
@@ -49261,7 +48753,7 @@ void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
   Put3Byte(mantissa);            \
 }
 
-#endif  /* _GRIBENCODE_H */
+#endif  /* _GRIB_ENCODE_H */
 #include <stdio.h>
 #include <math.h>
 
@@ -49535,14 +49027,14 @@ double intpow2(int x)
 }
 /* 
 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
- result on bailung (gcc 4.7):
-  orig    : fmin: -500000  fmax: 499999  time:   4.84s
-  sse2    : fmin: -500000  fmax: 499999  time:   4.82s
+ result on bailung (gcc 4.8.2):
+  orig    : fmin: -500000  fmax: 499999  time:   4.82s
+  sse2    : fmin: -500000  fmax: 499999  time:   4.83s
 
 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD minmax_val.c
- result on thunder5 (gcc 4.7.2):
+ result on thunder5 (gcc 4.8.2):
   orig    : fmin: -500000  fmax: 499999  time:   3.10s
-  simd    : fmin: -500000  fmax: 499999  time:   3.23s # omp simd in gcc 4.9
+  simd    : fmin: -500000  fmax: 499999  time:   3.10s # omp simd in gcc 4.9
   avx     : fmin: -500000  fmax: 499999  time:   2.84s
 
 icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
@@ -49624,7 +49116,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax
 #if defined(_ENABLE_AVX)
 
 static
-void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, double *max)
+void avx_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
 {
   double fmin[4], fmax[4];
   __m256d current_max, current_min, work;
@@ -49646,7 +49138,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
 
   while (nframes >= 16) {
 
-    (void) _mm_prefetch(buf+8, _MM_HINT_NTA);
+    (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
 
     work = _mm256_load_pd(buf);
     current_min = _mm256_min_pd(current_min, work);
@@ -49658,7 +49150,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
     current_max = _mm256_max_pd(current_max, work);
     buf += 4;
 
-    (void) _mm_prefetch(buf+8, _MM_HINT_NTA);
+    (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
 
     work = _mm256_load_pd(buf);
     current_min = _mm256_min_pd(current_min, work);
@@ -49718,7 +49210,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
 #elif defined(_ENABLE_SSE2)
 
 static
-void sse2_minmax_val(const double *restrict buf, size_t nframes, double *min, double *max)
+void sse2_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
 {
   __m128d current_max, current_min, work;
   
@@ -49796,7 +49288,7 @@ void sse2_minmax_val(const double *restrict buf, size_t nframes, double *min, do
 
 #if defined(_ARCH_PWR6)
 static
-void pwr6_minmax_val_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
 #define __UNROLL_DEPTH_1 6
   size_t datasize = idatasize;
@@ -49843,7 +49335,7 @@ void pwr6_minmax_val_unrolled6(const double *restrict data, long idatasize, doub
 
 #if defined(TEST_MINMAXVAL) && defined(__GNUC__)
 static
-void minmax_val_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
 #endif
 
 #if defined(GNUC_PUSH_POP)
@@ -49851,7 +49343,7 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma GCC optimize ("O3", "fast-math")
 #endif
 static
-void minmax_val_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
   size_t i;
   size_t datasize = idatasize;
@@ -49863,13 +49355,39 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma vdir nodep
 #elif defined(__uxp__)
 #pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; ++i )
+    {
+      dmin = dmin < data[i] ? dmin : data[i];
+      dmax = dmax > data[i] ? dmax : data[i];
+    }
+
+  *fmin = dmin;
+  *fmax = dmax;
+}
+
+static
+void minmax_val_float(const float *restrict data, long idatasize, float *fmin, float *fmax)
+{
+  size_t i;
+  size_t datasize = idatasize;
+  float dmin = *fmin, dmax = *fmax;
+
+#if   defined(CRAY)
+#pragma _CRI ivdep
+#elif defined(SX)
+#pragma vdir nodep
+#elif defined(__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
 #endif
   for ( i = 0; i < datasize; ++i )
     {
       dmin = dmin < data[i] ? dmin : data[i];
       dmax = dmax > data[i] ? dmax : data[i];
-      //      if ( dmin > data[i] ) dmin = data[i];
-      //      if ( dmax < data[i] ) dmax = data[i];
     }
 
   *fmin = dmin;
@@ -49892,7 +49410,7 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma GCC optimize ("O3", "fast-math")
 #endif
 static
-void minmax_val_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
   size_t i;
   size_t datasize = idatasize;
@@ -49917,7 +49435,7 @@ void minmax_val_simd(const double *restrict data, long idatasize, double *fmin,
 #endif
 
 static
-void minmax_val(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
 #if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER) 
   uint64_t start_minmax, end_minmax;
@@ -49935,11 +49453,11 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
 
 #if defined(_ENABLE_AVX)
 
-  avx_minmax_val(data, datasize, fmin, fmax);
+  avx_minmax_val_double(data, datasize, fmin, fmax);
 
 #elif defined(_ENABLE_SSE2)
 
-  sse2_minmax_val(data, datasize, fmin, fmax);
+  sse2_minmax_val_double(data, datasize, fmin, fmax);
 
 #else
 
@@ -49952,7 +49470,7 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
   hpmStart(1, "minmax fsel");
 #endif
 
-  pwr6_minmax_val_unrolled6(data, datasize, fmin, fmax);
+  pwr6_minmax_val_double_unrolled6(data, datasize, fmin, fmax);
 
 #if defined(_GET_IBM_COUNTER) 
   hpmStop(1);
@@ -49966,7 +49484,7 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
   hpmStart(1, "minmax base");
 #endif
 
-  minmax_val_orig(data, datasize, fmin, fmax);
+  minmax_val_double_orig(data, datasize, fmin, fmax);
 
 #if defined(_GET_IBM_COUNTER) 
   hpmStop(1);
@@ -50017,8 +49535,6 @@ double dtime()
 int main(void)
 {
   long datasize = 1000000;
-  double *data = NULL;
-  double fmin, fmax;
   double t_begin, t_end;
 
 #if   defined(_OPENMP)
@@ -50033,71 +49549,96 @@ int main(void)
   printf("gcc\n");
 #endif
 
-  data = (double*) malloc(datasize*sizeof(double));
+  {
+    float fmin, fmax;
+    float *data_sp = (float*) malloc(datasize*sizeof(float));
 
-  // for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
-  for ( long i = 0; i < datasize/2; i++ )        data[i] = (double) (i);
-  for ( long i = datasize/2; i < datasize; i++ ) data[i] = (double) (-datasize + i);
-  // for ( long i = 0; i < datasize; i++ )    printf("%d %g\n", i, data[i]);
+    for ( long i = 0; i < datasize/2; i++ )        data_sp[i] = (float) (i);
+    for ( long i = datasize/2; i < datasize; i++ ) data_sp[i] = (float) (-datasize + i);
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    printf("float:\n");
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val_orig(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("orig      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_sp[0];
+	minmax_val_float(data_sp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    free(data_sp);
+  }
+
+  {
+    double fmin, fmax;
+    double *data_dp = (double*) malloc(datasize*sizeof(double));
+
+    // for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
+    for ( long i = 0; i < datasize/2; i++ )        data_dp[i] = (double) (i);
+    for ( long i = datasize/2; i < datasize; i++ ) data_dp[i] = (double) (-datasize + i);
+
+    printf("double:\n");
+
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double_orig(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("orig      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 
 #if defined(OMP_SIMD)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val_simd(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("simd      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double_simd(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("simd      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
 
 #if defined(_ENABLE_AVX)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      avx_minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("avx       : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	avx_minmax_double_val(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("avx       : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #elif defined(_ENABLE_SSE2)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      sse2_minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("sse2      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	sse2_minmax_val_double(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("sse2      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
 #if defined(_ARCH_PWR6)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      pwr6_minmax_val_unrolled6(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("pwr6u6  : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	pwr6_minmax_val_double_unrolled6(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("pwr6u6  : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
+    free(data_dp);
+  }
 
   return (0);
 }
@@ -50108,22 +49649,27 @@ int main(void)
 #undef _ENABLE_SSE2
 #undef GNUC_PUSH_POP
 /* 
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL encode_double_array.c
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama (gcc 4.8.2):
+  orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 16.0471s
+  sse41   : val1: 1  val2: 1  val3: 2  valn: 66  time: 15.4391s
+
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
  result on bailung (gcc 4.7):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 8.4166s
   sse41   : val1: 1  val2: 1  val3: 2  valn: 66  time: 7.1522s
 
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL encode_double_array.c
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
  result on thunder5 (gcc 4.7):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 6.21976s
   avx     : val1: 1  val2: 1  val3: 2  valn: 66  time: 4.54485s
 
-icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_MINMAXVAL encode_double_array.c
+icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_ENCODE encode_array.c
  result on thunder5 (icc 13.2):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 14.6279s
   avx     : val1: 1  val2: 1  val3: 2  valn: 66  time:  4.9776s
 
-xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode_double_array.c
+xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_array.c
  result on blizzard (xlc 12):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 132.25s
   unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time:  27.202s
@@ -50134,7 +49680,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode
 #pragma options nostrict
 #endif
 
-#ifdef TEST_MINMAXVAL
+#ifdef TEST_ENCODE
 #include <stdio.h>
 #include <stdlib.h>
 #define  GRIBPACK     unsigned char
@@ -50194,7 +49740,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode
 #if defined _ENABLE_AVX
 
 static
-void avx_encode_double_array_2byte(size_t datasize, 
+void avx_encode_array_2byte_double(size_t datasize, 
 				   unsigned char * restrict lGrib,
 				   const double * restrict data, 
 				   double zref, double factor, size_t *gz) 
@@ -50295,7 +49841,7 @@ void avx_encode_double_array_2byte(size_t datasize,
 #elif defined _ENABLE_SSE4_1
 
 static
-void sse41_encode_double_array_2byte(size_t datasize, 
+void sse41_encode_array_2byte_double(size_t datasize, 
 				     unsigned char * restrict lGrib,
 				     const double * restrict data, 
 				     double zref, double factor, size_t *gz) 
@@ -50423,705 +49969,305 @@ void sse41_encode_double_array_2byte(size_t datasize,
 
 #endif // SIMD variants
 
+
+#ifdef TEST_ENCODE
+
+#define CAT(X,Y)      X##_##Y
+#define TEMPLATE(X,Y) CAT(X,Y)
+
+#ifdef T
+#undef T
+#endif
+#define T double
+
+#ifdef T
+#undef T
+#endif
+#define T float
+
+
+#include <sys/time.h>
+
 static
-void encode_double_array_common(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
-				const double *data, double zref, double factor, size_t *gz)
+double dtime()
 {
-  size_t i, z = *gz;
-  unsigned int ival;
-  int cbits, jbits;
-  unsigned int c;
-  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-    
-  /* code from gribw routine flist2bitstream */
+  double tseconds = 0.0;
+  struct timeval mytime;
+  gettimeofday(&mytime, NULL);
+  tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
+  return (tseconds);
+}
 
-  cbits = 8;
-  c = 0;
-  for ( i = packStart; i < datasize; i++ )
-    {
-      /* note float -> unsigned int .. truncate */
-      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
-      /*
-	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
-	if ( ival < 0 ) ival = 0;
-      */
-      jbits = numBits;
-      while ( cbits <= jbits ) 
-	{
-	  if ( cbits == 8 )
-	    {
-	      jbits -= 8;
-	      lGrib[z++] = (ival >> jbits) & 0xFF;
-	    }
-	  else
-	    {
-	      jbits -= cbits;
-	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
-	      cbits = 8;
-	      c = 0;
-	    }
-	}
-      /* now jbits < cbits */
-      if ( jbits )
-	{
-	  c = (c << jbits) + (ival & mask[jbits]);
-	  cbits -= jbits;
-	}
-    }
-  if ( cbits != 8 ) lGrib[z++] = c << cbits;
+#define NRUN 10000
 
-  *gz = z;
+static
+void pout(char *name, int s, unsigned char *lgrib, long datasize, double tt)
+{
+  printf("%8s: val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", name, (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], tt);
 }
 
-static
-void encode_double_array_2byte(size_t datasize, GRIBPACK *restrict lGrib,
-			       const double *restrict data, double zref, double factor, size_t *gz)
+int main(void)
 {
-  size_t i, z = *gz;
-  uint16_t ui16;
-  double tmp;
+  long datasize = 1000000;
+  float *dataf = NULL;
+  double *data = NULL;
+  double t_begin, t_end;
+  unsigned char *lgrib;
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
-#endif
-  for ( i = 0; i < datasize; i++ )
+  dataf = (float*) malloc(datasize*sizeof(float));
+  data  = (double*) malloc(datasize*sizeof(double));
+  lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
+
+  for ( long i = 0; i < datasize; ++i ) dataf[i] = (float) (-datasize/2 + i);
+  for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
+
+  int PackStart = 0;
+  int nbpv = 16;
+  double zref = data[0];
+  size_t z;
+  double factor = 0.00390625;
+  int s = 256;
+
+  if ( 0 )
     {
-      tmp = ((data[i] - zref) * factor + 0.5);
-      ui16 = (uint16_t) tmp;
-      lGrib[z  ] = ui16 >>  8;
-      lGrib[z+1] = ui16;
-      z += 2;
+      encode_array_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
+      encode_array_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
     }
 
-  *gz = z;
-}
 
-static
-void encode_double_array_byte(int numBits, size_t packStart, size_t datasize, 
-			      GRIBPACK *restrict lGrib,
-			      const double *restrict data, 
-			      double zref, double factor, size_t *gz)
-{
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
-  uint64_t start_minmax, end_minmax;
+#if   defined(__ICC)
+  printf("icc\n");
+#elif defined(__clang__)
+  printf("clang\n");
+#elif defined(__GNUC__)
+  printf("gcc\n");
 #endif
 
-  uint32_t ui32;
-  size_t i, z = *gz;
-  double tmp;
+  printf("float:\n");
 
-  data += packStart;
-  datasize -= packStart;
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_2byte_float(datasize, lgrib, dataf, (float)zref, (float)factor, &z);
+    }
+  t_end = dtime();
+  pout("orig", s, lgrib, datasize, t_end-t_begin);
 
-  if      ( numBits ==  8 )
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
     {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(2, "pack 8 bit base");
-#endif
+      z = 0;
+      encode_array_unrolled_float(nbpv, PackStart, datasize, lgrib, dataf, (float)zref, (float)factor, &z);
+    }
+  t_end = dtime();
+  pout("unrolled", s, lgrib, datasize, t_end-t_begin);
 
-#if defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
-#endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-	  lGrib[z  ] = (uint16_t) tmp;
-          z++;
-	}
+  printf("double:\n");
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(2);
-#endif
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
     }
-  else if ( numBits == 16 )
+  t_end = dtime();
+  pout("orig", s, lgrib, datasize, t_end-t_begin);
+
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
     {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(3, "pack 16 bit base");
-#elif defined _GET_X86_COUNTER 
-  start_minmax = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-  start_minmax = mach_absolute_time();
-#endif
+      z = 0;
+      encode_array_unrolled_double(nbpv, PackStart, datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("unrolled", s, lgrib, datasize, t_end-t_begin);
 
 #if defined _ENABLE_AVX
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      avx_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("avx", s, lgrib, datasize, t_end-t_begin);
+#elif defined _ENABLE_SSE4_1
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      sse41_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("sse41", s, lgrib, datasize, t_end-t_begin);
+#endif
 
-      avx_encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+  return 0;
+}
+#endif // TEST_ENCODE
 
-#elif defined _ENABLE_SSE4_1
+#undef DISABLE_SIMD
+#undef _ENABLE_AVX
+#undef _ENABLE_SSE4_1
+//#undef _GET_X86_COUNTER
+//#undef _GET_MACH_COUNTER
+//#undef _GET_IBM_COUNTER
+//#undef _ARCH_PWR6
+
+#if defined _GET_IBM_COUNTER
+#include <libhpc.h>
+#elif defined _GET_X86_COUNTER
+#include <x86intrin.h>
+#elif defined _GET_MACH_COUNTER
+#include <mach/mach_time.h>
+#endif
 
-      sse41_encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
 
+#if   defined(__GNUC__) && (__GNUC__ >= 4)
+#elif defined(__ICC)    && (__ICC >= 1100)
+#elif defined(__clang__)
 #else
+#define DISABLE_SIMD
+#endif
 
-      encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+#define DISABLE_SIMD
 
+#ifdef DISABLE_SIMD
+# ifdef ENABLE_AVX
+#  define _ENABLE_AVX
+# endif
+# ifdef ENABLE_SSE4_1
+#  define _ENABLE_SSE4_1
+# endif
 #endif
 
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER 
-      end_minmax = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      end_minmax = mach_absolute_time();
+#ifndef DISABLE_SIMD
+# ifdef __AVX__
+#  define _ENABLE_AVX
+# endif
+# ifdef __SSE4_1__
+#  define _ENABLE_SSE4_1
+# endif
 #endif
+
 #if defined _ENABLE_AVX
-      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#include <immintrin.h>
 #elif defined _ENABLE_SSE4_1
-      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
-#else
-      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
-#endif  
-#endif
-      
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(3);
-#endif
-    }
-  else if ( numBits == 24 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(4, "pack 24 bit base");
+#include <smmintrin.h>
 #endif
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
-#endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-          ui32 = (uint32_t) tmp;
-          lGrib[z  ] =  ui32 >> 16;
-          lGrib[z+1] =  ui32 >>  8;
-          lGrib[z+2] =  ui32;
-          z += 3;
-	}
+#if defined _ENABLE_AVX
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(4);
-#endif
-    }
-  else if ( numBits == 32 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(5, "pack 32 bit base");
-#endif
+static
+void avx_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
+				     double * restrict fpdata, double fmin, double zscale)
+{
+  size_t i, j;
+  size_t nframes = datasize;
+  size_t residual;
+  size_t ofs;
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
-#endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-          ui32 = (uint32_t) tmp;
-          lGrib[z  ] =  ui32 >> 24;
-          lGrib[z+1] =  ui32 >> 16;
-          lGrib[z+2] =  ui32 >>  8;
-          lGrib[z+3] =  ui32;
-          z += 4;
-	}
+  double dval;
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(5);
-#endif
-    }
-  else if ( numBits > 0 && numBits <= 32 )
+  double *data = fpdata;
+  __m128i *sgrib;
+  
+  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
+
+  __m256d ymm0 = _mm256_set1_pd(fmin);
+  __m256d ymm1 = _mm256_set1_pd(zscale);
+  
+  __m128i xmm0, xmm1, xmm2, xmm3;
+  __m256d ymm2, ymm3;
+
+  i = -1;
+  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
     {
-      encode_double_array_common(numBits, 0, datasize, lGrib, 
-				 data, zref, factor, &z);
+      i++;
+      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
+      fpdata[i] = fmin + zscale * dval;
+      data++;
+      nframes--;
     }
-  else if ( numBits == 0 )
-    {
+  
+  if (i == -1) i = 0;
+  sgrib = (__m128i *) (igrib+i);
+
+  while (nframes >= 16)
+    { 
+      xmm0 = _mm_loadu_si128((__m128i *) sgrib);
+      xmm0 = _mm_shuffle_epi8(xmm0, mask);
+      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
+      xmm2 = _mm_cvtepu16_epi32(xmm0);
+      xmm3 = _mm_cvtepu16_epi32(xmm1);
+
+      ymm2 = _mm256_cvtepi32_pd(xmm2);
+      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
+      (void) _mm256_stream_pd(data, ymm2);
+      ymm3 = _mm256_cvtepi32_pd(xmm3);
+      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+4, ymm3);  
+      
+      xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
+      xmm0 = _mm_shuffle_epi8(xmm0, mask);
+      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
+      xmm2 = _mm_cvtepu16_epi32(xmm0);
+      xmm3 = _mm_cvtepu16_epi32(xmm1);
+      
+      ymm2 = _mm256_cvtepi32_pd(xmm2);
+      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+8, ymm2);
+      ymm3 = _mm256_cvtepi32_pd(xmm3);
+      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+12, ymm3);  
+      
+      data += 16;
+      sgrib += 2;
+      nframes -= 16;
     }
-  else
+
+  residual = nframes;
+  ofs = datasize - residual;
+  for ( j = 0; j < residual; j++ )
     {
-      Error("Unimplemented packing factor %d!", numBits);
+      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
+      fpdata[ofs+j] = fmin + zscale * dval;
     }
 
-  *gz = z;
+  return;
 }
 
+#elif defined _ENABLE_SSE4_1
+
 static
-void encode_double_array_unrolled(int numBits, size_t packStart, size_t datasize, 
-				  GRIBPACK *restrict lGrib,
-				  const double *restrict data, 
-				  double zref, double factor, size_t *gz)
+void sse41_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
+				     double * restrict fpdata, double fmin, double zscale)
 {
-  U_BYTEORDER;
-  size_t i, j, z = *gz;
-#ifdef _ARCH_PWR6
-#define __UNROLL_DEPTH_2 8
-#else
-#define __UNROLL_DEPTH_2 8
-#endif
+  size_t i, j;
+  size_t nframes = datasize;
   size_t residual;
   size_t ofs;
-  double dval[__UNROLL_DEPTH_2];
-  unsigned long ival;
 
-  data += packStart;
-  datasize -= packStart;
-  residual =  datasize % __UNROLL_DEPTH_2;
-  ofs = datasize - residual;
+  double dval;
 
-  // reducing FP operations to single FMA is slowing down on pwr6 ...
+  double *data = fpdata;
+  __m128i *sgrib;
+  
+  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
+  __m128d dmm8 = _mm_set1_pd(fmin);
+  __m128d dmm9 = _mm_set1_pd(zscale);
+  
+  __m128i xmm4, xmm5;
+  __m128i xmm6, xmm7;
+  
+  __m128d dmm0, dmm1, dmm2, dmm3;
+  __m128d dmm4, dmm5, dmm6, dmm7;
 
-  if      ( numBits ==  8 )
-    {
-      unsigned char *cgrib = (unsigned char *) (lGrib + z);
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(2, "pack 8 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      *cgrib++ =  (unsigned long) dval[j];
-	    }
-	  z += __UNROLL_DEPTH_2;
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  *cgrib++ = (unsigned long) dval[j];
-	}
-      z += residual;
-
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(2);
-#endif
-    }
-  else if ( numBits == 16 )
-    {
-      unsigned short *sgrib = (unsigned short *) (lGrib + z);
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(3, "pack 16 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  if ( IS_BIGENDIAN() )
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  *sgrib++ = (unsigned long) dval[j];
-		}
-	      z += 2*__UNROLL_DEPTH_2;
-	    }
-	  else
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  ival = (unsigned long) dval[j];
-		  lGrib[z  ] = ival >>  8;
-		  lGrib[z+1] = ival;
-		  z += 2;
-		}
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      if ( IS_BIGENDIAN() )
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      *sgrib++ = (unsigned long) dval[j];
-	    }
-	  z += 2*residual;
-	}
-      else
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] = ival >>  8;
-	      lGrib[z+1] = ival;
-	      z += 2;
-	    }
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(3);
-#endif
-    }
-  else if ( numBits == 24 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(4, "pack 24 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] =  ival >> 16;
-	      lGrib[z+1] =  ival >>  8;
-	      lGrib[z+2] =  ival;
-	      z += 3;
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  ival = (unsigned long) dval[j];
-	  lGrib[z  ] =  ival >> 16;
-	  lGrib[z+1] =  ival >>  8;
-	  lGrib[z+2] =  ival;
-	  z += 3;
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(4);
-#endif
-    }
-  else if ( numBits == 32 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(5, "pack 32 bit unrolled");
-#endif
-      unsigned int *igrib = (unsigned int *) (lGrib + z);
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  if ( IS_BIGENDIAN() )
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  *igrib = (unsigned long) dval[j];
-		  igrib++;
-		  z += 4;
-		}
-	    }
-	  else
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  ival = (unsigned long) dval[j];
-		  lGrib[z  ] =  ival >> 24;
-		  lGrib[z+1] =  ival >> 16;
-		  lGrib[z+2] =  ival >>  8;
-		  lGrib[z+3] =  ival;
-		  z += 4;
-		}
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      if ( IS_BIGENDIAN() )
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      *igrib = (unsigned long) dval[j];
-	      igrib++;
-	      z += 4;
-	    }
-	}
-      else
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] =  ival >> 24;
-	      lGrib[z+1] =  ival >> 16;
-	      lGrib[z+2] =  ival >>  8;
-	      lGrib[z+3] =  ival;
-	      z += 4;
-	    }
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(5);
-#endif
-    }
-  else if ( numBits > 0 && numBits <= 32 )
-    {
-      encode_double_array_common(numBits, 0, datasize, lGrib, data, zref, factor, &z);
-    }
-  else if ( numBits == 0 )
-    {
-    }
-  else
-    {
-      Error("Unimplemented packing factor %d!", numBits);
-    }
-
-  *gz = z;
-#undef __UNROLL_DEPTH_2
-}
-
-#ifdef TEST_MINMAXVAL
-
-#include <sys/time.h>
-
-static
-double dtime()
-{
-  double tseconds = 0.0;
-  struct timeval mytime;
-  gettimeofday(&mytime, NULL);
-  tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
-  return (tseconds);
-}
-
-#define NRUN 10000
-
-int main(void)
-{
-  long datasize = 1000000;
-  double *data = NULL;
-  double t_begin, t_end;
-  unsigned char *lgrib;
-
-  data  = (double*) malloc(datasize*sizeof(double));
-  lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
-
-  for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
-
-  int PackStart = 0;
-  int nbpv = 16;
-  double zref = data[0];
-  size_t z;
-  double factor = 0.00390625;
-  int s = 256;
-
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("orig    : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      encode_double_array_unrolled (nbpv, PackStart, datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("unrolled: val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-
-#if defined _ENABLE_AVX
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      avx_encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("avx     : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-#elif defined _ENABLE_SSE4_1
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      sse41_encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("sse41   : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-#endif
-
-  return 0;
-}
-#endif // TEST_MINMAXVAL
-
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
-//#undef _GET_X86_COUNTER
-//#undef _GET_MACH_COUNTER
-//#undef _GET_IBM_COUNTER
-//#undef _ARCH_PWR6
-
-#if defined _GET_IBM_COUNTER
-#include <libhpc.h>
-#elif defined _GET_X86_COUNTER
-#include <x86intrin.h>
-#elif defined _GET_MACH_COUNTER
-#include <mach/mach_time.h>
-#endif
-
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#if   defined(__GNUC__) && (__GNUC__ >= 4)
-#elif defined(__ICC)    && (__ICC >= 1100)
-#elif defined(__clang__)
-#else
-#define DISABLE_SIMD
-#endif
-
-#define DISABLE_SIMD
-
-#ifdef DISABLE_SIMD
-# ifdef ENABLE_AVX
-#  define _ENABLE_AVX
-# endif
-# ifdef ENABLE_SSE4_1
-#  define _ENABLE_SSE4_1
-# endif
-#endif
-
-#ifndef DISABLE_SIMD
-# ifdef __AVX__
-#  define _ENABLE_AVX
-# endif
-# ifdef __SSE4_1__
-#  define _ENABLE_SSE4_1
-# endif
-#endif
-
-#if defined _ENABLE_AVX
-#include <immintrin.h>
-#elif defined _ENABLE_SSE4_1
-#include <smmintrin.h>
-#endif
-
-#if defined _ENABLE_AVX
-
-static
-void avx_decode_double_array_2byte(size_t datasize, const unsigned char * restrict igrib,
-				     double * restrict fpdata, double fmin, double zscale)
-{
-  size_t i, j;
-  size_t nframes = datasize;
-  size_t residual;
-  size_t ofs;
-
-  double dval;
-
-  double *data = fpdata;
-  __m128i *sgrib;
-  
-  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
-
-  __m256d ymm0 = _mm256_set1_pd(fmin);
-  __m256d ymm1 = _mm256_set1_pd(zscale);
-  
-  __m128i xmm0, xmm1, xmm2, xmm3;
-  __m256d ymm2, ymm3;
-
-  i = -1;
-  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
-    {
-      i++;
-      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
-      fpdata[i] = fmin + zscale * dval;
-      data++;
-      nframes--;
-    }
-  
-  if (i == -1) i = 0;
-  sgrib = (__m128i *) (igrib+i);
-
-  while (nframes >= 16)
-    { 
-      xmm0 = _mm_loadu_si128((__m128i *) sgrib);
-      xmm0 = _mm_shuffle_epi8(xmm0, mask);
-      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
-      xmm2 = _mm_cvtepu16_epi32(xmm0);
-      xmm3 = _mm_cvtepu16_epi32(xmm1);
-
-      ymm2 = _mm256_cvtepi32_pd(xmm2);
-      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
-      (void) _mm256_stream_pd(data, ymm2);
-      ymm3 = _mm256_cvtepi32_pd(xmm3);
-      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+4, ymm3);  
-      
-      xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
-      xmm0 = _mm_shuffle_epi8(xmm0, mask);
-      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
-      xmm2 = _mm_cvtepu16_epi32(xmm0);
-      xmm3 = _mm_cvtepu16_epi32(xmm1);
-      
-      ymm2 = _mm256_cvtepi32_pd(xmm2);
-      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+8, ymm2);
-      ymm3 = _mm256_cvtepi32_pd(xmm3);
-      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+12, ymm3);  
-      
-      data += 16;
-      sgrib += 2;
-      nframes -= 16;
-    }
-
-  residual = nframes;
-  ofs = datasize - residual;
-  for ( j = 0; j < residual; j++ )
-    {
-      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
-      fpdata[ofs+j] = fmin + zscale * dval;
-    }
-
-  return;
-}
-
-#elif defined _ENABLE_SSE4_1
-
-static
-void sse41_decode_double_array_2byte(size_t datasize, const unsigned char * restrict igrib,
-				     double * restrict fpdata, double fmin, double zscale)
-{
-  size_t i, j;
-  size_t nframes = datasize;
-  size_t residual;
-  size_t ofs;
-
-  double dval;
-
-  double *data = fpdata;
-  __m128i *sgrib;
-  
-  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
-  __m128d dmm8 = _mm_set1_pd(fmin);
-  __m128d dmm9 = _mm_set1_pd(zscale);
-  
-  __m128i xmm4, xmm5;
-  __m128i xmm6, xmm7;
-  
-  __m128d dmm0, dmm1, dmm2, dmm3;
-  __m128d dmm4, dmm5, dmm6, dmm7;
-
-  i = -1;
-  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
+  i = -1;
+  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
     {
       i++;
       dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
@@ -51193,266 +50339,23 @@ void sse41_decode_double_array_2byte(size_t datasize, const unsigned char * rest
 
 #endif
 
-static 
-void decode_double_array_common(const unsigned char * restrict igrib, long jlend, int NumBits, 
-				double fmin, double zscale, double * restrict fpdata)
-{
-  /* code from wgrib routine BDS_unpack */
-  const unsigned char *bits = igrib;
-  unsigned int jmask;
-  long i;
-  unsigned int tbits = 0;
-  int n_bits = NumBits;
-  int t_bits = 0;
-      
-  jmask = (1 << n_bits) - 1;
-  for ( i = 0; i < jlend; i++ )
-    {
-      if (n_bits - t_bits > 8)
-	{
-	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
-	  bits += 2;
-	  t_bits += 16;
-	}
-
-      while ( t_bits < n_bits )
-	{
-	  tbits = (tbits * 256) + *bits++;
-	  t_bits += 8;
-	}
-      t_bits -= n_bits;
-      fpdata[i] = (tbits >> t_bits) & jmask;
-    }
-  /* at least this vectorizes :) */
-  for ( i = 0; i < jlend; i++ )
-    fpdata[i] = fmin + zscale*fpdata[i];
-}
+#undef DISABLE_SIMD
+#undef _ENABLE_AVX
+#undef _ENABLE_SSE4_1
 
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
 
-static 
-void decode_double_array_common2(const unsigned char * restrict igrib, long jlend, int NumBits, 
-				 double fmin, double zscale, double * restrict fpdata)
+void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
 {
-  /* code from wgrib routine BDS_unpack */
-  const unsigned char *bits = igrib;
-  long i;
-  int n_bits = NumBits;
-  int c_bits, j_bits;
-  double jj;
+  /*
 
-  /* older unoptimized code, not often used */
-  c_bits = 8;
-  for ( i = 0; i < jlend; i++ )
-    {
-      jj = 0.0;
-      j_bits = n_bits;
-      while (c_bits <= j_bits)
-	{
-	  if (c_bits == 8)
-	    {
-	      jj = jj * 256.0  + (double) (*bits++);
-	      j_bits -= 8;
-	    }
-	  else
-	    {
-	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
-	      bits++;
-	      j_bits -= c_bits;
-	      c_bits = 8;
-	    }
-	}
+    Purpose:
+    --------
 
-      if (j_bits)
-	{
-	  c_bits -= j_bits;
-	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
-	}
-      
-      fpdata[i] = fmin + zscale*jj;
-    }
-} 
+    Convert floating point number from machine
+    representation to GRIB representation.
 
-static 
-void decode_double_array_byte(const unsigned char *restrict igrib, long jlend, int numBits, 
-			      double fmin, double zscale, double *restrict fpdata)
-{
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
-  uint64_t start_decode, end_decode;
-#endif
-
-  long i;
-  double dval;
-#if defined (VECTORCODE)
-  GRIBPACK *lgrib = NULL;
-
-  if ( numBits%8 == 0 )
-    {
-      long jlenc = jlend * numBits / 8;
-      if ( jlenc > 0 ) 
-	{
-	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
-	  if ( lgrib == NULL ) SysError("No Memory!");
-
-	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
-	}
-    }
-
-  if ( numBits ==  0 )
-    {
-      for ( i = 0; i < jlend; i++ )
-	fpdata[i] = fmin;
-    }
-  else if ( numBits ==  8 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (int)lgrib[i];
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 16 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 24 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
-	  	 (int)lgrib[3*i+2]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 32 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
-		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits <= 25 )
-    {
-      decode_double_array_common(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else if ( numBits > 25 && numBits < 32 )
-    {
-      decode_double_array_common2(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else
-    {
-      Error("Unimplemented packing factor %d!", numBits);
-    }
-
-  if ( lgrib ) free(lgrib);
-
-#else
-  if ( numBits ==  0 )
-    {
-      for ( i = 0; i < jlend; i++ )
-	fpdata[i] = fmin;
-    }
-  else if ( numBits ==  8 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (int)igrib[i];
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 16 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER 
-      start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      start_decode = mach_absolute_time();
-#endif
-      
-#if defined _ENABLE_AVX
-      printf("AVX selected ...\n");
-      avx_decode_double_array_2byte((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
-      printf("SSE4 selected ...\n");
-      sse41_decode_double_array_2byte((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
-      for ( i = 0; i < jlend; i++ )
-	{
-	  dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
-	  fpdata[i] = fmin + zscale * dval;
-	}
-#endif
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER 
-      end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
-      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
-      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
-      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif  
-#endif
-      
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(6);
-#endif
-    }
-  else if ( numBits == 24 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
-		 (int)igrib[3*i+2]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 32 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
-		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits <= 25 )
-    {
-      decode_double_array_common(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else if ( numBits > 25 && numBits < 32 )
-    {
-      decode_double_array_common2(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else
-    {
-      Error("Unimplemented packing factor %d!", numBits);
-    }
-#endif
-}
-
-static 
-void decode_double_array_unrolled(const unsigned char * restrict igrib, long jlend, int numBits, 
-				  double fmin, double zscale, double * restrict fpdata)
-{
-  decode_double_array_byte(igrib, jlend, numBits, fmin, zscale, fpdata);
-}
-
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
-
-
-void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
-{
-  /*
-
-    Purpose:
-    --------
-
-    Convert floating point number from machine
-    representation to GRIB representation.
-
-    Input Parameters:
-    -----------------
+    Input Parameters:
+    -----------------
 
        pval    - Floating point number to be converted.
        kbits   - Number of bits in computer word.
@@ -51947,13 +50850,14 @@ void gribDateTime(int *isec1, int *date, int *time)
       addsec = 0;
       switch ( ISEC1_TimeUnit )
 	{
-	case ISEC1_TABLE4_MINUTE:  addsec =    60 * time_period; break;
-	case ISEC1_TABLE4_QUARTER: addsec =   900 * time_period; break;
-	case ISEC1_TABLE4_HOUR:    addsec =  3600 * time_period; break;
-	case ISEC1_TABLE4_3HOURS:  addsec = 10800 * time_period; break;
-	case ISEC1_TABLE4_6HOURS:  addsec = 21600 * time_period; break;
-	case ISEC1_TABLE4_12HOURS: addsec = 43200 * time_period; break;
-	case ISEC1_TABLE4_DAY:     addsec = 86400 * time_period; break;
+	case ISEC1_TABLE4_MINUTE:    addsec =    60 * time_period; break;
+	case ISEC1_TABLE4_QUARTER:   addsec =   900 * time_period; break;
+	case ISEC1_TABLE4_30MINUTES: addsec =  1800 * time_period; break;
+	case ISEC1_TABLE4_HOUR:      addsec =  3600 * time_period; break;
+	case ISEC1_TABLE4_3HOURS:    addsec = 10800 * time_period; break;
+	case ISEC1_TABLE4_6HOURS:    addsec = 21600 * time_period; break;
+	case ISEC1_TABLE4_12HOURS:   addsec = 43200 * time_period; break;
+	case ISEC1_TABLE4_DAY:       addsec = 86400 * time_period; break;
 	default:
 	  if ( lprint )
 	    {
@@ -52001,15 +50905,21 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
   int yfunc = *hoper;
 
   if ( yfunc == 'C' )
-    gribEncode(isec0, isec1, isec2, fsec2, isec3,
-	       fsec3, isec4, fsec4, klenp, kgrib,
-	       kleng, kword, yfunc, kret);
+    {
+      grib_encode_double(isec0, isec1, isec2, fsec2, isec3,
+			 fsec3, isec4, fsec4, klenp, kgrib,
+			 kleng, kword, yfunc, kret);
+    }
   else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
-    gribDecode(isec0, isec1, isec2, fsec2, isec3,
-	       fsec3, isec4, fsec4, klenp, kgrib,
-	       kleng, kword, yfunc, kret);
+    {
+      grib_decode_double(isec0, isec1, isec2, fsec2, isec3,
+			 fsec3, isec4, fsec4, klenp, kgrib,
+			 kleng, kword, yfunc, kret);
+    }
   else if ( yfunc == 'V' )
-    fprintf(stderr, "  cgribex: Version is %s\n", cgribexLibraryVersion());
+    {
+      fprintf(stderr, "  cgribex: Version is %s\n", cgribexLibraryVersion());
+    }
   else
     {
       Error("oper %c unsupported!", yfunc);
@@ -52019,10 +50929,41 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
 
 
 void
-gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
-	 float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
+gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+	 float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
 	 int kleng, int *kword, char *hoper, int *kret)
 {
+  int yfunc = *hoper;
+
+  if ( yfunc == 'C' )
+    {
+      grib_encode_float(isec0, isec1, isec2, fsec2, isec3,
+			fsec3, isec4, fsec4, klenp, kgrib,
+			kleng, kword, yfunc, kret);
+    }
+  else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
+    {
+      grib_decode_float(isec0, isec1, isec2, fsec2, isec3,
+			fsec3, isec4, fsec4, klenp, kgrib,
+			kleng, kword, yfunc, kret);
+    }
+  else if ( yfunc == 'V' )
+    {
+      fprintf(stderr, " cgribex: Version is %s\n", cgribexLibraryVersion());
+    }
+  else
+    {
+      Error("oper %c unsupported!", yfunc);
+      *kret=-9;
+    }
+}
+
+
+void
+gribExSP_old(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
+	     float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
+	     int kleng, int *kword, char *hoper, int *kret)
+{
   int inum, j;
   double fsec2dp[1024];
   double fsec3dp[2];
@@ -52130,11 +51071,13 @@ void gribSetConst(int flag)
 
 void gribSetRound(int round)
 {
+  UNUSED(round);
 }
 
 
 void gribSetRefDP(double refval)
 {
+  UNUSED(refval);
 }
 
 
@@ -52146,6 +51089,7 @@ void gribSetRefSP(float refval)
 
 void gribSetValueCheck(int vcheck)
 {
+  UNUSED(vcheck);
 }
 #include <string.h>
 #include <math.h>
@@ -52205,7 +51149,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 
   */
 
-  int iprev, icurr, icount, ioffset;
+  int iprev, icurr, ioffset;
   int ibit, ierr, iout, iyear;
   int jloop, jiloop;
   float value;
@@ -52299,7 +51243,7 @@ void gribPrintSec1(int *isec0, int *isec1)
     fprintf(grprsm, " Century of reference time of data.   %9d\n", isec1[20]);
 
   /*   Print sub-centre  */
-  fprintf(grprsm, " Sub-centre identifier.               %9d\n", isec1[21]);
+  fprintf(grprsm, " Sub-centre identifier.               %9d\n", ISEC1_SubCenterID);
 
   /*   Decimal scale factor  */
   fprintf(grprsm, " Units decimal scaling factor.        %9d\n", isec1[22]);
@@ -52757,7 +51701,7 @@ void gribPrintSec1(int *isec0, int *isec1)
           fprintf(grprsm, " List of different time intervals used:\n");
           iprev  = isec1[49];
           icurr  = 0;
-          icount = 0;
+          unsigned icount = 0;
           for (jloop = 1; jloop <= isec1[48]; jloop++)
 	    {
 	      icurr = isec1[48+jloop];
@@ -52768,7 +51712,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 		  if ( icount == 2 )
 		    fprintf(grprsm, "  - interval %5.4d used       twice\n", iprev);
 		  if ( icount > 2 )
-		    fprintf(grprsm, "  - interval %5.4d used %5d times\n",  iprev, icount);
+		    fprintf(grprsm, "  - interval %5.4d used %5u times\n",  iprev, icount);
 		  iprev  = icurr;
 		  icount = 1;
 		}
@@ -52780,7 +51724,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 	  if ( icount == 2 )
 	    fprintf(grprsm, "  - interval %5.4d used       twice\n", iprev);
 	  if ( icount > 2 )
-	    fprintf(grprsm, "  - interval %5.4d used %5d times\n",  iprev, icount);
+	    fprintf(grprsm, "  - interval %5.4d used %5u times\n",  iprev, icount);
 	}
       /*
 	ECMWF Local definition 13.
@@ -52911,7 +51855,7 @@ void gribPrintSec1(int *isec0, int *isec1)
     Washington EPS products (but not reformatted Washington EPS
     products.
   */
-  if ( (isec1[1] == 7 && isec1[23] == 1) && (! isec1[21] == 98) )
+  if ( (isec1[1] == 7 && isec1[23] == 1) && (! (ISEC1_SubCenterID == 98)) )
     {
       /*   CALL KWPRS1 (iSEC0,iSEC1)*/
     }
@@ -52953,7 +51897,7 @@ void printQuasi(int *isec2)
   */
 
   char yout[64];
-  int nextlat, nrepeat, latcnt;
+  int nextlat, latcnt;
   int j;
   int ntos;
 
@@ -52994,7 +51938,7 @@ void printQuasi(int *isec2)
       /*
 	Look for neighbouring latitudes with same number of points
       */
-      nrepeat = 0;
+      unsigned nrepeat = 0;
 
     LABEL110:
       /*
@@ -53265,7 +52209,7 @@ void gribPrintSec2DP(int *isec0, int *isec2, double *fsec2)
     -----------------------------------------------------------------
   */
   /*
-  if ( isec2[0] == 192 && isec1[1] == 98 )
+  if ( isec2[0] == 192 && ISEC1_CenterID == 98 )
     {
       fprintf(grprsm, " Data represent type = ECMWF ocean  (Table 6) %9d\n", isec2[0]);
       if ( isec2[1] ==  32767 )
@@ -53289,7 +52233,7 @@ void gribPrintSec2DP(int *isec0, int *isec2, double *fsec2)
     Section 7.6 . Print triangular data
     -----------------------------------------------------------------
   */
-  if ( isec2[0] == 192 /* && isec1[1] == 78 */ )
+  if ( isec2[0] == 192 /* && ISEC1_CenterID == 78 */ )
     {
       fprintf(grprsm, " Data represent type = triangular   (Table 6) %9d\n", isec2[0]);
       fprintf(grprsm, " Number of factor 2 in factorisation of Ni.   %9d\n", isec2[1]);
@@ -53408,6 +52352,8 @@ void gribPrintSec3DP(int *isec0, int *isec3, double *fsec3)
 
   */
 
+  UNUSED(isec0);
+
   grsdef();
 
   fprintf(grprsm, " \n");
@@ -53458,6 +52404,8 @@ void gribPrintSec4DP(int *isec0, int *isec4, double *fsec4)
   int inum;
   int j;
 
+  UNUSED(isec0);
+
   grsdef();
 
   /*
@@ -53636,2639 +52584,3020 @@ void gribPrintSec4Wave(int *isec4)
       fprintf(grprsm, "%20.10f\n", *ptemp);
     }
 }
-#include <string.h>
+#if defined (HAVE_CONFIG_H)
+#endif
 
-int  BitsPerInt = (int) (sizeof(int) * 8);
+#include <string.h>
+#include <ctype.h>
 
 
 
-/* GRIB block 0 - indicator block */
-static
-void encodeIS(GRIBPACK *lGrib, long *gribLen)
+int gribOpen(const char *filename, const char *mode)
 {
-  long z = *gribLen;
-
-  lGrib[0] = 'G';
-  lGrib[1] = 'R';
-  lGrib[2] = 'I';
-  lGrib[3] = 'B';
+  int fileID;
 
-  /* 
-   * lGrib[4]-lGrib[6] contains full length of grib record. 
-   * included before finished CODEGB
-   */
+  fileID = fileOpen(filename, mode);
 
-  z = 7;   
-  Put1Byte(1); /* grib version */
-  z = 8;
+#if defined (__sun)
+  if ( fileID != FILE_UNDEFID && tolower(*mode) == 'r' )
+    {
+      fileSetBufferType(fileID, FILE_BUFTYPE_MMAP);
+    }
+#endif
 
-  *gribLen = z;
+  return (fileID);  
 }
 
-/* GRIB block 5 - end block */
-static
-void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
+
+void gribClose(int fileID)
 {
-  long z = *gribLen;
+  fileClose(fileID);
+}
 
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
 
-  if ( z > JP23SET )
-    {
-      long itemp;
-      long bdslen = z - 4;
-      /*
-      fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET);
-      exit(1);
-      */
-      /*
-	If a very large product, the section 4 length field holds
-	the number of bytes in the product after section 4 upto
-	the end of the padding bytes.
-	This is a fixup to get round the restriction on product lengths
-	due to the count being only 24 bits. It is only possible because
-	the (default) rounding for GRIB products is 120 bytes.
-      */
-      while ( z%120 ) lGrib[z++] = 0;
+off_t gribGetPos(int fileID)
+{
+  return (fileGetPos(fileID));
+}
 
-      if ( z > JP23SET*120 )
-	{
-	  fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET*120);
-	  exit(1);
-	}
 
-      itemp = z / (-120);
-      itemp = JP23SET - itemp + 1;
+int gribCheckFiletype(int fileID)
+{
+  int ierr;
+  int found = 0;
+  char buffer[4];
 
-      lGrib[4] = itemp >> 16;
-      lGrib[5] = itemp >>  8;
-      lGrib[6] = itemp;
+  if ( fileRead(fileID, buffer, 4) != 4 ) return(found);
 
-      bdslen = z - bdslen;
-      lGrib[bdsstart  ] = bdslen >> 16;
-      lGrib[bdsstart+1] = bdslen >>  8;
-      lGrib[bdsstart+2] = bdslen;
+  if ( memcmp(buffer, "GRIB", 4) == 0 )
+    {
+      found = 1;
+      if ( CGRIBEX_Debug ) Message("found GRIB file = %s", fileInqName(fileID));
     }
   else
     {
-      lGrib[4] = z >> 16;
-      lGrib[5] = z >>  8;
-      lGrib[6] = z;
+      long offset;
 
-      while ( z%8 ) lGrib[z++] = 0;
+      ierr = gribFileSeek(fileID, &offset);
+      fileRewind(fileID);
+      if ( !ierr )
+	{
+	  found = 1;
+	  if ( CGRIBEX_Debug ) Message("found seek GRIB file = %s", fileInqName(fileID));
+	}
     }
 
-  *gribLen = z;
+  return (found);
 }
 
-/* GRIB block 1 - product definition block. */
-
-#define DWD_extension_253_len 38
-#define DWD_extension_254_len 26
-#define ECMWF_extension_1_len 24
-#define MPIM_extension_1_len  18
 
-static
-long getLocalExtLen(int *isec1)
+int gribCheckSeek(int fileID, long *offset, int *version)
 {
-  long extlen = 0;
+  int ierr;
+  char buffer[4];
 
-  if ( ISEC1_LocalFLag )
+  ierr = gribFileSeek(fileID, offset);
+
+  *version = -1;
+  if ( !ierr )
     {
-      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	{
-	  if      ( isec1[36] == 254 ) extlen = DWD_extension_254_len;
-	  else if ( isec1[36] == 253 ) extlen = DWD_extension_253_len;
-	}
-      else if ( ISEC1_CenterID == 98 )
-        {
-	  if ( isec1[36] == 1 )   extlen = ECMWF_extension_1_len;
-        }
-      else if ( ISEC1_CenterID == 252 )
-        {
-	  if ( isec1[36] == 1 ) extlen = MPIM_extension_1_len;
-        }
+      if ( fileRead(fileID, buffer, 4) == 4 )
+	*version = buffer[3];
     }
 
-  return (extlen);
+  return (ierr);
 }
 
-static
-long getPdsLen(int *isec1)
+
+int gribFileSeekOld(int fileID, long *offset)
 {
-  long pdslen = 28;
+  /* position file pointer after GRIB */
+  int ch;
+  int buffersize = 4096;
+  unsigned char buffer[4096];
+  int retry = 4096;
+  int i;
+  void *fileptr;
 
-  pdslen += getLocalExtLen(isec1);
+  *offset = 0;
 
-  return (pdslen);
-}
+  fileptr = filePtr(fileID);
 
-static
-void encodePDS_DWD_local_Extension_254(GRIBPACK *lGrib, long *zs, int *isec1)
-{
-  int isvn;
-  long localextlen, i;
-  long z = *zs;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
+  /*
+  fileRead(fileID, buffer, 4);
+  */
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-2; i++ )
+  while ( retry-- )
     {
-      Put1Byte(isec1[24+i]);
+      for ( i = 0; i < buffersize-4; ++i )
+	{
+	  if (buffer[i  ] == 'G' && 
+	      buffer[i+1] == 'R' &&
+	      buffer[i+2] == 'I' &&
+	      buffer[i+3] == 'B')
+	    {
+	      if ( CGRIBEX_Debug )
+		Message("record offset = %d", (int) *offset);
+	      return (0);
+	    }
+	  else
+	    {
+	      ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
+	      (*offset)++;
+	    }
+	}
+      buffer[0] = buffer[i  ];
+      buffer[1] = buffer[i+1];
+      buffer[2] = buffer[i+2];
+      buffer[3] = buffer[i+3];
     }
 
-  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
-  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
 
-  *zs = z;
+  return (1);
 }
 
-static
-void encodePDS_DWD_local_Extension_253(GRIBPACK *lGrib, long *zs, int *isec1)
+
+int gribFileSeek(int fileID, long *offset)
 {
-  int isvn;
-  long localextlen, i;
-  long z = *zs;
+  /* position file pointer after GRIB */
+  const long GRIB = 0x47524942;
+  long code = 0;
+  int ch;
+  int retry = 4096*4096;
+  void *fileptr;
 
-  localextlen = DWD_extension_254_len;
-  for ( i = 0; i < localextlen-2; i++ )
+  *offset = 0;
+
+  fileptr = filePtr(fileID);
+
+  while ( retry-- )
     {
-      Put1Byte(isec1[24+i]);
+      ch = filePtrGetc(fileptr);
+      if ( ch == EOF ) return (-1);
+    
+      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+
+      if ( code == GRIB )
+	{
+	  if ( CGRIBEX_Debug )
+	    Message("record offset = %d", (int) *offset);
+	  return (0);
+	}
+
+      (*offset)++;
     }
 
-  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
-  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
-  Put1Byte(isec1[50]);        /* 55 User id, specified by table       */
-  Put2Byte(isec1[51]);        /* 56 Experiment identifier             */
-  Put2Byte(isec1[52]);        /* 58 Ensemble identification by table  */
-  Put2Byte(isec1[53]);        /* 60 Number of ensemble members        */
-  Put2Byte(isec1[54]);        /* 62 Actual number of ensemble member  */
-  Put1Byte(isec1[55]);        /* 64 Model major version number        */ 
-  Put1Byte(isec1[56]);        /* 65 Model minor version number        */ 
-  Put1Byte(0);                /* 66 Blank for even buffer length      */
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
 
-  *zs = z;
+  return (1);
 }
 
-static
-void encodePDS_ECMWF_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
+
+int gribFileSeekTest(int fileID, long *offset)
 {
-  // int isvn;
-  long localextlen, i;
-  long z = *zs;
+  /* position file pointer after GRIB */
+  const long GRIB = 0x47524942;
+  long code = 0;
+  int ch;
+  int i = 0;
+  const int buffersize = 8;
+  unsigned char buffer[8];
+  int retry = 4096*4096;
+  void *fileptr;
+  int nread = 0;
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-12; i++ )
+  *offset = 0;
+
+  fileptr = filePtr(fileID);
+
+  while ( retry-- )
     {
-      Put1Byte(isec1[24+i]);
-    }
-                              /* 12 bytes explicitly encoded below:         */
-  Put1Byte(isec1[36]);        /* ECMWF local GRIB use definition identifier */
-                              /*    1=MARS labelling or ensemble fcst. data */
-  Put1Byte(isec1[37]);        /* Class                                      */
-  Put1Byte(isec1[38]);        /* Type                                       */
-  Put2Byte(isec1[39]);        /* Stream                                     */
+      if ( i >= nread )
+	{
+	  nread = (int) filePtrRead(fileptr, buffer, buffersize);
+	  if ( nread == 0 ) return (-1);
+	  i = 0;
+	}
 
-  /* Version number or experiment identifier    */
-  Put1Byte(((unsigned char*) &isec1[40])[0]);
-  Put1Byte(((unsigned char*) &isec1[40])[1]);
-  Put1Byte(((unsigned char*) &isec1[40])[2]);
-  Put1Byte(((unsigned char*) &isec1[40])[3]);
+      ch = buffer[i++];
+      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
 
-  Put1Byte(isec1[41]);        /* Ensemble forecast number                   */
-  Put1Byte(isec1[42]);        /* Total number of forecasts in ensemble      */
-  Put1Byte(0);                /* (Spare)                                    */
+      if ( code == GRIB )
+	{
+	  /* printf("end: %d %d\n", nread, i); */
+	  if ( CGRIBEX_Debug )
+	    Message("record offset = %d", (int) *offset);
 
-  *zs = z;
-}
+	  if ( i != nread ) fileSetPos(fileID, (off_t) i-nread, SEEK_CUR);
 
-static
-void encodePDS_MPIM_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
-{
-  // int isvn;
-  long localextlen, i;
-  long z = *zs;
+	  return (0);
+	}
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-6; i++ )
-    {
-      Put1Byte(isec1[24+i]);
+      (*offset)++;
     }
-                              /* 6 bytes explicitly encoded below:          */
-  Put1Byte(isec1[36]);        /* MPIM local GRIB use definition identifier  */
-                              /*    (extension identifier)                  */
-  Put1Byte(isec1[37]);        /* type of ensemble forecast                  */
-  Put2Byte(isec1[38]);        /* individual ensemble member                 */
-  Put2Byte(isec1[39]);        /* number of forecasts in ensemble            */
-
-  *zs = z;
-}
 
-/* GRIB BLOCK 1 - PRODUCT DESCRIPTION SECTION */
-static
-void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
+
+  return (1);
+}
+
+
+int gribReadSize(int fileID)
 {
-  GRIBPACK *lGrib = lpds;
-  long z = 0;
-  int ival, century, year;
+  int gribversion, gribsize;
+  int b1, b2, b3;
+  off_t pos;
+  void *fileptr;
+  /*
+  const int buffersize = 4;
+  unsigned char buffer[4];
+  */
+  fileptr = filePtr(fileID);
 
-  century = ISEC1_Century;
-  year    = ISEC1_Year;
+  pos = fileGetPos(fileID); 
+  /* bug: order of functions calls!
+     gribsize = (filePtrGetc(fileptr) << 16) + (filePtrGetc(fileptr) << 8) + filePtrGetc(fileptr);
+  */
+  b1 = filePtrGetc(fileptr);
+  b2 = filePtrGetc(fileptr);
+  b3 = filePtrGetc(fileptr);
+  // gribsize = (b1 << 16) + (b2 << 8) + b3;
+  gribsize = gribrec_len(b1, b2, b3);
 
-  if ( century < 0 )
-    {
-      century = -century;
-      year    = -year;
-    }
+  gribversion = filePtrGetc(fileptr);
+  /*
+  filePtrRead(fileptr, buffer, buffersize);
 
-  Put3Byte(pdsLen);               /*  0 Length of Block 1        */
-  Put1Byte(ISEC1_CodeTable);      /*  3 Local table number       */
-  Put1Byte(ISEC1_CenterID);       /*  4 Identification of centre */
-  Put1Byte(ISEC1_ModelID);        /*  5 Identification of model  */
-  Put1Byte(ISEC1_GridDefinition); /*  6 Grid definition          */
-  Put1Byte(ISEC1_Sec2Or3Flag);    /*  7 Block 2 included         */
-  Put1Byte(ISEC1_Parameter);      /*  8 Parameter Code           */
-  Put1Byte(ISEC1_LevelType);      /*  9 Type of level            */
-  if ( (ISEC1_LevelType !=  20) &&
-       (ISEC1_LevelType != GRIB1_LTYPE_99)         &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)   &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)   &&
-       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)     &&
-       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)      &&
-       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)     &&
-       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH)  &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
-       (ISEC1_LevelType != 115) &&
-       (ISEC1_LevelType != 117) &&
-       (ISEC1_LevelType != 125) &&
-       (ISEC1_LevelType != 127) &&
-       (ISEC1_LevelType != 160) &&
-       (ISEC1_LevelType != 210) )
-    {
-      Put1Byte(ISEC1_Level1);
-      Put1Byte(ISEC1_Level2);
-    }
-  else
+  gribsize = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
+
+  gribversion = buffer[3];
+  */
+  if ( gribsize == 24 )
     {
-      Put2Byte(ISEC1_Level1);     /* 10 Level                    */    
+      if ( gribversion != 1 && gribversion != 2 ) gribversion = 0;
     }
 
-  Put1Int(year);                  /* 12 Year of Century          */
-  Put1Byte(ISEC1_Month);          /* 13 Month                    */
-  Put1Byte(ISEC1_Day);            /* 14 Day                      */
-  Put1Byte(ISEC1_Hour);           /* 15 Hour                     */
-  Put1Byte(ISEC1_Minute);         /* 16 Minute                   */
+  if ( CGRIBEX_Debug )
+    Message("gribversion = %d", gribversion);
 
-  Put1Byte(ISEC1_TimeUnit);       /* 17 Time unit                */
-  if ( ISEC1_TimeRange == 10 )
-    {
-      Put1Byte(ISEC1_TimePeriod1);
-      Put1Byte(ISEC1_TimePeriod2);
-    }
-  else if ( ISEC1_TimeRange == 113 || ISEC1_TimeRange ==   0 )
-    {
-      Put1Byte(ISEC1_TimePeriod1);
-      Put1Byte(0);
-    }
-  else if ( ISEC1_TimeRange ==   5 || ISEC1_TimeRange ==   4 || 
-	    ISEC1_TimeRange ==   3 || ISEC1_TimeRange ==   2 )
-    {
-      Put1Byte(0);
-      Put1Byte(ISEC1_TimePeriod2);
-    }
-  else
+  if ( gribversion == 0 )
     {
-      Put1Byte(0);
-      Put1Byte(0); 
-    }
-  Put1Byte(ISEC1_TimeRange);      /* 20 Timerange flag           */
-  Put2Byte(ISEC1_AvgNum);         /* 21 Average                  */
+      int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
+      int issize = 4, essize = 4;
+      int flag;
 
-  Put1Byte(ISEC1_AvgMiss);        /* 23 Missing from averages    */
-  Put1Byte(century);              /* 24 Century                  */
-  Put1Byte(ISEC1_SubCenterID);    /* 25 Subcenter                */
-  Put2Byte(ISEC1_DecScaleFactor); /* 26 Decimal scale factor     */
+      pdssize = gribsize;
+      fileSetPos(fileID, (off_t) 3, SEEK_CUR);
+      if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
+      flag = filePtrGetc(fileptr);
+      if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
+  
+      fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
 
-  if ( ISEC1_LocalFLag )
-    {
-      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	{
-	  if      ( isec1[36] == 254 ) encodePDS_DWD_local_Extension_254(lGrib, &z, isec1);
-	  else if ( isec1[36] == 253 ) encodePDS_DWD_local_Extension_253(lGrib, &z, isec1);
-	}
-      else if ( ISEC1_CenterID == 98 )
-	{
-	  if ( isec1[36] == 1 ) encodePDS_ECMWF_local_Extension_1(lGrib, &z, isec1);
-	}
-      else if ( ISEC1_CenterID == 252 )
+      if ( flag & 128 )
 	{
-	  if ( isec1[36] == 1 ) encodePDS_MPIM_local_Extension_1(lGrib, &z, isec1);
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  gdssize = (b1 << 16) + (b2 << 8) + b3;
+	  fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
+	  if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
 	}
-      else
+
+      if ( flag & 64 )
 	{
-	  long i, localextlen;
-	  localextlen = getLocalExtLen(isec1);
-	  for ( i = 0; i < localextlen; i++ )
-	    {
-	      Put1Byte(isec1[24+i]);
-	    }
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  bmssize = (b1 << 16) + (b2 << 8) + b3;
+	  fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
+	  if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
 	}
-    }
-}
-
-/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
-static
-void encodeGDS(GRIBPACK *lGrib, long *gribLen, int *isec2, double *fsec2)
-{
-  long z = *gribLen;
-  int exponent, mantissa;
-  long i;
-  int ival;
-  int pvoffset = 0xFF;
-  int gdslen = 32;
-  unsigned lonIncr, latIncr;
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
+      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+      bdssize = (b1 << 16) + (b2 << 8) + b3;
+      if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
+      gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
+    }
+  else if ( gribversion == 1 )
+    {
+      if ( gribsize > JP23SET ) /* Large GRIB record */
+	{
+	  int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
+	  int issize = 4, essize = 4;
+	  int flag;
 
-  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  pdssize = (b1 << 16) + (b2 << 8) + b3;
+	  if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
 
-  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
+	  for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
+	  if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
+  
+	  fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
 
-  gdslen += ISEC2_NumVCP * 4;
+	  if ( flag & 128 )
+	    {
+	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	      gdssize = (b1 << 16) + (b2 << 8) + b3;
+	      fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
+	      if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
+	    }
+	  
+	  if ( flag & 64 )
+	    {
+	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	      bmssize = (b1 << 16) + (b2 << 8) + b3;
+	      fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
+	      if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
+	    }
 
-  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
-  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
-  Put1Byte(pvoffset);           /*  4    PV */
-  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  bdssize = (b1 << 16) + (b2 << 8) + b3;
+	  bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
+	  if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
-    {
-      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
-      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
-      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
-      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
-      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
-      PutnZero(18);             /* 14-31 reserved                 */
+	  gribsize = issize+pdssize+gdssize+bmssize+bdssize+essize;
+	}
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+  else if ( gribversion == 2 )
     {
-      Put2Byte(ISEC2_GME_NI2);
-      Put2Byte(ISEC2_GME_NI3);
-      Put3Byte(ISEC2_GME_ND);
-      Put3Byte(ISEC2_GME_NI);
-      Put1Byte(ISEC2_GME_AFlag);
-      Put3Int(ISEC2_GME_LatPP);
-      Put3Int(ISEC2_GME_LonPP);
-      Put3Int(ISEC2_GME_LonMPL);
-      Put1Byte(ISEC2_GME_BFlag);
-      PutnZero(5);
+      int i;
+      /* we set gribsize the following way because it doesn't matter then
+	 whether int is 4 or 8 bytes long - we don't have to care if the size
+	 really fits: if it does not, the record can not be read at all */
+      gribsize = 0;
+      for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | filePtrGetc(fileptr);
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+  else
     {
-      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
-
-      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
-      Put3Int(ISEC2_FirstLat);
-      Put3Int(ISEC2_FirstLon);
-      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
-      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
-      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
-      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
-      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
-      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
-      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
-      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
-      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
-      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
-      PutnZero(2);                     /* 34-41 */
+      gribsize = 0;
+      Warning("GRIB version %d unsupported!", gribversion);
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-    {
-      int numlon;
-      if ( ISEC2_Reduced )
-	numlon = 0xFFFF;
-      else
-	numlon = ISEC2_NumLon;
 
-      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
+  if ( filePtrEOF(fileptr) ) gribsize = 0;
 
-      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
-      Put3Int(ISEC2_FirstLat);
-      Put3Int(ISEC2_FirstLon);
-      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
-      Put3Int(ISEC2_LastLat);
-      Put3Int(ISEC2_LastLon);
-      if ( ISEC2_ResFlag == 0 )
-	{
-	  lonIncr = 0xFFFF;
-	  latIncr = 0xFFFF;
-	}
-      else
-	{
-	  lonIncr = ISEC2_LonIncr;
-	  latIncr = ISEC2_LatIncr;
-	}
-      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
-      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
-	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
-      else
-	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
+  if ( CGRIBEX_Debug )
+    Message("gribsize    = %d", gribsize);
 
-      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
-      PutnZero(4);                     /* 28-31 reserved                 */
+  fileSetPos(fileID, pos, SEEK_SET);
 
-      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-	{
-	  Put3Int(ISEC2_LatSP);
-	  Put3Int(ISEC2_LonSP);
-	  Put1Real(FSEC2_RotAngle);
-	}
-    }
-  else
-    {
-      Error("Unsupported grid type %d", ISEC2_GridType);
-    }
+  return (gribsize);
+}
 
-#if defined (SX)
-#pragma vdir novector     /* vectorization gives wrong results on NEC */
-#endif
-  for ( i = 0; i < ISEC2_NumVCP; ++i )
+
+int gribGetSize(int fileID)
+{
+  int recsize;
+  long offset;
+  int ierr;
+
+  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
+  if ( ierr > 0 )
     {
-      Put1Real(fsec2[10+i]);
+      Warning("GRIB record not found!");
+      return (0);
     }
 
-  if ( ISEC2_Reduced )
-    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
+  if ( ierr == -1 )
+    return (0);
+  else if ( ierr == 1 )
+    return (0);
 
-  *gribLen = z;
+  recsize = gribReadSize(fileID);
+
+  if ( CGRIBEX_Debug ) Message("recsize = %d", recsize);
+
+  fileSetPos(fileID, (off_t) -4, SEEK_CUR);
+
+  return (recsize);
 }
 
-/* GRIB BLOCK 3 - BIT MAP SECTION */
-static
-void encodeBMS(GRIBPACK *lGrib, long *gribLen, double *fsec3, int *isec4, double *data, long *datasize)
+
+int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
 {
-  GRIBPACK *bitmap;
-  long bitmapSize;
-  long imaskSize;
-  long i;
-  long bmsLen, bmsUnusedBits;
-  long fsec4size;
-  long z = *gribLen;
-#if defined (VECTORCODE)
-  unsigned int *imask;
-#endif
-  static int lmissvalinfo = 1;
-  /*  unsigned int c, imask; */
+  long offset;
+  int ierr = 0;
+  size_t nread, recsize, recsize0;
 
-  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
+  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
+  if ( ierr > 0 )
     {
-      lmissvalinfo = 0;
-      Message("Missing value = NaN is unsupported!");
+      Warning("GRIB record not found!");
+      return (-2);
     }
 
-  bitmapSize = ISEC4_NumValues;
-  imaskSize = ((bitmapSize+7)>>3)<<3;
-  bitmap = &lGrib[z+6];
-  fsec4size = 0;
-
-#if defined (VECTORCODE)
-  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
-  memset(imask, 0, imaskSize*sizeof(int));
-
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-  for ( i = 0; i < bitmapSize; i++ )
+  if ( ierr == -1 )
     {
-      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
-	{
-	  data[fsec4size++] = data[i];
-	  imask[i] = 1;
-	}
+      *buffersize = 0;
+      return (-1);
     }
-
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-  for ( i = 0; i < imaskSize/8; i++ )
+  else if ( ierr == 1 )
     {
-      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
-	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
-	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
-	          (imask[i*8+6] << 1) | (imask[i*8+7]);
+      *buffersize = 0;
+      return (-2);
     }
 
-  free(imask);
-#else
-  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
+  recsize = gribReadSize(fileID);
 
-  for ( i = 0; i < bitmapSize; i++ )
+  buffer[0] = 'G';
+  buffer[1] = 'R';
+  buffer[2] = 'I';
+  buffer[3] = 'B';
+
+  recsize0 = recsize;
+
+  if ( recsize > *buffersize )
     {
-      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
-	{
-	  data[fsec4size++] = data[i];
-	  bitmap[i/8] |= 1<<(7-(i&7));
-	}
+      recsize = *buffersize;
+      ierr = -3;
     }
-#endif
 
-  bmsLen = imaskSize/8 + 6;
-  bmsUnusedBits = imaskSize - bitmapSize;
+  *buffersize = recsize0;
 
-  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
-  Put1Byte(bmsUnusedBits);
-  Put2Byte(0);
+  nread = fileRead(fileID, &buffer[4], recsize-4);
 
-  *gribLen += bmsLen;
+  if ( nread != recsize-4 ) ierr = 1;
 
-  *datasize = fsec4size;
+  return (ierr);
 }
 
 
-/* GRIB BLOCK 4 - BINARY DATA SECTION */
-static
-int encodeBDS(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, double *data,
-	      long *datstart, long *datsize, int code)
+int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
 {
-  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
-  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
-
-  size_t z = *gribLen;
-  long i, jloop;
-  int numBits;
-  int ival;
-  int blockLength, PackStart = 0, Flag = 0;
-  int binscale = 0;
-  int nbpv;
-  int bds_head = 11;
-  int bds_ext = 0;
-  /* ibits = BitsPerInt; */
-  unsigned int max_nbpv_pow2;
-  int exponent, mantissa;
-  int unused_bits = 0;
-  int lspherc = FALSE, lcomplex = FALSE;
-  int isubset = 0, itemp = 0, itrunc = 0;
-  double factor = 1, fmin, fmax, zref;
-  double range, rangec;
-  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
-                                /*        of floating point numbers - needed   */
-		                /*        on some platforms (eg vpp700, linux) */
-  extern const double _pow2tab[158];
-  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
+  int  nwrite = 0;
 
-  if ( isec2 )
+  if( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
     {
-      /* If section 2 is present, it says if data is spherical harmonic */
+      perror(__func__);
+      nwrite = -1;
+    }
 
-      if ( isec2[0] == 50 || isec2[0] == 60 || 
-	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
+  return ((int) nwrite);
+}
 
-      if ( lspherc )
-	isec4[2] = 128;
-      else
-	isec4[2] = 0;
-    }
-  else
-    {
-      /* Section 4 says if it's spherical harmonic data.. */
 
-      lspherc = ( isec4[2] == 128 );
-    }
+int gribrec_len(int b1, int b2, int b3)
+{
+  int gribsize;
 
-  /* Complex packing supported for spherical harmonics. */
+  gribsize = (1-(int) ((unsigned) (b1&128) >> 6)) * (int) (((b1&127) << 16)+(b2<<8) + b3);
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( gribsize < 0 ) gribsize *= (-120);
 
-  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
-             ( lspherc && isec2 && ( isec2[5] == 2 ) );
+  return (gribsize);
+}
 
-  /* Check input specification is consistent */
-
-  if ( lcomplex && isec2 )
-    {
-      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
-	{
-	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
-	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
-	  return (807);
-	}
-      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
-	{
-	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
-	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
-	  return (807);
-        }
-      else if ( lcomplex )
-	{
-	  /*
-	    Truncation of full spectrum, which is supposed triangular,
-	    has to be diagnosed. Define also sub-set truncation.
-	  */
-	  isubset = isec4[17];
-	  /* When encoding, use the total number of data. */
-	  itemp   = isec4[0];
-	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
-	}
-    }
-
-  if ( decscale )
-    {
-      double scale = pow(10.0, (double) decscale);
-      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
-    }
-
-  if ( lspherc )
-    {
-      if ( lcomplex )
-	{
-	  int jup, ioff;
-	  jup  = isubset;
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
-	  PackStart = ioff;
-	  Flag = 192;
-	}
-      else
-	{
-	  bds_ext = 4;
-	  PackStart = 1;
-	  Flag = 128;
-	}
-    }
-
-  *datstart = bds_head + bds_ext;
-
-  nbpv = numBits = ISEC4_NumBits;
-
-  if ( lspherc && lcomplex )
-    {
-      int pcStart, pcScale;
-      pcStart = isubset;
-      pcScale = isec4[16];
-      scaleComplex(data, pcStart, pcScale, itrunc, 0);
-      gatherComplex(data, pcStart, itrunc, datasize);
-    }
-
-  fmin = fmax = data[PackStart];
-
-  minmax_val(data+PackStart, datasize-PackStart, &fmin, &fmax);
-
-  zref = fmin;
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 
 
-  if ( CGRIBEX_Const && !lspherc )
-    {
-      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
-    }
+FILE *grprsm = NULL;
+double fref;
+double fmaxval;
+int nfref;
+int nfmaxval;
+int nrnd;
+int ndbg;
+int nvck;
+int nonoff;
+int noabort;
+int num2ok;
+int next2o;
+int nloc2o;
+int nsubce;
+int grib_calendar = -1;
 
 
-  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
-  if ( (blockLength%2) == 1 ) blockLength++;
+void gribSetCalendar(int calendar)
+{
+  grib_calendar = calendar;
+}
 
-  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
 
-  Flag += unused_bits;
+void grsdef(void)
+{
+  /*
+C---->
+C**** GRSDEF - Initial (default) setting of common area variables
+C              for GRIBEX package.
+C
+C     Purpose.
+C     --------
+C
+C     Sets initial values for common area variables for all
+C     routines of GRIBEX package, if not already done.
+C
+C**   Interface.
+C     ----------
+C
+C     CALL GRSDEF
+C
+C     Input Parameters.
+C     -----------------
+C
+C     None.
+C
+C     Output Parameters.
+C     ------------------
+C
+C     None.
+C
+C     Method.
+C     -------
+C
+C     Self-explanatory.
+C
+C     Externals.
+C     ----------
+C
+C     None.
+C
+C     Reference.
+C     ----------
+C
+C     See subroutine GRIBEX.
+C
+C     Comments.
+C     ---------
+C
+C     None
+C
+C     Author.
+C     -------
+C
+C     J. Clochard, Meteo France, for ECMWF - March 1998.
+C
+C     Modifications.
+C     --------------
+C
+C     J. Clochard, Meteo France, for ECMWF - June 1999.
+C     Add variable NSUBCE.
+C     Use a static variable to determine if initialisation has already
+C     been done. NUSER removed .
+C     Reverse defaults for NEXT2O and NLOC2O, for consistency with
+C     version 13.023 of software .
+C
+  */
+  /*
+C     ----------------------------------------------------------------
+C*    Section 0 . Definition of variables.
+C     ----------------------------------------------------------------
+  */
+  char *envString;
+  char *env_stream;
+  static int lfirst = TRUE;
+  extern int CGRIBEX_Const;
 
+  if ( ! lfirst ) return;
 
   /*
-    Adjust number of bits per value if full integer length to
-    avoid hitting most significant bit (sign bit).
+    ----------------------------------------------------------------
+    Section 1 . Set values, conditionally.
+    ----------------------------------------------------------------
   */
-  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
   /*
-    Calculate the binary scaling factor to spread the range of
-    values over the number of bits per value.
-    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
-    as a guideline).           
+    Common area variables have not been set. Set them.
+    
+    User supplied reference value.
   */
-  range = fabs(fmax - fmin);
-
-  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  fref   = 0.0;
   /*
-    Have to allow tolerance in comparisons on some platforms
-    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
-    to avoid clipping ranges which are a power of 2.
+    Reference value supplied by user flag. Set to off.
   */
-  if ( range <= jpepsln )
+  nfref  = 0;
+  /*
+    User supplied maximum value.
+  */
+  fmaxval   = 0.0;
+  /*
+    Maximum value supplied by user flag. Set to off.
+  */
+  nfmaxval  = 0;
+  /*
+    Set rounding to 120 bytes on.
+  */
+  nrnd   = 1;
+  /*
+    Set GRIB calendar.
+  */
+  if ( grib_calendar == -1 )
     {
-      binscale = 0;
+      grib_calendar = CALENDAR_PROLEPTIC;
+  
+      envString = getenv("GRIB_CALENDAR");
+      if ( envString )
+	{
+	  if      ( strncmp(envString, "standard", 8) == 0 )
+	    grib_calendar = CALENDAR_STANDARD;
+	  else if ( strncmp(envString, "proleptic", 9) == 0 )
+	    grib_calendar = CALENDAR_PROLEPTIC;
+	  else if ( strncmp(envString, "360days", 7) == 0 )
+	    grib_calendar = CALENDAR_360DAYS;
+	  else if ( strncmp(envString, "365days", 7) == 0 )
+	    grib_calendar = CALENDAR_365DAYS;
+	  else if ( strncmp(envString, "366days", 7) == 0 )
+	    grib_calendar = CALENDAR_366DAYS;
+	  else if ( strncmp(envString, "none", 4) == 0 )
+	    grib_calendar = CALENDAR_NONE;
+	}
     }
-  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
+  /*
+    Set debug print off.
+  */
+  ndbg   = 0;
+  
+  envString = getenv("GRIBEX_DEBUG");
+  if ( envString != NULL )
     {
-      binscale = 0;
+      if ( !strncmp(envString, "ON", 2) )
+        ndbg = 1;
+      else if( *envString == '1')
+        ndbg = 1;
+      else if( *envString == '2')
+        ndbg = 2;
+      else
+        ndbg = 0;
     }
-  else if ( fabs(range-1.0) <= jpepsln )
+  /*
+    Set GRIBEX compatibility mode.
+  */
+  envString = getenv("GRIB_GRIBEX_MODE_ON");
+  if ( envString != NULL )
     {
-      binscale = 1 - nbpv;
+      if ( atoi(envString) == 1 ) CGRIBEX_Const = 0;
     }
-  else if ( range > 1.0 )
+
+  /*
+    Set GRIB value checking on.
+  */
+  nvck   = 1;
+  
+  envString = getenv("GRIBEX_CHECK");
+  if ( envString )
     {
-      rangec = range + jpepsln;
-      for ( jloop = 1; jloop < 128; jloop++ )
-	{
-	  if ( _pow2tab[jloop] > rangec ) break;
-	}
-      if ( jloop == 128 )
-	{
-	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
-	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
-	  return (707);
-	}
+      if ( !strncmp(envString, "OFF", 3) )
+        nvck = 0;
       else
-	{
-	  binscale = jloop - nbpv;
-	}
+        nvck = 1;
     }
-  else
+  /*
+    See if output stream needs changing
+  */
+  grprsm = stdout;
+  env_stream = getenv("GRPRS_STREAM");
+  if ( env_stream )
     {
-      rangec = range - jpepsln;
-      for ( jloop = 1; jloop < 127; jloop++ )
-	{
-	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
-	}
-      if ( jloop == 127 )
+      if ( isdigit((int) env_stream[0]) )
 	{
-	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
-	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
-	  return (707);
+	  int unit;
+	  unit = atoi(env_stream);
+	  if ( unit < 1 || unit > 99 )
+	    Warning("Invalid number for GRPRS_STREAM: %d", unit);
+	  else if ( unit == 2 )
+	    grprsm = stderr;
+	  else if ( unit == 6 )
+	    grprsm = stdout;
+	  else
+	    {
+	      char filename[] = "unit.00";
+	      sprintf(filename, "%2.2d", unit);
+	      grprsm = fopen(filename, "w");
+	      if ( ! grprsm )
+		SysError("GRPRS_STREAM = %d", unit);
+	    }
 	}
       else
 	{
-	  binscale = 1 - jloop - nbpv;
+	  if ( env_stream[0] )
+	    {
+	      grprsm = fopen(env_stream, "w");
+	      if ( ! grprsm )
+		SysError("GRPRS_STREAM = %s", env_stream);
+	    }
 	}
     }
+  /*
+    Set P factor switch to default, user supplies the P factor.
+  */
+  nonoff = 0;
+  /*
+    Set abort flag to NO abort
+  */
+  noabort = 1;
+  /*
+    Mark common area values set by user.
+  */
+  lfirst = FALSE;
+  /*
+    Exhaustive use of all possible second-order packing methods
+    for HOPER='K'. Set to off.
+  */
+  num2ok  = 0;
+  /*
+    Use of extended second-order packing methods for grid-point
+    encoding (HOPER='C' and 'K'). Set to on.
+  */
+  next2o  = 1;
+  /*
+    Use of non-local second-order packing methods for grid-point
+    encoding (HOPER='C' and 'K'). Set to on.
+  */
+  nloc2o  = 1;
+  /*
+    Use of (all valid) sub-centre values for ECMWF fields encoding .
+    encoding. Set to off.
+  */
+  nsubce  = 0;
+}
 
-  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
-  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
+/* pack 8-bit bytes from 64-bit words to a packed buffer */
+/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (unsigned char) up[i]; */
 
-  if ( binscale != 0 )
-    {
-      if ( binscale < 0 )
-	{
-	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
-	}
-      else
-	{
-	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
-	}
+long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc)
+{
+#if defined (CRAY)
+  (void) _pack(up, cp, bc, tc);
+#else
+  U_BYTEORDER;
+  unsigned char *cp0;
+  unsigned INT64 upi, *up0, *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
+  long head, trail, inner, i, j;
+  long ipack = sizeof(INT64);
+  
+  /* Bytes until first word boundary in destination buffer */
 
-      if ( binscale < 0 ) factor =     intpow2(-binscale);
-      else                factor = 1.0/intpow2( binscale);
-    }
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
 
-  ref2ibm(&zref, BitsPerInt);
+  inner = bc - head;
 
-  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
-  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
-  if ( binscale < 0 ) binscale = 32768 - binscale;
-  Put2Byte(binscale);         /*  4-5 Scale factor             */
-  Put1Real(zref);             /*  6-9 Reference value          */
-  Put1Byte(nbpv);             /*   10 Packing size             */
+  /* Trailing bytes which do not make a full word */
 
-  if ( lspherc )
+  trail = inner & (ipack-1);
+
+  /* Number of bytes/words to be processed in fast loop */
+
+  inner -= trail;
+  inner /= ipack;
+
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+  ip4 = ip0 + 4;
+  ip5 = ip0 + 5;
+  ip6 = ip0 + 6;
+  ip7 = ip0 + 7;
+
+  up0 = (unsigned INT64 *) (cp + head);
+
+  /* Here we should process any bytes until the first word boundary 
+   * of our destination buffer 
+   * That code is missing so far  because our output buffer is 
+   * word aligned by FORTRAN 
+   */
+
+  j = 0;
+
+  if ( IS_BIGENDIAN() )
     {
-      if ( lcomplex )
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
 	{
-	  int jup = isubset;
-	  int ioff = z + bds_ext;
-	  if ( ioff > 0xFFFF ) ioff = 0;
-	  Put2Byte(ioff);
-	  Put2Int(isec4[16]);
-	  Put1Byte(jup);
-	  Put1Byte(jup);
-	  Put1Byte(jup);
-	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real(data[i]);
+	  upi =             (   ip0[j]          << 56 ) 
+	                 |  ( ( ip1[j] & 0xFF ) << 48 )
+	                 |  ( ( ip2[j] & 0xFF ) << 40 )
+	                 |  ( ( ip3[j] & 0xFF ) << 32 )
+	                 |  ( ( ip4[j] & 0xFF ) << 24 ) ;
+	  up0[i] = upi   |  ( ( ip5[j] & 0xFF ) << 16 )
+	                 |  ( ( ip6[j] & 0xFF ) <<  8 )
+	                 |    ( ip7[j] & 0xFF ) ;
+	  j += ipack;
 	}
-      else
+    }
+  else
+    {
+      for ( i = 0 ; i < inner ; i++ )
 	{
-	  Put1Real(data[0]);
+	  upi =             (   ip7[j]          << 56 ) 
+	                 |  ( ( ip6[j] & 0xFF ) << 48 )
+                         |  ( ( ip5[j] & 0xFF ) << 40 )
+                         |  ( ( ip4[j] & 0xFF ) << 32 )
+                         |  ( ( ip3[j] & 0xFF ) << 24 ) ;
+	  up0[i] = upi   |  ( ( ip2[j] & 0xFF ) << 16 )
+                         |  ( ( ip1[j] & 0xFF ) <<  8 )
+                         |    ( ip0[j] & 0xFF ) ;
+	  j += ipack;
 	}
     }
 
-  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
+  cp0 = (unsigned char *) ( up0 + inner );
+  if ( trail > 0 )
+    {
+      up0[inner] = 0;
+      for ( i = 0 ; i < trail ; i ++ )
+	{
+	  *cp0 = (unsigned char) ip0[ipack*inner+i];
+	  cp0++;
+	}
+    }
 
-#if  defined  (_ARCH_PWR6)
-  encode_double_array_unrolled(nbpv, PackStart, datasize, lGrib, data, zref, factor, &z);
-#else
-  encode_double_array_byte    (nbpv, PackStart, datasize, lGrib, data, zref, factor, &z);
+  if ( tc != -1 )
+    {
+      bc++;
+      *cp0 = (unsigned char) tc;
+    }
 #endif
-
-  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
-
-  *gribLen = z;
-
-  return (0);
+  return (bc);
 }
 
+/* unpack 8-bit bytes from a packed buffer with 64-bit words */
+/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT64) cp[i]; */
 
-void gribEncode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		int kleng, int *kword, int efunc, int *kret)
+long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc)
 {
-  long gribLen = 0; /* Counter of GRIB length for output */
-  long isLen, pdsLen;
-  GRIBPACK *lpds;
-  unsigned char *CGrib;
-  long fsec4size = 0;
-  int numBytes;
-  int bmsIncluded;
-  size_t len;
-  GRIBPACK *lGrib;
-  long datstart, datsize, bdsstart;
-  int status = 0;
+  U_BYTEORDER;
+  const unsigned char *cp0;
+  unsigned INT64 *up0;
+  unsigned INT64 *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
+  long head, trail, inner, i, j;
+  long offset;
+  long ipack = sizeof(INT64);
 
-  grsdef();
+  UNUSED(tc);
 
-  CGrib = (unsigned char *) kgrib;
+  /* Bytes until first word boundary in source buffer */
 
-  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
+  if ( head > bc ) head = bc;
 
-  /* set max header len */
-  len = 16384;
+  inner = bc - head;
 
-  /* add data len */
-  numBytes = (ISEC4_NumBits+7)>>3;
+  /* Trailing bytes which do not make a full word */
+ 
+  trail = inner & (ipack-1);
+ 
+  /* Number of bytes/words to be processed in fast loop */
 
-  len += numBytes*klenp;
+  inner -= trail;
+  inner /= ipack;
 
-  /* add bitmap len */
-  if ( bmsIncluded ) len += (klenp+7)>>3;
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+  ip4 = ip0 + 4;
+  ip5 = ip0 + 5;
+  ip6 = ip0 + 6;
+  ip7 = ip0 + 7;
 
-#if defined (VECTORCODE)
-  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
-  if ( lGrib == NULL ) SysError("No Memory!");
-#else
-  lGrib = CGrib;
-#endif
+  up0 = (unsigned INT64 *) (cp + head);
 
-  isLen = 8;
-  encodeIS(lGrib, &gribLen);
-  lpds = &lGrib[isLen];
-  pdsLen = getPdsLen(isec1);
+  /* Process any bytes until the first word boundary 
+   * of our source buffer 
+   */
+  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT64) cp[i];
 
-  encodePDS(lpds, pdsLen,  isec1);
-  gribLen += pdsLen;
-  /*
-  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
+  j = 0;
+
+  if ( IS_BIGENDIAN() )
     {
-      static int lwarn_cplx = TRUE;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip0[j] = (up0[i] >> 56) & 0xFF;
+	  ip1[j] = (up0[i] >> 48) & 0xFF;
+	  ip2[j] = (up0[i] >> 40) & 0xFF;
+	  ip3[j] = (up0[i] >> 32) & 0xFF;
+	  ip4[j] = (up0[i] >> 24) & 0xFF;
+	  ip5[j] = (up0[i] >> 16) & 0xFF;
+	  ip6[j] = (up0[i] >>  8) & 0xFF;
+	  ip7[j] = (up0[i])       & 0xFF;
 
-      if ( lwarn_cplx )
-	Message("Complex packing of spectral data unsupported, using simple packing!");
+	  j += ipack;
+	}
+    }
+  else
+    {
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip7[j] = (up0[i] >> 56) & 0xFF;
+	  ip6[j] = (up0[i] >> 48) & 0xFF;
+	  ip5[j] = (up0[i] >> 40) & 0xFF;
+	  ip4[j] = (up0[i] >> 32) & 0xFF;
+	  ip3[j] = (up0[i] >> 24) & 0xFF;
+	  ip2[j] = (up0[i] >> 16) & 0xFF;
+	  ip1[j] = (up0[i] >>  8) & 0xFF;
+	  ip0[j] = (up0[i])       & 0xFF;
 
-      isec2[5] = 1;
-      isec4[3] = 0;
+	  j += ipack;
+	}
+    }
 
-      lwarn_cplx = FALSE;
+  if ( trail > 0 )
+    {
+      offset = head + ipack*inner;
+      cp0 = cp + offset;
+      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT64) cp0[i];
     }
-  */
-  encodeGDS(lGrib, &gribLen, isec2, fsec2);
   /*
-    ----------------------------------------------------------------
-    BMS Bit-Map Section Section (Section 3)
-    ----------------------------------------------------------------
-  */ 
-  if ( bmsIncluded )
+  if ( tc != -1 ) {
+    bc++;
+    *cp0 = (unsigned char) tc;
+  }
+  */
+  return (bc);
+}
+
+/* pack 8-bit bytes from 32-bit words to a packed buffer */
+/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (char) up[i]; */
+
+#if  defined  (INT32)
+long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
+{
+  U_BYTEORDER;
+  unsigned char *cp0;
+  unsigned INT32 *up0, *ip0, *ip1, *ip2, *ip3;
+  long head, trail, inner, i, j;
+  long ipack = sizeof(INT32);
+  
+  /* Bytes until first word boundary in destination buffer */
+
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
+
+  inner = bc - head;
+
+  /* Trailing bytes which do not make a full word */
+
+  trail = inner & (ipack-1);
+
+  /* Number of bytes/words to be processed in fast loop */
+
+  inner -= trail;
+  inner /= ipack;
+
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+
+  up0 = (unsigned INT32 *) (cp + head);
+
+  /* Here we should process any bytes until the first word boundary 
+   * of our destination buffer 
+   * That code is missing so far  because our output buffer is 
+   * word aligned by FORTRAN 
+   */
+
+  j = 0;
+
+  if ( IS_BIGENDIAN() )
     {
-      encodeBMS(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  up0[i] =          (   ip0[j]          << 24 ) 
+	                 |  ( ( ip1[j] & 0xFF ) << 16 )
+	                 |  ( ( ip2[j] & 0xFF ) <<  8 )
+	                 |    ( ip3[j] & 0xFF ) ;
+	  j += ipack;
+	}
     }
   else
     {
-      fsec4size = ISEC4_NumValues;
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  up0[i] =          (   ip3[j]          << 24 ) 
+	                 |  ( ( ip2[j] & 0xFF ) << 16 )
+                         |  ( ( ip1[j] & 0xFF ) <<  8 )
+                         |    ( ip0[j] & 0xFF ) ;
+	  j += ipack;
+	}
     }
 
-  bdsstart = gribLen;
-  status = encodeBDS(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
-		     isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
-  if ( status )
+  cp0 = (unsigned char *) ( up0 + inner );
+  if ( trail > 0 )
     {
-      *kret = status;
-      return;
+      up0[inner] = 0;
+      for ( i = 0 ; i < trail ; i ++ )
+	{
+	  *cp0 = (unsigned char) ip0[ipack*inner+i];
+	  cp0++;
+	}
     }
 
-  encodeES(lGrib, &gribLen, bdsstart);
-
-  if ( (size_t) gribLen > kleng*sizeof(int) )
-    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
+  if ( tc != -1 )
+    {
+      bc++;
+      *cp0 = (unsigned char) tc;
+    }
 
-#if defined (VECTORCODE)
-  if ( (size_t) gribLen > len )
-    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
+  return (bc);
+}
+#endif
 
-  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
+/* unpack 8-bit bytes from a packed buffer with 32-bit words */
+/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT32) cp[i]; */
 
-  free(lGrib);
-#endif
+#if  defined  (INT32)
+long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
+{
+  U_BYTEORDER;
+  const unsigned char *cp0;
+  unsigned INT32 *up0;
+  unsigned INT32 *ip0, *ip1, *ip2, *ip3;
+  long head, trail, inner, i, j;
+  long offset;
+  long ipack = sizeof(INT32);
 
-  ISEC0_GRIB_Len     = gribLen;
-  ISEC0_GRIB_Version = 1;
+  UNUSED(tc);
 
-  *kword = gribLen / sizeof(int);
-  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+  /* Bytes until first word boundary in source buffer */
 
-  *kret = status;
-}
-#include <string.h>
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
+  if ( head > bc ) head = bc;
 
+  inner = bc - head;
 
+  /* Trailing bytes which do not make a full word */
+ 
+  trail = inner & (ipack-1);
+ 
+  /* Number of bytes/words to be processed in fast loop */
 
+  inner -= trail;
+  inner /= ipack;
 
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
 
-int gribVersion(unsigned char *is, size_t buffersize)
-{
-  if ( buffersize < 8 )
-    Error("Buffer too small (current size %d)!", (int) buffersize);
+  up0 = (unsigned INT32 *) (cp + head);
 
-  return (GRIB_EDITION(is));
-}
+  /* Process any bytes until the first word boundary 
+   * of our source buffer 
+   */
+  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT32) cp[i];
 
-static 
-double GET_Real(unsigned char *grib)
-{
-  int iexp, imant;
+  j = 0;
 
-  iexp  = GET_UINT1(grib[0]);
-  imant = GET_UINT3(grib[1], grib[2], grib[3]);
+  if ( IS_BIGENDIAN() )
+    {
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip0[j] = (up0[i] >> 24) & 0xFF;
+	  ip1[j] = (up0[i] >> 16) & 0xFF;
+	  ip2[j] = (up0[i] >>  8) & 0xFF;
+	  ip3[j] = (up0[i])       & 0xFF;
 
-  return (decfp2(iexp, imant));
-}
+	  j += ipack;
+	}
+    }
+  else
+    {
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip3[j] = (up0[i] >> 24) & 0xFF;
+	  ip2[j] = (up0[i] >> 16) & 0xFF;
+	  ip1[j] = (up0[i] >>  8) & 0xFF;
+	  ip0[j] = (up0[i])       & 0xFF;
 
-static 
-int decodeIS(unsigned char *is, int *isec0, int *iret)
-{
-  int isLen = 0;
-  int grib1offset;
-  int lgrib = FALSE, lbudg = FALSE, ltide = FALSE;
+	  j += ipack;
+	}
+    }
 
+  if ( trail > 0 )
+    {
+      offset = head + ipack*inner;
+      cp0 = cp + offset;
+      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT32) cp0[i];
+    }
   /*
-    Octets 1 - 4 : The letters G R I B.
-    Four 8 bit fields.
-  */
-  /*
-    Check letters -> GRIB, BUDG or TIDE.
-  */
-  /*
-    Check that 'GRIB' is found where expected.
+  if ( tc != -1 ) {
+    bc++;
+    *cp0 = (unsigned char) tc;
+  }
   */
-  if ( GRIB_START(is) ) lgrib = TRUE;
+
+  return (bc);
+}
+#endif
+#include <stdio.h>
+
+void prtbin(int kin, int knbit, int *kout, int *kerr)
+{
   /*
-    ECMWF pseudo-grib data uses 'BUDG' and 'TIDE'.
+
+    Produces a decimal number with ones and zeroes
+    corresponding to the ones and zeroes of the input
+    binary number.
+    eg input number 1011 binary, output number 1011 decimal.
+
+
+    Input Parameters:
+    
+       kin   - Integer variable containing binary number.
+
+       knbit - Number of bits in binary number.
+
+    Output Parameters:
+
+       kout  - Integer variable containing decimal value
+               with ones and zeroes corresponding to those of
+	       the input binary number.
+
+       kerr  - 0, If no error.
+               1, Number of bits in binary number exceeds
+	          maximum allowed or is less than 1.
+
+
+    Converted from EMOS routine PRTBIN.
+
+       Uwe Schulzweida   MPIfM   01/04/2001
+
   */
-  if ( BUDG_START(is) ) lbudg = TRUE;
-  if ( TIDE_START(is) ) ltide = TRUE;
+  int idec;
+  int ik;
+  int itemp;
+  int j;
+
   /*
-    Data is not GRIB or pseudo-grib.
+    Check length of binary number to ensure decimal number
+    generated will fit in the computer word - in this case will
+    it fit in a Cray 48 bit integer?
   */
-  if ( lgrib == FALSE && lbudg == FALSE && ltide == FALSE )
+  if ( knbit < 1 || knbit > 14 )
     {
-      *iret = 305;
-      gprintf(__func__, "Input data is not GRIB or pseudo-grib.");
-      gprintf(__func__, "Return code = %d", *iret);
+      *kerr = 1;
+      printf(" prtbin : Error in binary number length - %3d bits.\n", knbit);
+      return;
     }
-  if ( lbudg == TRUE || ltide == TRUE )
+  else
+    *kerr = 0;
+  /*
+    -----------------------------------------------------------------
+    Section 1. Generate required number.
+    -----------------------------------------------------------------
+  */
+  *kout = 0;
+  ik    = kin;
+  idec  = 1;
+
+  for ( j = 0; j < knbit; j++ )
     {
-      *iret = 305;
-      gprintf(__func__, "Pseudo-grib data unsupported.");
-      gprintf(__func__, "Return code = %d", *iret);
+      itemp = ik - ( (ik/2)*2 );
+      *kout = (*kout) + itemp * idec;
+      ik    = ik / 2;
+      idec  = idec * 10;
     }
 
+  return;
+}
+
+
+void ref2ibm(double *pref, int kbits)
+{
   /*
-    Octets 5 - 7 : Length of message.
-    One 24 bit field.
-  */
-  ISEC0_GRIB_Len = GRIB1_SECLEN(is);
-  /*
-    Octet 8 : GRIB Edition Number.
-    One 8 bit field.
-  */
-  ISEC0_GRIB_Version = GRIB_EDITION(is);
 
-  if ( ISEC0_GRIB_Version > 1 )
-    Error("GRIB version %d unsupported!", ISEC0_GRIB_Version);
+    Purpose:
+    --------
 
-  grib1offset = ISEC0_GRIB_Version * 4;
+    Code and check reference value in IBM format
 
-  isLen = 4 + grib1offset;
+    Input Parameters:
+    -----------------
 
-  return (isLen);
-}
+    pref       - Reference value
+    kbits      - Number of bits per computer word.
 
-static 
-void decodePDS_ECMWF_local_Extension_1(unsigned char *pds, int *isec1)
-{
-  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier       */
-  isec1[37] = GET_UINT1(pds[41]);         /* Class                      */
-  isec1[38] = GET_UINT1(pds[42]);         /* Type                       */
-  isec1[39] = GET_UINT2(pds[43],pds[44]); /* Stream                     */
-  /* isec1[40] = GET_UINT4(pds[45],pds[46],pds[47],pds[48]); */
-  memcpy((char*) &isec1[40], &pds[45], 4);
-  isec1[41] = GET_UINT1(pds[49]);         /* Forecast number            */
-  isec1[42] = GET_UINT1(pds[50]);         /* Total number of forecasts  */
-}
+    Output Parameters:
+    ------------------
 
-static 
-void decodePDS_DWD_local_Extension_254(unsigned char *pds, int *isec1)
-{
-  long i;
-  int isvn;
+    pref       - Reference value
 
-  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
-  for ( i = 0; i < 11; i++ ) 
-    { 
-      isec1[37+i] =  GET_UINT1(pds[41+i]);
-    } 
+    Method:
+    -------
 
-  isvn = GET_UINT2(pds[52],pds[53]);
-  
-  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
-  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
+    Codes in IBM format, then decides to ensure that reference 
+    value used for packing is not different from that stored
+    because of packing differences.
 
-}
+    Externals.
+    ----------
 
-static 
-void decodePDS_DWD_local_Extension_253(unsigned char *pds, int *isec1)
-{
-  long i;
-  int isvn;
+    confp3    - Encode into IBM floating point format.
+    decfp2    - Decode from IBM floating point format.
 
-  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
-  for ( i = 0; i < 11; i++ ) 
-    { 
-      isec1[37+i] =  GET_UINT1(pds[41+i]);
-    } 
+    Reference:
+    ----------
 
-  isvn = GET_UINT2(pds[52],pds[53]);
-  
-  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
-  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
-  isec1[50] =  GET_UINT1(pds[54]);         /* User id, specified by table          */
-  isec1[51] =  GET_UINT2(pds[55],pds[56]); /* Experiment identifier                */
-  isec1[52] =  GET_UINT2(pds[57],pds[58]); /* Ensemble identification by table     */
-  isec1[53] =  GET_UINT2(pds[59],pds[60]); /* Number of ensemble members           */
-  isec1[54] =  GET_UINT2(pds[61],pds[62]); /* Actual number of ensemble member     */
-  isec1[55] =  GET_UINT1(pds[63]);         /* Model major version number           */
-  isec1[56] =  GET_UINT1(pds[64]);         /* Model minor version number           */
+    None.
 
-}
+    Comments:
+    --------
 
-static 
-void decodePDS_MPIM_local_Extension_1(unsigned char *pds, int *isec1)
-{
-  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier            */
-  isec1[37] = GET_UINT1(pds[41]);         /* type of ensemble forecast       */
-  isec1[38] = GET_UINT2(pds[42],pds[43]); /* individual ensemble member      */
-  isec1[39] = GET_UINT2(pds[44],pds[45]); /* number of forecasts in ensemble */
-}
+    None.
 
-static 
-int decodePDS(unsigned char *pds, int *isec0, int *isec1)
-{
-  int pdsLen;
+    Author:
+    -------
 
-  pdsLen = PDS_Len;
+    J.D.Chambers     ECMWF      17:05:94
 
-  ISEC1_CodeTable      = PDS_CodeTable;
-  ISEC1_CenterID       = PDS_CenterID;
-  ISEC1_ModelID        = PDS_ModelID;
-  ISEC1_GridDefinition = PDS_GridDefinition;
-  ISEC1_Sec2Or3Flag    = PDS_Sec2Or3Flag;
-  ISEC1_Parameter      = PDS_Parameter;
-  ISEC1_LevelType      = PDS_LevelType;
+    Modifications:
+    --------------
 
-  if ( (ISEC1_LevelType !=  20) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_99)        && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)  && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)  && 
-       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)    && 
-       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)     && 
-       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)    && 
-       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) && 
-       (ISEC1_LevelType != 115) && 
-       (ISEC1_LevelType != 117) && 
-       (ISEC1_LevelType != 125) && 
-       (ISEC1_LevelType != 127) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_SEADEPTH)  && 
-       (ISEC1_LevelType != 210) )
-    {
-      ISEC1_Level1 = PDS_Level1;
-      ISEC1_Level2 = PDS_Level2;
-    }
-  else
-    {
-      ISEC1_Level1 = PDS_Level;
-      ISEC1_Level2 = 0;
-    }
+    Uwe Schulzweida   MPIfM   01/04/2001
 
-  /* ISEC1_Year        = PDS_Year; */
-  ISEC1_Month          = PDS_Month;
-  ISEC1_Day            = PDS_Day;
-  ISEC1_Hour           = PDS_Hour;
-  ISEC1_Minute         = PDS_Minute;
-  ISEC1_TimeUnit       = PDS_TimeUnit;
-  ISEC1_TimePeriod1    = PDS_TimePeriod1;
-  ISEC1_TimePeriod2    = PDS_TimePeriod2;
-  ISEC1_TimeRange      = PDS_TimeRange;
-  ISEC1_AvgNum         = PDS_AvgNum;
-  ISEC1_AvgMiss        = PDS_AvgMiss;
+    Convert to C from EMOS library version 130
 
-  if ( ISEC0_GRIB_Version == 1 )
-    {
-      ISEC1_Year           = PDS_Year;
-      ISEC1_Century        = PDS_Century;
-      ISEC1_SubCenterID    = PDS_Subcenter;
-      ISEC1_DecScaleFactor = PDS_DecimalScale;
-    }
-  else
-    {
-      int year;
-      year                 = GET_UINT1(pds[12]);
-      if ( year <= 100 )
-	{
-	  ISEC1_Year       = year;
-	  ISEC1_Century    = 1;
-	}
-      else
-	{
-	  ISEC1_Year       = year%100;
-	  ISEC1_Century    = 1 + (year-ISEC1_Year)/100;
-	}
-      ISEC1_SubCenterID    = 0;
-      ISEC1_DecScaleFactor = 0;
-    }
+  */
 
-  if ( ISEC1_Year < 0 )
-    {
-      ISEC1_Year    = -ISEC1_Year;
-      ISEC1_Century = -ISEC1_Century;
-    }
+  static int itrnd;
+  static int kexp, kmant;
+  static double ztemp, zdumm;
+  extern int CGRIBEX_Debug;
 
-  ISEC1_LocalFLag = 0;
-  if ( pdsLen > 28 )
-    {
-      int localextlen;
-      localextlen = pdsLen-28;
+  /* ----------------------------------------------------------------- */
+  /*   Section 1. Convert to and from IBM format.                      */
+  /* ----------------------------------------------------------------- */
 
-      if ( localextlen > 4000 )
-	{
-	  Warning("PDS larger than 4000 bytes not supported!");
-	}
-      else
-	{
-	  ISEC1_LocalFLag = 1;
+  /*  Convert floating point reference value to IBM representation. */
 
-	  if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	    {
-	      if ( pds[40] == 254 ) 
-		{
-		  decodePDS_DWD_local_Extension_254(pds, isec1);
-		}
-	      else if ( pds[40] == 253 )
-		{ 
-		  decodePDS_DWD_local_Extension_253(pds, isec1);
-		}
-	    }
-	  else if ( (ISEC1_CenterID    == 98 && ISEC1_LocalFLag ==  1) ||
-		    (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag ==  1) ||
-		    (ISEC1_CenterID    ==  7 && ISEC1_SubCenterID == 98) )
-	    {
-	      if ( pds[40] == 1 )
-		decodePDS_ECMWF_local_Extension_1(pds, isec1);
-	    }
-	  else if ( ISEC1_CenterID    == 252 && ISEC1_LocalFLag ==  1 )
-	    {
-	      if ( pds[40] == 1 )
-		decodePDS_MPIM_local_Extension_1(pds, isec1);	      
-	    }
-	  else
-	    {
-	      long i;
-	      for ( i = 0; i < localextlen; i++ )
-		{
-		  isec1[24+i] = pds[28+i];
-		}
-	    }
-	}
-    }
+  itrnd = 1;
+  zdumm = ztemp = *pref;
+  confp3(zdumm, &kexp, &kmant, kbits, itrnd);
 
-  return (pdsLen);
-}
+  if ( kexp == 0 && kmant == 0 ) return;
 
-static 
-int decodeGDS(unsigned char  *gds, int *isec0, int *isec2, double *fsec2, int *numGridVals, int dfunc)
-{
-  /* int imisng = 0; */
-  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
-  int  locnv = 0, locnl;
-  int  jlenl;
-  long i;
-  int iexp, imant;
-  int ipvpl, ipl;
-  int gdsLen = 0;
-#if defined (VECTORCODE)
-  unsigned char *igrib;
-  GRIBPACK *lgrib = NULL;
-  size_t lGribLen = 0;
-#endif
+  /*  Set reference value to that actually stored in the GRIB code. */
 
-  *numGridVals = 0;
+  *pref = decfp2(kexp, kmant);
 
-  memset(isec2, 0, 22*sizeof(int));
+  /*  If the nearest number which can be represented in */
+  /*  GRIB format is greater than the reference value,  */
+  /*  find the nearest number in GRIB format lower      */
+  /*  than the reference value.                         */
 
-  gdsLen = GDS_Len;
+  if ( ztemp < *pref )
+    {
+      /*  Convert floating point to GRIB representation */
+      /*  using truncation to ensure that the converted */
+      /*  number is smaller than the original one.      */
 
-  ipvpl = GDS_PVPL;
-  if ( ipvpl == 0 ) ipvpl = 0xFF;
+      itrnd = 0;
+      zdumm = *pref = ztemp;
+      confp3(zdumm, &kexp, &kmant, kbits, itrnd);
 
-  if ( ipvpl != 0xFF )
-    { /* Either vct or reduced grid */
-      if ( GDS_NV != 0 )
-	{ /* we have vct */
-	  VertCoorTab = TRUE;
-	  ipl =  4*GDS_NV + ipvpl - 1;
-	  if ( ipl < gdsLen )
-	    {
-	      ReducedGrid = TRUE;
-	    }
-	}
-      else
-	{
-	  VertCoorTab = FALSE;
-	  ReducedGrid = TRUE;
-	}
-      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
-    }
- 
-  if ( ISEC0_GRIB_Version == 0 )
-    {
-      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
-      else                   VertCoorTab = FALSE;
-    }
-  
-  if ( ReducedGrid )
-    {
-      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
-      jlenl = (gdsLen - locnl)  >> 1;
-      if ( jlenl == GDS_NumLat )
+      /*  Set reference value to that stored in the GRIB code. */
+
+      *pref = decfp2(kexp, kmant);
+
+      if ( ztemp < *pref )
 	{
-	  *numGridVals = 0;
-	  ISEC2_Reduced = TRUE;
-	  for ( i = 0; i < jlenl; i++ )
+	  if ( CGRIBEX_Debug )
 	    {
-	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
-	      *numGridVals += ISEC2_RowLon(i);
+	      Message("Reference value error.");
+	      Message("Notify Met.Applications Section.");
+	      Message("ZTEMP = ", ztemp);
+	      Message("PREF = ", pref);
 	    }
-	}
-      else
-	{
-	  ReducedGrid = FALSE;
+	  *pref = ztemp;
 	}
     }
 
-  ISEC2_GridType = GDS_GridType;
+  return;
+} /* ref2ibm */
+#include <string.h>
 
+
+int correct_bdslen(int bdslen, long recsize, long gribpos)
+{
   /*
-     Gaussian grid definition.
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
   */
-  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
-       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
-       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-    {
-      ISEC2_NumLat    = GDS_NumLat;
-      if ( ! ReducedGrid )
-	{
-	  ISEC2_NumLon = GDS_NumLon;
-	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-	}
-      ISEC2_FirstLat  = GDS_FirstLat;
-      ISEC2_FirstLon  = GDS_FirstLon;
-      ISEC2_ResFlag   = GDS_ResFlag;
-      ISEC2_LastLat   = GDS_LastLat;
-      ISEC2_LastLon   = GDS_LastLon;
-      ISEC2_LonIncr   = GDS_LonIncr;
+  if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
+  return (bdslen);
+}
 
-      ISEC2_NumPar    = GDS_NumPar;
-      ISEC2_ScanFlag  = GDS_ScanFlag;
-      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-	{
-	  ISEC2_LatSP     = GDS_LatSP;
-	  ISEC2_LonSP     = GDS_LonSP;
-	  FSEC2_RotAngle  = GDS_RotAngle;
-	}
-      /*
-	if ( Lons != Longitudes || Lats != Latitudes )
-	Error("Latitude/Longitude Conflict");
-      */
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
-    {
-      /*
-      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
-      */
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
+
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
+		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize)
+{
+  unsigned char *pds, *gds, *bms, *bds;
+  unsigned char *bufpointer, *is, *section;
+  int gribversion, grib1offset;
+  long gribsize = 0, recsize;
+  int bdslen;
+
+  *gribrecsize = 0;
+  *pdsp = NULL;
+  *gdsp = NULL;
+  *bmsp = NULL;
+  *bdsp = NULL;
+
+  section = gribbuffer;
+  is = gribbuffer;
+  if ( ! GRIB_START(section) )
     {
-      /*
-      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
-      */
+      fprintf(stderr, "Wrong GRIB indicator section: found >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+
+  recsize = gribrec_len(section[4], section[5], section[6]);
+
+  gribversion = GRIB_EDITION(section);
+  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
+
+  if ( gribversion == 1 )
+    grib1offset = 4;
+  else
+    grib1offset = 0;
+
+  pds = is + 4 + grib1offset;
+  bufpointer = pds + PDS_Len;
+  gribsize += 4 + grib1offset + PDS_Len;
+
+  if ( PDS_HAS_GDS )
     {
-      ISEC2_NumLon    = GDS_NumLon;
-      ISEC2_NumLat    = GDS_NumLat;
-      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-      ISEC2_FirstLat  = GDS_FirstLat;
-      ISEC2_FirstLon  = GDS_FirstLon;
-      ISEC2_ResFlag   = GDS_ResFlag;
-      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
-      ISEC2_Lambert_dx    = GDS_Lambert_dx;
-      ISEC2_Lambert_dy    = GDS_Lambert_dy;
-      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
-      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
-      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
-      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
-      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
-      ISEC2_ScanFlag      = GDS_ScanFlag;
+      gds = bufpointer;
+      bufpointer += GDS_Len;
+      gribsize += GDS_Len;
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
+  else
     {
-      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
-      ISEC2_PentaK  = GDS_PentaK;
-      ISEC2_PentaM  = GDS_PentaM;
-      ISEC2_RepType = GDS_RepType;
-      ISEC2_RepMode = GDS_RepMode;
-      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
-      isec2[ 6] = 0;
-      isec2[ 7] = 0;
-      isec2[ 8] = 0;
-      isec2[ 9] = 0;
-      isec2[10] = 0;
-      /*
-      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
-      */
+      gds = NULL;
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+
+  if ( PDS_HAS_BMS )
     {
-      ISEC2_GME_NI2    = GDS_GME_NI2;
-      ISEC2_GME_NI3    = GDS_GME_NI3;
-      ISEC2_GME_ND     = GDS_GME_ND;
-      ISEC2_GME_NI     = GDS_GME_NI;
-      ISEC2_GME_AFlag  = GDS_GME_AFlag;
-      ISEC2_GME_LatPP  = GDS_GME_LatPP;
-      ISEC2_GME_LonPP  = GDS_GME_LonPP;
-      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
-      ISEC2_GME_BFlag  = GDS_GME_BFlag;
-      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
-      /*
-      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
-      */
+      bms = bufpointer;
+      bufpointer += BMS_Len;
+      gribsize += BMS_Len;
     }
   else
     {
-      ISEC2_NumLon = GDS_NumLon;
-      ISEC2_NumLat = GDS_NumLat;
-      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-      Message("Gridtype %d unsupported", ISEC2_GridType);
+      bms = NULL;
     }
 
-  /*    vertical coordinate parameters for hybrid levels.     */
-  /*    get number of vertical coordinate parameters, if any. */
+  bds = bufpointer;
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, gribsize);
+  bufpointer += bdslen;
+  gribsize += bdslen;
+  gribsize += 4;
 
-  ISEC2_NumVCP = 0;
+  *pdsp = pds;
+  *gdsp = gds;
+  *bmsp = bms;
+  *bdsp = bds;
 
-  isec2[17] = 0;
-  isec2[18] = 0;
+  *gribrecsize = gribsize;
 
-  if ( VertCoorTab == TRUE )
+  if ( gribbufsize < gribsize )
     {
-      if ( ISEC0_GRIB_Version  == 0 )
-	{
-	  locnv = 32;
-	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
-	}
-      else
-	{
-	  locnv = GDS_PVPL - 1;
-	  ISEC2_NumVCP = GDS_NV;
-	}
-#if defined (SX)
-      lGribLen = 4*ISEC2_NumVCP;	      
-      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
-
-      igrib = &gds[locnv];
-      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
-      for ( i = 0; i < ISEC2_NumVCP; i++ )
-	{
-	  iexp   = (lgrib[4*i  ]);
-	  imant  =((lgrib[4*i+1]) << 16) +
-	          ((lgrib[4*i+2]) <<  8) +
-	           (lgrib[4*i+3]);
-	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
-	}
+      fprintf(stderr, "Length of GRIB message is inconsistent (grib_buffer_size=%ld < grib_record_size=%ld)!\n", gribbufsize, gribsize);
+      return (1);
+    }
 
-      free(lgrib);
-#else
-      for ( i = 0; i < ISEC2_NumVCP; i++ )
-	{
-	  iexp   = (gds[locnv+4*i  ]);
-	  imant  =((gds[locnv+4*i+1]) << 16) +
-	          ((gds[locnv+4*i+2]) <<  8) +
-	           (gds[locnv+4*i+3]);
-	  fsec2[10+i] = decfp2(iexp,imant);
-	}
-#endif
+  /* end section - "7777" in ascii */
+  if ( !GRIB_FIN(bufpointer) )
+    {
+      fprintf(stderr, "Missing GRIB end section: found >%c%c%c%c<\n",
+	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
+      return (-2);
     }
 
-  return (gdsLen);
+  return (0);
 }
 
-static
-int decodeBDS(int decscale, unsigned char *bds, int *isec2, int *isec4, 
-	      double *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
-{
-  unsigned char *igrib;
-  int lspherc = FALSE, lcomplex = FALSE;
-  int lcompress;
-  int jup, kup, mup;
-  int locnd;
-  long jlend;
-  long i;
-  int bds_flag, jscale, imiss;
-  int bds_ubits;
-  int ioff = 0;
-  int iexp, imant;
-  int zoff;
-  int bds_head = 11;
-  double fmin = 0., zscale = 0.;
-  double *fpdata = fsec4;
-  int bdsLen;
-  extern int CGRIBEX_Fix_ZSE;
 
-  *iret = 0;
-  igrib = bds;
+int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
+		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
+		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp)
+{
+  unsigned char *section;
+  long sec_len;
+  int sec_num;
+  int gribversion;
+  int i, msec;
+  long gribsize;
+  long grib_len = 0;
 
-  memset(isec4, 0, 42*sizeof(int));
+  UNUSED(gribbufsize);
 
-  /* get length of binary data block. */
+  *idsp = NULL;
+  *lusp = NULL;
+  *gdsp = NULL;
+  *pdsp = NULL;
+  *drsp = NULL;
+  *bmsp = NULL;
+  *bdsp = NULL;
 
-  bdsLen = BDS_Len;
-  /*
-    If a very large product, the section 4 length field holds
-    the number of bytes in the product after section 4 upto
-    the end of the padding bytes.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
+  section = gribbuffer;
+  sec_len = 16;
 
-  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
+  if ( !GRIB_START(section) )
+    {
+      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
+    }
 
-  bds_flag = BDS_Flag;
+  gribversion = GRIB_EDITION(section);
+  if ( gribversion != 2 )
+    {
+      fprintf(stderr, "wrong GRIB version %d\n", gribversion);
+      return (-1);      
+    }
 
-  /* 0------- grid point           */
-  /* 1------- spherical harmonics  */
+  gribsize = 0;
+  for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | section[8+i];
 
-  lspherc = bds_flag >> 7;
+  grib_len += sec_len;
+  section  += sec_len;
 
-  if ( lspherc ) isec4[2] = 128;
-  else           isec4[2] = 0;
+  /* section 1 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "ids %d %ld\n", sec_num, sec_len);
 
-  /* -0------  simple packing */
-  /* -1------ complex packing */
+  if ( sec_num != 1 )
+    {
+      fprintf(stderr, "Unexpected section1 number %d\n", sec_num);
+      return (-1);
+    }
 
-  lcomplex = (bds_flag >> 6)&1;
+  *idsp = section;
 
-  if ( lcomplex ) isec4[3] = 64;
-  else            isec4[3] =  0;
-
-  /* ---0---- No additional flags */
-  /* ---1---- No additional flags */
+  grib_len += sec_len;
+  section  += sec_len;
 
-  lcompress = (bds_flag >> 4)&1; /* compress */
+  /* section 2 and 3 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "lus %d %ld\n", sec_num, sec_len);
 
-  if ( lcompress )
-    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
-  else
-    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+  if ( sec_num == 2 )
+    {
+      *lusp = section;
 
-  /* ----++++ number of unused bits at end of section) */
+      grib_len += sec_len;
+      section  += sec_len;
 
-  bds_ubits = bds_flag & 0xF;
-  
-  /* scale factor (2 bytes) */;
+      /* section 3 */
+      sec_len = GRIB2_SECLEN(section);
+      sec_num = GRIB2_SECNUM(section);
+      //fprintf(stderr, "gds %d %ld\n", sec_num, sec_len);
 
-  jscale = BDS_BinScale;
+      *gdsp = section;
+    }
+  else if ( sec_num == 3 )
+    {
+      *gdsp = section;
+    }
+  else
+    {
+      fprintf(stderr, "Unexpected section3 number %d\n", sec_num);
+      return (-1);
+    }
 
-  /* check for missing data indicators. */
+  grib_len += sec_len;
+  section  += sec_len;
 
-  iexp  = bds[ 6];
-  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
+  /* section 4 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "pds %d %ld\n", sec_num, sec_len);
 
-  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
+  if ( sec_num != 4 )
+    {
+      fprintf(stderr, "Unexpected section4 number %d\n", sec_num);
+      return (-1);
+    }
 
-  /* convert reference value and scale factor. */
+  *pdsp = section;
 
-  if ( ! (dfunc == 'J') )
-    if ( imiss == 0 )
-      {
-	fmin = BDS_RefValue;
-	
-	if ( jscale < 0 )
-	  zscale = 1.0/intpow2(-jscale);
-	else
-	  zscale = intpow2(jscale);
-      }
+  grib_len += sec_len;
+  section  += sec_len;
 
-  /* get number of bits in each data value. */
+  /* section 5 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "drs %d %ld\n", sec_num, sec_len);
 
-  ISEC4_NumBits = BDS_NumBits;
+  if ( sec_num != 5 )
+    {
+      fprintf(stderr, "Unexpected section5 number %d\n", sec_num);
+      return (-1);
+    }
 
-  /* octet number of start of packed data */
-  /* calculated from start of block 4 - 1 */
+  *drsp = section;
 
-  locnd = zoff + bds_head;
+  grib_len += sec_len;
+  section  += sec_len;
 
-  /* if data is in spherical harmonic form, distinguish   */
-  /* between simple/complex packing (lcomplex = 0/1)      */
+  /* section 6 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "bms %d %ld\n", sec_num, sec_len);
 
-  if ( lspherc )
+  if ( sec_num != 6 )
     {
-      if ( !lcomplex )
-	{
-	  /*    no unpacked binary data present */
-
-	  jup = kup = mup = 0;
+      fprintf(stderr, "Unexpected section6 number %d\n", sec_num);
+      return (-1);
+    }
 
-	  /*    octet number of start of packed data */
-	  /*    calculated from start of block 4 - 1 */
+  *bmsp = section;
 
-	  ioff   = 1;
-	  locnd += 4*ioff;  /* RealCoef */
+  grib_len += sec_len;
+  section  += sec_len;
 
-	  /*    get real (0,0) coefficient in grib format and     */
-	  /*    convert to floating point.                        */
+  /* section 7 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "bds %d %ld\n", sec_num, sec_len);
 
-	  if ( dfunc != 'J' )
-	    {
-	      if ( imiss ) *fpdata++ = 0.0;
-	      else         *fpdata++ = BDS_RealCoef;
-	    }
-	}
-      else /* complex packed spherical harmonics */
-	{
-	  isec4[15] = BDS_PackData;
-	  /*    scaling factor */
-	  isec4[16] = BDS_Power;
+  if ( sec_num != 7 )
+    {
+      fprintf(stderr, "Unexpected section7 number %d\n", sec_num);
+      return (-1);
+    }
 
-	  /*    pentagonal resolution parameters of the */
-	  /*    unpacked section of data field          */
+  *bdsp = section;
 
-	  jup = bds[zoff+15];
-	  kup = bds[zoff+16];
-	  mup = bds[zoff+17];
+  grib_len += sec_len;
+  section  += sec_len;
 
-	  isec4[zoff+17] = jup;
-	  isec4[zoff+18] = kup;
-	  isec4[zoff+19] = mup;
+  /* skip multi GRIB sections */
+  msec = 1;
+  while ( !GRIB_FIN(section) )
+    {
+      sec_len = GRIB2_SECLEN(section);
+      sec_num = GRIB2_SECNUM(section);
 
-	  /*    unpacked binary data */
+      if ( sec_num < 1 || sec_num > 7 ) break;
 
-	  locnd += 4; /* 2 + power */
-	  locnd += 3; /* j, k, m   */
-	  ioff   = (jup+1)*(jup+2);
+      if ( sec_num == 7 )
+	fprintf(stderr, "Skipped unsupported multi GRIB section %d!\n", ++msec);
 
-	  if ( dfunc != 'J' )
-	    for ( i = 0; i < ioff; i++ )
-	      {
-		iexp   = (bds[locnd+4*i  ]);
-		imant  =((bds[locnd+4*i+1]) << 16) +
-		        ((bds[locnd+4*i+2]) <<  8) +
-		         (bds[locnd+4*i+3]);
+      if ( (grib_len + sec_len) > gribsize ) break;
 
-		if ( imiss ) *fpdata++ = 0.0;
-		else         *fpdata++ = decfp2(iexp,imant);
-	      }
-	  
-	  locnd += 4*ioff;  /* RealCoef */
-	}
+      grib_len += sec_len;
+      section  += sec_len;
     }
-  else
+
+  /* end section - "7777" in ASCII */
+  if ( !GRIB_FIN(section) )
     {
-      if ( lcomplex )
-	{
-	  *iret = 1999;
-	  gprintf(__func__, " Second order packed grids unsupported!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
-	}
+      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-2);
     }
 
-  /* Decode data values to floating point and store in fsec4.  */
-  /* First calculate the number of data values.                */
-  /* Take into account that spherical harmonics can be packed  */
-  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
-
-  jlend = bdsLen - locnd;
+  return (0);
+}
 
-  if ( ISEC4_NumBits == 0 )
-    {
-      if ( jlend > 1 )
-	{
-	  *iret = 2001;
-	  gprintf(__func__, " Number of bits per data value = 0!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
-	}
 
-      if ( numGridVals == 0 )
-	{
-	  *iret = 2002;
-	  gprintf(__func__, " Constant field unsupported for this grid type!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
-	}
+int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
+			int *intnum, float *fltnum, off_t *bignum)
+{
+  unsigned char *pds, *gds, *bms, *bds;
+  unsigned char *bufpointer, *is, *section;
+  int gribversion, grib1offset;
+  long gribsize = 0;
+  off_t dpos, bpos = 0;
+  int bdslen;
+  float bsf;
 
-      jlend = numGridVals;
-      jlend -= ioff;
-    }
-  else
+  section = gribbuffer;
+  is = gribbuffer;
+  if ( ! GRIB_START(section) )
     {
-      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
+      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
     }
 
-  ISEC4_NumValues        = jlend + ioff;
-  ISEC4_NumNonMissValues = 0;
-
-  if ( lcompress )
-    {
-      size_t len;
-
-      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
-	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
-      else
-        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-
-      ISEC4_NumValues = len*8/ISEC4_NumBits;
+  gribversion = GRIB_EDITION(section);
+  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
 
-      if ( lspherc )
-	{
-	  if ( lcomplex )
-	    ISEC4_NumValues += ioff;
-	  else
-	    ISEC4_NumValues++;
-	}
-    }
+  if ( gribversion == 1 )
+    grib1offset = 4;
+  else
+    grib1offset = 0;
 
-  if ( dfunc == 'J' ) return (bdsLen);
+  pds = is + 4 + grib1offset;
+  bufpointer = pds + PDS_Len;
+  gribsize += 4 + grib1offset + PDS_Len;
 
-  /* check length of output array. */
-  
-  if ( ISEC4_NumValues > fsec4len )
+  if ( PDS_HAS_GDS )
     {
-      *iret = 710;
-      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
-      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
-      gprintf(__func__, " Return code =  %d", *iret);
-      return (0);
+      gds = bufpointer;
+      bufpointer += GDS_Len;
+      gribsize += GDS_Len;
     }
-
-  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(double));
   else
     {
-      igrib += locnd;
-
-#if  defined  (_ARCH_PWR6)
-      decode_double_array_unrolled(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
-#else
-      decode_double_array_byte    (igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
-#endif
+      gds = NULL;
     }
 
-  if ( lspherc && lcomplex )
+  if ( PDS_HAS_BMS )
     {
-      int pcStart, pcScale;
-      pcStart = isec4[19];
-      pcScale = isec4[16];
-      scatterComplex(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
-      scaleComplex(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
-    }
+      bms = bufpointer;
+      bufpointer += BMS_Len;
 
-  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
-    if ( lspherc && !lcomplex )
-      {
-        /* 20100705: Fix ZeroShiftError - Edi Kirk */
-	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
-	  {
-	    double zserr = fsec4[1];
-	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
-	  }
-      }
+      bpos = recpos + gribsize + 6;
 
-  if ( decscale )
+      gribsize += BMS_Len;
+    }
+  else
     {
-      double scale = pow(10.0, (double)-decscale);
-      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+      bms = NULL;
     }
 
-  return (bdsLen);
-}
+  bds = bufpointer;
 
+  dpos = recpos + gribsize + 11;
 
-void gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		double *fsec3, int *isec4, double *fsec4, int fsec4len, int *kgrib,
-		int kleng, int *kword, int dfunc, int *iret)
-{
-  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
-  int gribLen = 0;
-  int gdsIncluded = FALSE;
-  int bmsIncluded = FALSE;
-  int bitmapSize = 0;
-  int imaskSize = 0;
-  int ldebug = FALSE;
-  int llarge = FALSE, l_iorj = FALSE;
-  int lsect2 = FALSE, lsect3 = FALSE;
-  int numGridVals = 0;
-  static int lmissvalinfo = 1;
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
+  bufpointer += bdslen;
+  gribsize += bdslen;
+  gribsize += 4;
 
-  *iret = 0;
+  if ( gribsize > recsize )
+    {
+      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", recsize, gribsize);
+      return (1);
+    }
 
-  grsdef();
+  /* end section - "7777" in ascii */
+  if ( !GRIB_FIN(bufpointer) )
+    {
+      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
+	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
+    }
 
-  ISEC2_Reduced = FALSE;
+  bsf = BDS_BinScale;
+  if ( bsf > 32767 ) bsf = 32768-bsf;
+  bsf = pow(2.0,(double)bsf);
 
+  bignum[0] = dpos;
+  if ( bms ) bignum[1] = bpos;
+  else       bignum[1] = -999;
+  intnum[0] = BDS_NumBits;
+
+  /*  fltnum[0] = 1.0; */
+  fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
+  fltnum[1] = bsf;
+  fltnum[2] = BDS_RefValue;
   /*
-    ----------------------------------------------------------------
-    IS Indicator Section (Section 0)
-    ----------------------------------------------------------------
+  printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
+  printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
   */
-  is = (unsigned char *) &kgrib[0];
+  return (0);
+}
 
-  isLen = decodeIS(is, isec0, iret);
 
-  /*
-    If count is negative, have to rescale by factor of -120.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( ISEC0_GRIB_Len < 0 )
+void grib1PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  static int header = 1;
+  int GridType, level, nerr;
+  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
+  int bdslen;
+  int llarge = 0;
+
+  if ( header )
     {
-      if ( ldebug )
-	gprintf(__func__, "Special case, negative length multiplied by -120");
-      llarge = TRUE;
-      ISEC0_GRIB_Len *= (-120);
+      fprintf(stdout, 
+      "  Rec : Off Position   Size : V PDS  GDS    BMS    BDS : Code Level :  LType GType: CR LL\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
-  /*
-    When decoding or calculating length, previous editions
-    of the GRIB code must be taken into account.
-
-    In the table below, covering sections 0 and 1 of the GRIB
-    code, octet numbering is from the beginning of the GRIB
-    message;
-    * indicates that the value is not available in the code edition;
-    R indicates reserved, should be set to 0;
-    Experimental edition is considered as edition -1.
 
-    GRIB code edition -1 has fixed length of 20 octets for
-    section 1, the length not included in the message.
-    GRIB code edition 0 has fixed length of 24 octets for
-    section 1, the length being included in the message.
-    GRIB code edition 1 can have different lengths for section
-    1, the minimum being 28 octets, length being included in
-    the message.
+  is = gribbuffer;
 
-                                         Octet numbers for code
-                                                  editions
+  if ( gribrec_len(is[4], is[5], is[6]) > JP23SET ) llarge = 1;
 
-                 Contents.                   -1      0      1
-                 ---------                ----------------------
-       Letters GRIB                          1-4    1-4    1-4
-       Total length of GRIB message.          *      *     5-7
-       GRIB code edition number               *      *      8
-       Length of Section 1.                   *     5-7    9-11
-       Reserved octet (R).                    *      8(R)   *
-       Version no. of Code Table 2.           *      *     12
-       Identification of centre.              5      9     13
-       Generating process.                    6     10     14
-       Grid definition .                      7     11     15
-       Flag (Code Table 1).                   8     12     16
-       Indicator of parameter.                9     13     17
-       Indicator of type of level.           10     14     18
-       Height, pressure etc of levels.      11-12  15-16  19-20
-       Year of century.                      13     17     21
-       Month.                                14     18     22
-       Day.                                  15     19     23
-       Hour.                                 16     20     24
-       Minute.                               17     21     25
-       Indicator of unit of time.            18     22     26
-       P1 - Period of time.                  19     23     27
-       P2 - Period of time                  20(R)   24     28
-       or reserved octet (R).
-       Time range indicator.                21(R)   25     29
-       or reserved octet (R).
-       Number included in average.       22-23(R)  26-27  30-31
-       or reserved octet (R).
-       Number missing from average.         24(R)  28(R)   32
-       or reserved octet (R).
-       Century of data.                       *      *     33
-       Designates sub-centre if not 0.        *      *     34
-       Decimal scale factor.                  *      *    35-36
-       Reserved. Set to 0.                    *      *    37-48
-       (Need not be present)
-       For originating centre use only.       *      *    49-nn
-       (Need not be present)
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d :%4ld %8ld %6ld : GRIB message error\n", nrec, offset, recpos, recsize);
+      return;
+    }
 
-    Identify which GRIB code edition is being decoded.
+  if ( gds == NULL )
+    GridType = -1;
+  else
+    GridType = GDS_GridType;
 
-    In GRIB edition 1, the edition number is in octet 8.
-    In GRIB edition 0, octet 8 is reserved and set to 0.
-    In GRIB edition -1, octet 8 is a flag field and can have a
-    a valid value of 0, 1, 2 or 3.
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else if ( PDS_LevelType == 109 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-    However, GRIB edition number 0 has a fixed
-    length of 24, included in the message, for section 1, so
-    if the value extracted from octets 5-7 is 24 and that from
-    octet 8 is 0, it is safe to assume edition 0 of the code.
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
 
-  */
-  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
+  if ( ((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130) )
     {
-      /*
-	Set length of GRIB message to missing data value.
-      */
-      ISEC0_GRIB_Len = 0;
+      int s1, s2;
+      s1 = gribrec_len(bds[14], bds[15], bds[16]);
+      s2 = gribrec_len(gribbuffer[4], gribbuffer[5], gribbuffer[6]);
+      cr = ((double)s1)/s2;
     }
-  /*
-    If Grib Edition 1 and only length is required, go to section 9.
-  */
-  if ( dfunc == 'L' ) goto LABEL900;
 
-  /*
-    ----------------------------------------------------------------
-    PDS Product Definition Section (Section 1)
-    ----------------------------------------------------------------
-  */ 
-  pds = is + isLen;
+  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d%4d%5d %6d %6d : %3d %6d : %5d %5d %6.4g  %c",
+	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
+	  PDS_Len, GDS_Len, BMS_Len, bdslen,
+	  PDS_Parameter, level, PDS_LevelType, GridType, cr, llarge?'T':'F');
 
-  pdsLen = decodePDS(pds, isec0, isec1);
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
+}
 
-  /*
-    ----------------------------------------------------------------
-    GDS Grid Description Section (Section 2)
-    ----------------------------------------------------------------
-  */
-  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
 
-  if ( gdsIncluded )
-    {
-      gds = is + isLen + pdsLen;
+void grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  static int header = 1;
+  int nerr;
+  unsigned char *is  = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  unsigned char *ids = NULL, *lus = NULL, *drs = NULL;
+  long ids_len = 0, lus_len = 0, gds_len = 0, pds_len = 0, drs_len = 0, bms_len = 0, bds_len = 0;
+  int gridtype, paramnum, level1type /*, level2type*/;
+  int level1 /*, level1sf*/;
+  /* int level2, level2sf; */
+  double cr = 1;
 
-      gdsLen = decodeGDS(gds, isec0, isec2, fsec2, &numGridVals, dfunc);
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : Off Position   Size : V IDS LUS GDS PDS  DRS    BMS    BDS : Code Level :  LType GType: CR\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
 
-  /*
-    ----------------------------------------------------------------
-    BMS Bit-Map Section Section (Section 3)
-    ----------------------------------------------------------------
-  */ 
-  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+  is = gribbuffer;
 
-  isec3[0] = 0;
-  if ( bmsIncluded )
+  nerr = grib2Sections(gribbuffer, recsize, &ids, &lus, &gds, &pds, &drs, &bms, &bds);
+  if ( nerr )
     {
-      bms = is + isLen + pdsLen + gdsLen;
-
-      bmsLen = BMS_Len;
-      imaskSize = (bmsLen - 6)<<3;
-      bitmapSize = imaskSize - BMS_UnusedBits;
-      /*
-      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
-      */
+      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
+      return;
     }
 
+  if ( ids ) ids_len = GRIB2_SECLEN(ids);
+  if ( lus ) lus_len = GRIB2_SECLEN(lus);
+  if ( gds ) gds_len = GRIB2_SECLEN(gds);
+  if ( pds ) pds_len = GRIB2_SECLEN(pds);
+  if ( drs ) drs_len = GRIB2_SECLEN(drs);
+  if ( bms ) bms_len = GRIB2_SECLEN(bms);
+  if ( bds ) bds_len = GRIB2_SECLEN(bds);
+
   /*
-    ----------------------------------------------------------------
-    BDS Binary Data Section (Section 4)
-    ----------------------------------------------------------------
+  if ( (BDS_Flag >> 4)&1 && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[14]<<16)+(bds[15]<<8)+bds[16]));
+      s2 = ((int) ((gribbuffer[4]<<16)+(gribbuffer[5]<<8)+gribbuffer[6]));
+      cr = ((double)s1)/s2;
+    }
   */
-  bds = is + isLen + pdsLen + gdsLen + bmsLen;
-
-  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
+  gridtype   = GET_UINT2(gds[12],gds[13]);
+  paramnum   = GET_UINT1(pds[10]);
+  level1type = GET_UINT1(pds[22]);
+  /* level1sf   = GET_UINT1(pds[23]); */
+  level1     = GET_UINT4(pds[24],pds[25],pds[26],pds[27]);
+  /* level2type = GET_UINT1(pds[28]); */
+  /* level2sf   = GET_UINT1(pds[29]); */
+  /* level2     = GET_UINT4(pds[30],pds[31],pds[32],pds[33]); */
+  /*
+  printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
+  */
+  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %3d%7d : %5d %5d %6.4g\n",
+	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
+	  ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len,
+	  paramnum, level1, level1type, gridtype, cr);
+}
 
-  bdsLen = decodeBDS(ISEC1_DecScaleFactor, bds, isec2, isec4, 
-		     fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
 
-  if ( *iret != 0 ) return;
+void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  int gribversion;
 
-  ISEC4_NumNonMissValues = ISEC4_NumValues;
+  gribversion = gribVersion(gribbuffer, recsize);
 
-  if ( bitmapSize > 0 )
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
+  else if ( gribversion == 2 )
+    grib2PrintALL(nrec, offset, recpos, recsize, gribbuffer);
+  else
     {
-      if ( dfunc != 'L' && dfunc != 'J' )
-	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
-	  {
-	    lmissvalinfo = 0;
-	    FSEC3_MissVal = GRIB_MISSVAL;
-	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
-	  }
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, offset, recpos, recsize, gribversion); 
+    }
+}
 
-      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
-      ISEC4_NumValues        = bitmapSize;
 
-      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
-	{
-	  long i, j;
-	  GRIBPACK *pbitmap;
-	  GRIBPACK bitmap;
-	  GRIBPACK *imask;
+void grib1PrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  static int header = 1;
+  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int century, subcenter, decimalscale, nerr;
+  int fc_num = 0;
+  int year = 0, date;
 
-	  /*
-	  unsigned char *bitmap;
-	  bitmap = BMS_Bitmap;
-	  j = ISEC4_NumNonMissValues;
-	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
-	    {
-	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
-		fsec4[i] = fsec4[--j];
-	      else
-		fsec4[i] = FSEC3_MissVal;
-	    }
-	  */
+  UNUSED(recpos);
 
-	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : PDS Tab Cen Sub Ver Grid Code LTyp Level1 Level2    Date  Time P1 P2 TU TR NAVE Scale FCnum CT\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
 
-#if defined (VECTORCODE)
-	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
-	  pbitmap = imask;
-#else
-	  pbitmap = BMS_Bitmap;
-#endif
+  is = gribbuffer;
 
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-	  for ( i = imaskSize/8-1; i >= 0; i-- )
-	    {
-	      bitmap = pbitmap[i];
-	      imask[i*8+0] = 1 & (bitmap >> 7);
-	      imask[i*8+1] = 1 & (bitmap >> 6);
-	      imask[i*8+2] = 1 & (bitmap >> 5);
-	      imask[i*8+3] = 1 & (bitmap >> 4);
-	      imask[i*8+4] = 1 & (bitmap >> 3);
-	      imask[i*8+5] = 1 & (bitmap >> 2);
-	      imask[i*8+6] = 1 & (bitmap >> 1);
-	      imask[i*8+7] = 1 & (bitmap);
-	    }
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-	  j = 0;
-	  for ( i = 0; i < ISEC4_NumValues; i++ )
-	    if ( imask[i] ) j++;
+  switch(GRIB_EDITION(is))
+    {   
+    case 0:
+      year                = GET_UINT1(pds[12]);
+      century             = 1;
+      subcenter           = 0;
+      decimalscale        = 0;
+      break;
+    case 1:
+      year                = PDS_Year;
+      century             = PDS_Century;
+      subcenter           = PDS_Subcenter;
+      decimalscale        = PDS_DecimalScale;
+      break;
+    default:
+      fprintf(stderr, "Grib version %d not supported!", GRIB_EDITION(is));
+      exit(EXIT_FAILURE);
+    }
 
-	  if ( ISEC4_NumNonMissValues != j )
-	    {
-	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
-		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
-			j, ISEC4_NumNonMissValues);
+  if ( PDS_Len > 28 )
+    if ( PDS_CenterID    == 98 || PDS_Subcenter == 98 ||
+	(PDS_CenterID    ==  7 && PDS_Subcenter == 98) )
+      if ( pds[40] == 1 )
+	fc_num = GET_UINT1(pds[49]);
 
-	      ISEC4_NumNonMissValues = j;
-	    }
+  if ( year < 0 )
+    {
+      date = (-year)*10000+PDS_Month*100+PDS_Day;
+      century = -century;
+    }
+  else
+    {
+      date =    year*10000+PDS_Month*100+PDS_Day;
+    }
+      
+  fprintf(stdout, "%5d :%4d%4d%4d%4d%4d %4d %4d%4d%7d%7d %8d%6d%3d%3d%3d%3d%5d%6d%5d%4d", nrec,
+	  PDS_Len,  PDS_CodeTable,   PDS_CenterID, subcenter, PDS_ModelID,
+	  PDS_GridDefinition, PDS_Parameter, PDS_LevelType, PDS_Level1, PDS_Level2,
+	  date, PDS_Time, PDS_TimePeriod1, PDS_TimePeriod2, PDS_TimeUnit, PDS_TimeRange,
+	  PDS_AvgNum, decimalscale, fc_num, century);
 
-	  if ( dfunc != 'J' )
-	    {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
-		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
-	    }
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
+}
 
-	  free(imask);
-	}
-    }
 
-  if ( ISEC2_Reduced )
+void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  int gribversion;
+
+  gribversion = gribVersion(gribbuffer, recsize);
+
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
+  /*
+  else if ( gribversion == 2 )
+    grib2PrintPDS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
     {
-      int nlon, nlat;
-      int lsect3, lperio = 1, lveggy;
-      int ilat;
-      int nvalues = 0;
-      int dlon;
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
+    }
+}
 
-      nlat = ISEC2_NumLat;
-      nlon = ISEC2_RowLonPtr[0];
-      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
-      for ( ilat = 1; ilat < nlat; ++ilat )
-	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
 
-      dlon = ISEC2_LastLon-ISEC2_FirstLon;
-      if ( dlon < 0 ) dlon += 360000;
-	  
-      if ( nvalues != ISEC4_NumValues )
-	{
-	  *iret = -801;
-	}
-      //printf("nlat %d  nlon %d \n", nlat, nlon);
-      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
+void grib1PrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  static int header = 1;
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-      if ( dfunc == 'R' && *iret == -801 )
-	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
-		ISEC4_NumValues, nvalues);
-      
-      if ( dfunc == 'R' && *iret != -801 )
-	{
-	  ISEC2_Reduced = 0;
-	  ISEC2_NumLon = nlon;
-	  ISEC4_NumValues = nlon*nlat;
+  UNUSED(recpos);
 
-	  lsect3 = bitmapSize > 0;
-	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
-	    ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
-	     (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
-	      
-	  (void) qu2reg3(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
-	      
-	  if ( bitmapSize > 0 )
-	    {
-	      long i;
-	      int j = 0;
-	      
-	      for ( i = 0; i < ISEC4_NumValues; i++ )
-		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
-		  
-	      ISEC4_NumNonMissValues = j;
-	    }
-	}
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : GDS  NV PVPL Typ : xsize ysize   Lat1   Lon1   Lat2   Lon2    dx    dy\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
 
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
-  esLen = 4;
+  fprintf(stdout, "%5d :", nrec);
 
-  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+  if ( gds )
+    fprintf(stdout, "%4d%4d%4d %4d :%6d%6d%7d%7d%7d%7d%6d%6d",
+	    GDS_Len,  GDS_NV,   GDS_PVPL, GDS_GridType,
+	    GDS_NumLon,   GDS_NumLat,
+	    GDS_FirstLat, GDS_FirstLon,
+	    GDS_LastLat,  GDS_LastLon,
+	    GDS_LonIncr,  GDS_LatIncr);
+  else
+    fprintf(stdout, " Grid Description Section not defined");
 
-  if ( ISEC0_GRIB_Len )
-    if ( gribLen > ISEC0_GRIB_Len )
-      {
-	Warning("grib1Len = %d gribLen = %d", ISEC0_GRIB_Len, gribLen);
-      }
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
+}
 
-  ISEC0_GRIB_Len = gribLen;
 
-  *kword = gribLen / sizeof(int);
-  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  int gribversion;
+
+  gribversion = gribVersion(gribbuffer, recsize);
 
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
   /*
-    ----------------------------------------------------------------
-    Section 9 . Abort/return to calling routine.
-    ----------------------------------------------------------------
+  else if ( gribversion == 2 )
+    grib2PrintGDS(nrec, recpos, recsize, gribbuffer);
   */
- LABEL900:;
-
-  if ( ldebug )
+  else
     {
-      gprintf(__func__, "Section 9.");
-      gprintf(__func__, "Output values set -");
-
-      gribPrintSec0(isec0);
-      gribPrintSec1(isec0, isec1);
-      /*
-	Print section 2 if present.
-      */
-      if ( lsect2 ) gribPrintSec2DP(isec0, isec2, fsec2);
-
-      if ( ! l_iorj )
-	{
-	  /*
-	    Print section 3 if present.
-	  */
-	  if ( lsect3 ) gribPrintSec3DP(isec0, isec3, fsec3);
-
-	  gribPrintSec4DP(isec0, isec4, fsec4);
-	  /*
-	    Special print for 2D spectra wave field real values in
-	    section 4
-	  */
-	  if ( (isec1[ 0] ==  140) && 
-	       (isec1[ 1] ==   98) && 
-	       (isec1[23] ==    1) && 
-	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
-	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
-	    gribPrintSec4Wave(isec4);
-	}
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
     }
 }
-#if defined (HAVE_CONFIG_H)
-#endif
-
-#include <string.h>
-#include <ctype.h>
 
 
-
-int gribOpen(const char *filename, const char *mode)
+void grib1PrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int fileID;
+  static int header = 1;
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-  fileID = fileOpen(filename, mode);
+  UNUSED(recpos);
 
-#if defined (__sun)
-  if ( fileID != FILE_UNDEFID && tolower(*mode) == 'r' )
+  if ( header )
     {
-      fileSetBufferType(fileID, FILE_BUFTYPE_MMAP);
+      fprintf(stdout, 
+      "  Rec : Code Level     BMS    Size\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
-#endif
 
-  return (fileID);  
-}
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
+
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
+  fprintf(stdout, "%5d :", nrec);
 
-void gribClose(int fileID)
-{
-  fileClose(fileID);
+  if ( bms )
+    fprintf(stdout, "%4d%7d %7d %7d",
+	    PDS_Parameter, level,
+	    BMS_Len, BMS_BitmapSize);
+  else
+    fprintf(stdout, "%4d%7d Bit Map Section not defined", PDS_Parameter, level);
+
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-off_t gribGetPos(int fileID)
+void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  return (fileGetPos(fileID));
+  int gribversion;
+
+  gribversion = gribVersion(gribbuffer, recsize);
+
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
+  /*
+  else if ( gribversion == 2 )
+    grib2PrintBMS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
+    {
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
+    }
 }
 
 
-int gribCheckFiletype(int fileID)
+void grib1PrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int ierr;
-  int found = 0;
-  char buffer[4];
+  static int header = 1;
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
+  double refval, scale;
 
-  if ( fileRead(fileID, buffer, 4) != 4 ) return(found);
+  UNUSED(recpos);
 
-  if ( memcmp(buffer, "GRIB", 4) == 0 )
+  if ( header )
     {
-      found = 1;
-      if ( CGRIBEX_Debug ) Message("found GRIB file = %s", fileInqName(fileID));
+      fprintf(stdout, 
+      "  Rec : Code Level     BDS Flag     Scale   RefValue Bits  CR\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
+
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
     }
+
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
   else
+    level = PDS_Level1;
+
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
     {
-      long offset;
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
+    }
 
-      ierr = gribFileSeek(fileID, &offset);
-      fileRewind(fileID);
-      if ( !ierr )
-	{
-	  found = 1;
-	  if ( CGRIBEX_Debug ) Message("found seek GRIB file = %s", fileInqName(fileID));
-	}
+  refval = BDS_RefValue;
+
+  if ( BDS_BinScale < 0 )
+    scale = 1.0/pow(2.0, (double) -BDS_BinScale);
+  else
+    scale = pow(2.0, (double) BDS_BinScale);
+
+  if ( PDS_DecimalScale )
+    {
+      double decscale;
+      decscale = pow(10.0, (double)-PDS_DecimalScale);
+      refval *= decscale;
+      scale  *= decscale;
     }
 
-  return (found);
+  fprintf(stdout, "%5d :", nrec);
+
+  if ( bds )
+    fprintf(stdout, "%4d%7d %7d %4d %8.5g %11.5g%4d %6.4g",
+	    PDS_Parameter, level,
+	    BDS_Len, BDS_Flag, scale, refval, BDS_NumBits, cr);
+  else
+    fprintf(stdout, " Binary Data Section not defined");
+
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-int gribCheckSeek(int fileID, long *offset, int *version)
+void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int ierr;
-  char buffer[4];
+  int gribversion;
 
-  ierr = gribFileSeek(fileID, offset);
+  gribversion = gribVersion(gribbuffer, recsize);
 
-  *version = -1;
-  if ( !ierr )
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
+  /*
+  else if ( gribversion == 2 )
+    grib2PrintBDS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
     {
-      if ( fileRead(fileID, buffer, 4) == 4 )
-	*version = buffer[3];
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
     }
-
-  return (ierr);
 }
 
 
-int gribFileSeekOld(int fileID, long *offset)
+void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  /* position file pointer after GRIB */
-  int ch;
-  int buffersize = 4096;
-  unsigned char buffer[4096];
-  int retry = 4096;
-  int i;
-  void *fileptr;
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
 
-  *offset = 0;
+  UNUSED(recpos);
 
-  fileptr = filePtr(fileID);
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
-  /*
-  fileRead(fileID, buffer, 4);
-  */
-
-  while ( retry-- )
+  if ( nerr > 0 )
     {
-      for ( i = 0; i < buffersize-4; ++i )
-	{
-	  if (buffer[i  ] == 'G' && 
-	      buffer[i+1] == 'R' &&
-	      buffer[i+2] == 'I' &&
-	      buffer[i+3] == 'B')
-	    {
-	      if ( CGRIBEX_Debug )
-		Message("record offset = %d", (int) *offset);
-	      return (0);
-	    }
-	  else
-	    {
-	      ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
-	      (*offset)++;
-	    }
-	}
-      buffer[0] = buffer[i  ];
-      buffer[1] = buffer[i+1];
-      buffer[2] = buffer[i+2];
-      buffer[3] = buffer[i+3];
+      fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
+      return;
     }
 
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-  return (1);
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
+    }
+
+  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+    {
+      fprintf(stdout, "GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+    }
 }
 
 
-int gribFileSeek(int fileID, long *offset)
+static
+void repair1(unsigned char *gbuf, long gbufsize)
 {
-  /* position file pointer after GRIB */
-  const long GRIB = 0x47524942;
-  long code = 0;
-  int ch;
-  int retry = 4096*4096;
-  void *fileptr;
-
-  *offset = 0;
-
-  fileptr = filePtr(fileID);
+  long i;
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  /* int recLen; */
+  unsigned char *source;
+  size_t sourceLen;
+  int bds_len, bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress */;
+  int bds_head = 11;
+  int bds_ext = 0, bds_ubits;
+  int datstart = 0;
+  /* int llarge = FALSE; */
 
-  while ( retry-- )
+  long gribrecsize;
+  nerr = grib1Sections(gbuf, gbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      ch = filePtrGetc(fileptr);
-      if ( ch == EOF ) return (-1);
-    
-      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
-
-      if ( code == GRIB )
-	{
-	  if ( CGRIBEX_Debug )
-	    Message("record offset = %d", (int) *offset);
-	  return (0);
-	}
-
-      (*offset)++;
+      fprintf(stdout, "GRIB message error\n");
+      return;
     }
 
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
-
-  return (1);
-}
-
-
-int gribFileSeekTest(int fileID, long *offset)
-{
-  /* position file pointer after GRIB */
-  const long GRIB = 0x47524942;
-  long code = 0;
-  int ch;
-  int i = 0;
-  const int buffersize = 8;
-  unsigned char buffer[8];
-  int retry = 4096*4096;
-  void *fileptr;
-  int nread = 0;
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return;
+    }
 
-  *offset = 0;
+  /* recLen = gribrec_len(gbuf[4], gbuf[5], gbuf[6]); */
+  /* if ( recLen > JP23SET ) llarge = TRUE; */
 
-  fileptr = filePtr(fileID);
+  bds_len   = BDS_Len;
+  bds_nbits = BDS_NumBits;
+  bds_flag  = BDS_Flag;
+  bds_ubits = bds_flag & 15;
+  lspherc   =  bds_flag >> 7;
+  lcomplex  = (bds_flag >> 6)&1;
+  /* lcompress = (bds_flag >> 4)&1; */
 
-  while ( retry-- )
+  if ( lspherc )
     {
-      if ( i >= nread )
+      if ( lcomplex  )
 	{
-	  nread = (int) filePtrRead(fileptr, buffer, buffersize);
-	  if ( nread == 0 ) return (-1);
-	  i = 0;
+	  int jup, ioff;
+	  jup  = bds[15];
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	}
+      else
+	{
+	  bds_ext = 4;
 	}
+    }
 
-      ch = buffer[i++];
-      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+  datstart = bds_head + bds_ext;
 
-      if ( code == GRIB )
-	{
-	  /* printf("end: %d %d\n", nread, i); */
-	  if ( CGRIBEX_Debug )
-	    Message("record offset = %d", (int) *offset);
+  source = bds + datstart;
 
-	  if ( i != nread ) fileSetPos(fileID, (off_t) i-nread, SEEK_CUR);
+  sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
 
-	  return (0);
+  if ( bds_nbits == 24 )
+    {
+      long nelem;
+      unsigned char *pbuf;
+      nelem = sourceLen/3;
+      pbuf = (unsigned char*) malloc(sourceLen);
+      for ( i = 0; i < nelem; i++ )
+	{
+	  pbuf[3*i  ] = source[        i];
+	  pbuf[3*i+1] = source[  nelem+i];
+	  pbuf[3*i+2] = source[2*nelem+i];
 	}
-
-      (*offset)++;
+      memcpy(source, pbuf, sourceLen);
+      free(pbuf);
     }
-
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
-
-  return (1);
 }
 
 
-int gribReadSize(int fileID)
+void gribRepair1(int nrec, long recsize, unsigned char *gribbuffer)
 {
-  int gribversion, gribsize;
-  int b1, b2, b3;
-  off_t pos;
-  void *fileptr;
-  /*
-  const int buffersize = 4;
-  unsigned char buffer[4];
-  */
-  fileptr = filePtr(fileID);
-
-  pos = fileGetPos(fileID); 
-  /* bug: order of functions calls!
-     gribsize = (filePtrGetc(fileptr) << 16) + (filePtrGetc(fileptr) << 8) + filePtrGetc(fileptr);
-  */
-  b1 = filePtrGetc(fileptr);
-  b2 = filePtrGetc(fileptr);
-  b3 = filePtrGetc(fileptr);
-  // gribsize = (b1 << 16) + (b2 << 8) + b3;
-  gribsize = gribrec_len(b1, b2, b3);
-
-  gribversion = filePtrGetc(fileptr);
-  /*
-  filePtrRead(fileptr, buffer, buffersize);
-
-  gribsize = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
 
-  gribversion = buffer[3];
-  */
-  if ( gribsize == 24 )
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      if ( gribversion != 1 && gribversion != 2 ) gribversion = 0;
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
     }
 
-  if ( CGRIBEX_Debug )
-    Message("gribversion = %d", gribversion);
-
-  if ( gribversion == 0 )
+  if ( nerr > 0 )
     {
-      int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
-      int issize = 4, essize = 4;
-      int flag;
-
-      pdssize = gribsize;
-      fileSetPos(fileID, (off_t) 3, SEEK_CUR);
-      if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
-      flag = filePtrGetc(fileptr);
-      if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
-  
-      fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
-
-      if ( flag & 128 )
-	{
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  gdssize = (b1 << 16) + (b2 << 8) + b3;
-	  fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
-	  if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
-	}
-
-      if ( flag & 64 )
-	{
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  bmssize = (b1 << 16) + (b2 << 8) + b3;
-	  fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
-	  if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
-	}
-
-      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-      bdssize = (b1 << 16) + (b2 << 8) + b3;
-      if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
-
-      gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
+      fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
+      return;
     }
-  else if ( gribversion == 1 )
-    {
-      if ( gribsize > JP23SET ) /* Large GRIB record */
-	{
-	  int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
-	  int issize = 4, essize = 4;
-	  int flag;
-
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  pdssize = (b1 << 16) + (b2 << 8) + b3;
-	  if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
-
-	  for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
-	  if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
-  
-	  fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
-
-	  if ( flag & 128 )
-	    {
-	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	      gdssize = (b1 << 16) + (b2 << 8) + b3;
-	      fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
-	      if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
-	    }
-	  
-	  if ( flag & 64 )
-	    {
-	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	      bmssize = (b1 << 16) + (b2 << 8) + b3;
-	      fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
-	      if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
-	    }
 
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  bdssize = (b1 << 16) + (b2 << 8) + b3;
-	  bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
-	  if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-	  gribsize = issize+pdssize+gdssize+bmssize+bdssize+essize;
-	}
-    }
-  else if ( gribversion == 2 )
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
     {
-      int i;
-      /* we set gribsize the following way because it doesn't matter then
-	 whether int is 4 or 8 bytes long - we don't have to care if the size
-	 really fits: if it does not, the record can not be read at all */
-      gribsize = 0;
-      for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | filePtrGetc(fileptr);
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
     }
-  else
+
+  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
     {
-      gribsize = 0;
-      Warning("GRIB version %d unsupported!", gribversion);
+      fprintf(stdout, "Repair GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+      repair1(gribbuffer, recsize);
     }
+}
+#include <stdio.h>
+#include <string.h>
 
-  if ( filePtrEOF(fileptr) ) gribsize = 0;
-
-  if ( CGRIBEX_Debug )
-    Message("gribsize    = %d", gribsize);
-
-  fileSetPos(fileID, pos, SEEK_SET);
+#if defined (HAVE_CONFIG_H)
+#endif
 
-  return (gribsize);
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if defined (HAVE_LIBAEC)
+#  include <libaec.h>
+#else
+#  include <szlib.h>
+#endif
+#if defined (__cplusplus)
 }
+#endif
 
+#if defined (HAVE_LIBAEC)
+#  define AEC_FLAGS           (AEC_DATA_MSB | AEC_DATA_PREPROCESS)
+#else
+#  define OPTIONS_MASK        (SZ_RAW_OPTION_MASK | SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK)
+#endif
 
-int gribGetSize(int fileID)
-{
-  int recsize;
-  long offset;
-  int ierr;
+#  define PIXELS_PER_BLOCK    (8)
+#  define PIXELS_PER_SCANLINE (PIXELS_PER_BLOCK*128)
 
-  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
-  if ( ierr > 0 )
-    {
-      Warning("GRIB record not found!");
-      return (0);
-    }
+#  define MIN_COMPRESS        (0.95)
+#  define MIN_SIZE            (256)
+#endif
 
-  if ( ierr == -1 )
-    return (0);
-  else if ( ierr == 1 )
-    return (0);
+#define  Z_SZIP  128
+#define  Z_AEC   130
 
-  recsize = gribReadSize(fileID);
 
-  if ( CGRIBEX_Debug ) Message("recsize = %d", recsize);
+#define SetLen3(var, offset, value) ((var[offset+0] = 0xFF & (value >> 16)), \
+				     (var[offset+1] = 0xFF & (value >>  8)), \
+				     (var[offset+2] = 0xFF & (value      )))
+#define SetLen4(var, offset, value) ((var[offset+0] = 0xFF & (value >> 24)), \
+				     (var[offset+1] = 0xFF & (value >> 16)), \
+				     (var[offset+2] = 0xFF & (value >>  8)), \
+				     (var[offset+3] = 0xFF & (value      )))
 
-  fileSetPos(fileID, (off_t) -4, SEEK_CUR);
 
-  return (recsize);
-}
+int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
+{
+  /* urecsize : uncompressed record size  */
+  int compress = 0;
+  int nerr;
+  /* int  bds_len, bds_nbits, lspherc, lcomplex; */
+  int bds_flag, lcompress;
+  long gribsize = 0;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int gribversion;
 
+  gribversion = gribVersion(gribbuffer, recsize);
 
-int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
-{
-  long offset;
-  int ierr = 0;
-  size_t nread, recsize, recsize0;
+  if ( gribversion == 2 ) return (compress);
 
-  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
-  if ( ierr > 0 )
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      Warning("GRIB record not found!");
-      return (-2);
+      fprintf(stdout, "GRIB message error\n");
+      return (compress);
     }
 
-  if ( ierr == -1 )
-    {
-      *buffersize = 0;
-      return (-1);
-    }
-  else if ( ierr == 1 )
+  if ( nerr > 0 )
     {
-      *buffersize = 0;
-      return (-2);
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (compress);
     }
 
-  recsize = gribReadSize(fileID);
-
-  buffer[0] = 'G';
-  buffer[1] = 'R';
-  buffer[2] = 'I';
-  buffer[3] = 'B';
-
-  recsize0 = recsize;
+  /* bds_len   = BDS_Len; */
+  /* bds_nbits = BDS_NumBits; */
+  bds_flag  = BDS_Flag;
+  /* lspherc   =  bds_flag >> 7; */
+  /* lcomplex  = (bds_flag >> 6)&1; */
+  lcompress = (bds_flag >> 4)&1;
 
-  if ( recsize > *buffersize )
+  *urecsize = 0;
+  if ( lcompress )
     {
-      recsize = *buffersize;
-      ierr = -3;
+      compress = BDS_Z;
+      if ( compress == Z_SZIP || compress == Z_AEC )
+	{
+	  gribsize = gribrec_len(bds[14], bds[15], bds[16]);
+	}
     }
 
-  *buffersize = recsize0;
-
-  nread = fileRead(fileID, &buffer[4], recsize-4);
-
-  if ( nread != recsize-4 ) ierr = 1;
+  *urecsize = gribsize;
 
-  return (ierr);
+  return (compress);
 }
 
 
-int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
+int  gribZip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
 {
-  int  nwrite = 0;
+  int nerr;
+  int gribLen;
+  int rec_len;
+  int llarge = FALSE;
+#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
+  static int libszwarn = 1;
+#endif
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-  if( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
+  gribLen = gribrec_len(dbuf[4], dbuf[5], dbuf[6]);
+  if ( gribLen > JP23SET ) llarge = TRUE;
+
+  rec_len = gribLen;
+
+  long gribrecsize;
+  nerr = grib1Sections(dbuf, dbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      perror(__func__);
-      nwrite = -1;
+      fprintf(stdout, "GRIB message error\n");
+      return (rec_len);
     }
 
-  return ((int) nwrite);
-}
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (rec_len);
+    }
 
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
 
-int gribrec_len(int b1, int b2, int b3)
-{
-  int gribsize;
+  {
+    long i;
+    int bdsLen;
+    int gribLenOld = 0;
+    int status;
+    size_t datstart, datsize;
+#if defined (HAVE_LIBAEC)
+    struct aec_stream strm;
+#else
+    SZ_com_t sz_param;          /* szip parameter block */
+#endif
+    unsigned char *dest, *source;
+    size_t destLen, sourceLen;
+    int bits_per_sample;
+    int bds_len, bds_nbits, bds_flag, lspherc, lcomplex,/* lcompress,*/ bds_ubits;
+    int bds_head = 11;
+    int bds_ext = 0;
+    int bds_zoffset, bds_zstart;
+    unsigned char *pbuf = NULL;
 
-  gribsize = (1-(int) ((unsigned) (b1&128) >> 6)) * (int) (((b1&127) << 16)+(b2<<8) + b3);
-  /*
-    If count is negative, have to rescale by factor of -120.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( gribsize < 0 ) gribsize *= (-120);
+    bds_zstart  = 14;
+    bds_zoffset = 12;
+    if ( llarge ) bds_zoffset += 2;
 
-  return (gribsize);
-}
+    bds_len   = BDS_Len;
+    bds_len   = correct_bdslen(bds_len, gribLen, bds-dbuf);
+    bds_nbits = BDS_NumBits;
+    bds_flag  = BDS_Flag;
+    bds_ubits = bds_flag & 15;
+    lspherc   =  bds_flag >> 7;
+    lcomplex  = (bds_flag >> 6)&1;
+    /* lcompress = (bds_flag >> 4)&1; */
+    
+    if ( bds_nbits != 8 && bds_nbits != 16 && bds_nbits != 24 && bds_nbits != 32 )
+      {
+	static int linfo = 1;
+	if ( linfo && bds_nbits != 0 )
+	  {
+	    linfo = 0;
+	    fprintf(stderr, "GRIB szip only supports 8, 16, 24 and 32 bit data!\n");
+	  }
+	return (rec_len);
+      }
 
-#include <stdio.h>
-#include <math.h>
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      bits_per_sample    = 8;
+    else
+#endif
+      bits_per_sample    = bds_nbits;
+
+#if defined (HAVE_LIBAEC)
+    strm.bits_per_sample = bits_per_sample;
+    strm.block_size      = PIXELS_PER_BLOCK;
+    strm.rsi             = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
+    strm.flags           = AEC_FLAGS;
+    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
+#else
+    sz_param.options_mask        = OPTIONS_MASK;
+    sz_param.bits_per_pixel      = bits_per_sample;
+    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
+    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
+#endif
+
+    if ( lspherc )
+      {
+	if ( lcomplex  )
+	  {
+	    int jup, ioff;
+	    jup  = bds[15];
+	    ioff = (jup+1)*(jup+2);
+	    bds_ext = 4 + 3 + 4*ioff;
+	  }
+	else
+	  {
+	    bds_ext = 4;
+	  }
+      }
+
+    datstart = bds_head + bds_ext;
+
+    datsize = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+
+    if ( datsize < MIN_SIZE ) return (rec_len);
+    /*
+    fprintf(stderr, "%d %d %d %d\n", bds_len, datstart, bds_len - datstart, datsize);
+    */
+    sourceLen = datsize;
+    destLen   = sbufsize;
+    
+    source = bds + datstart;
+    dest = sbuf;
+
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      {
+	long nelem;
+	nelem = sourceLen/3;
+	pbuf = (unsigned char*) malloc(sourceLen);
+	for ( i = 0; i < nelem; i++ )
+	  {
+	    pbuf[        i] = source[3*i  ];
+	    pbuf[  nelem+i] = source[3*i+1];
+	    pbuf[2*nelem+i] = source[3*i+2];
+	  }
+	source = pbuf;
+      }
+#endif
+
+#if defined (HAVE_LIBAEC)
+    strm.next_in = source;
+    strm.avail_in = sourceLen;
+    strm.next_out = dest;
+    strm.avail_out = destLen;
+
+    status = aec_buffer_encode(&strm);
+    if ( status != AEC_OK )
+      {
+       	if ( status != AEC_DATA_ERROR )
+	  Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
+
+    destLen = strm.total_out;
+#else
+    status = SZ_BufftoBuffCompress(dest, &destLen, source, sourceLen, &sz_param);
+    if ( status != SZ_OK )
+      {
+	if ( status == SZ_NO_ENCODER_ERROR )
+	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_PARAM_ERROR )
+	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_MEM_ERROR )
+	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_OUTBUFF_FULL )
+	  /*Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2)*/;
+	else
+	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
+#endif
+    
+    if ( pbuf ) free(pbuf);
+    /*
+    fprintf(stderr, "sourceLen, destLen %d %d\n", sourceLen, destLen);
+    */
+    if ( destLen < MIN_COMPRESS*sourceLen )
+      {
+	source = bds + datstart + bds_zoffset;
+	memcpy(source, dest, destLen);
+	
+	/* ----++++ number of unused bits at end of section) */
+
+	BDS_Flag -= bds_ubits;
+    
+	gribLenOld = gribLen;
+
+	if ( bds_ext )
+	  for ( i = bds_ext-1; i >= 0; --i )
+	    bds[bds_zoffset+bds_head+i] = bds[bds_head+i];
+
+	/*
+	fprintf(stderr, "destLen, datsize, datstart %d %d %d\n", destLen, datsize, datstart);
+	*/
+	/*	memcpy(bds + datstart + bds_zoffset, source, destLen); */
+	/*
+	  fprintf(stderr, "z>>> %d %d %d %d <<<\n", (int) bds[0+datstart+bds_zoffset],
+	    (int)bds[1+datstart+bds_zoffset], (int)bds[2+datstart+bds_zoffset], (int)bds[3+datstart+bds_zoffset]);
+	*/
+	if ( llarge )
+	  {
+	    if ( gribLenOld%120 )
+	      {
+		fprintf(stderr, "Internal problem, record length not multiple of 120!");
+		while ( gribLenOld%120 ) gribLenOld++;
+	      }
+	    gribLenOld = gribLenOld / (-120);
+	    gribLenOld = JP23SET - gribLenOld + 1;
+
+	    SetLen3(bds, bds_zstart, gribLenOld);
+	    SetLen4(bds, bds_zstart+3, sourceLen);
+	    SetLen4(bds, bds_zstart+7, destLen);
+	  }
+	else
+	  {
+	    SetLen3(bds, bds_zstart, gribLenOld);
+	    SetLen3(bds, bds_zstart+3, sourceLen);
+	    SetLen3(bds, bds_zstart+6, destLen);
+	  }
+
+	bdsLen = datstart + bds_zoffset + destLen;
+
+	bds[11] = 0;
+	bds[12] = 0;
+#if defined (HAVE_LIBAEC)
+	BDS_Z   = Z_AEC;
+#else
+	BDS_Z   = Z_SZIP;
+#endif
+
+	BDS_Flag += 16;
+	if ( (bdsLen%2) == 1 )
+	  {
+	    BDS_Flag += 8;
+	    bds[bdsLen++] = 0;
+	  }
+
+	SetLen3(bds, 0, bdsLen);
+
+	gribLen = (bds - dbuf) + bdsLen;
+
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
+
+	if ( llarge )
+	  {
+	    long itemp;
+	    long bdslen = gribLen - 4;
+
+	    /*
+	      If a very large product, the section 4 length field holds
+	      the number of bytes in the product after section 4 upto
+	      the end of the padding bytes.
+	      This is a fixup to get round the restriction on product lengths
+	      due to the count being only 24 bits. It is only possible because
+	      the (default) rounding for GRIB products is 120 bytes.
+	    */
+	    while ( gribLen%120 ) dbuf[gribLen++] = 0;
+
+	    itemp = gribLen / (-120);
+	    itemp = JP23SET - itemp + 1;
+
+	    SetLen3(dbuf, 4, itemp);
+
+	    bdslen = gribLen - bdslen;
+
+	    SetLen3(bds, 0, bdslen);
+	  }
+	else
+	  {
+	    SetLen3(dbuf, 4, gribLen);
+	  }
+      }
+    else
+      {
+      }
+    /*
+    fprintf(stderr, "%3d %3d griblen in %6d  out %6d  CR %g   slen %6d dlen %6d  CR %g\n",
+	    PDS_Parameter, PDS_Level1, gribLenOld, gribLen,
+	    ((double)gribLenOld)/gribLen, sourceLen, destLen,
+	    ((double)sourceLen)/destLen);
+    */
+  }
+
+#else
+  if ( libszwarn )
+    {
+      Warning("Compression disabled, szlib or libaec not available!");
+      libszwarn = 0;
+    }
+#endif
+
+  if ( llarge )
+    while ( gribLen%120 ) dbuf[gribLen++] = 0;
+  else
+    while ( gribLen & 7 ) dbuf[gribLen++] = 0;
+
+  rec_len = gribLen;
+
+  return (rec_len);
+}
+
+
+int  gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
+{
+#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
+  static int libszwarn = 1;
+#endif
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int bdsLen, recLen, gribLen = 0;
+  unsigned char *dest, *source;
+  size_t destLen, sourceLen;
+  int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
+  int bds_head = 11;
+  int bds_ext = 0;
+  int bds_zoffset, bds_zstart;
+  int datstart = 0;
+  int llarge = FALSE;
+
+  UNUSED(dbufsize);
+
+  long gribrecsize;
+  nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (0);
+    }
+
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (0);
+    }
+
+  bds_zstart = 14;
+
+  recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
+  if ( recLen > JP23SET ) llarge = TRUE;
+
+  bds_zoffset = 12;
+  if ( llarge ) bds_zoffset += 2;
+
+  /* bds_len   = BDS_Len; */
+  bds_nbits = BDS_NumBits;
+  bds_flag  = BDS_Flag;
+  lspherc   =  bds_flag >> 7;
+  lcomplex  = (bds_flag >> 6)&1;
+  /* lcompress = (bds_flag >> 4)&1; */
+
+  if ( lspherc )
+    {
+      if ( lcomplex  )
+	{
+	  int jup, ioff;
+	  jup  = bds[bds_zoffset+15];
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	}
+      else
+	{
+	  bds_ext = 4;
+	}
+    }
+
+  datstart = bds_head + bds_ext;
+
+  source = bds + datstart + bds_zoffset;
+  if ( llarge )
+    sourceLen = ((size_t) ((bds[21]<<24)+(bds[22]<<16)+(bds[23]<<8)+bds[24]));
+  else
+    sourceLen = ((size_t) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+
+  nerr = grib1Sections(dbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (0);
+    }
+
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (0);
+    }
+
+  dest = bds + datstart;
+   if ( llarge )
+    destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+  else
+    destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+
+  BDS_Flag -= 16;
+
+  bdsLen = datstart + destLen;
+
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+  {
+    int status;
+    long i;
+    size_t tmpLen;
+    int bds_ubits;
+    int bits_per_sample;
+#if defined (HAVE_LIBAEC)
+    struct aec_stream strm;
+#else
+    SZ_com_t sz_param;          /* szip parameter block */
+#endif
+
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      bits_per_sample    = 8;
+    else
+#endif
+      bits_per_sample    = bds_nbits;
+
+#if defined (HAVE_LIBAEC)
+    strm.bits_per_sample         = bits_per_sample;
+    strm.block_size              = PIXELS_PER_BLOCK;
+    strm.rsi                     = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
+    strm.flags                   = AEC_FLAGS;
+    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
+#else
+    sz_param.options_mask        = OPTIONS_MASK;
+    sz_param.bits_per_pixel      = bits_per_sample;
+    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
+    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
+#endif
+
+    if ( bds_ext )
+      for ( i = 0; i < bds_ext; ++i )
+	bds[bds_head+i] = bds[bds_zoffset+bds_head+i];
+
+    /*
+    fprintf(stderr, "gribUnzip: sourceLen %ld; destLen %ld\n", (long)sourceLen, (long)destLen);
+    fprintf(stderr, "gribUnzip: sourceOff %d; destOff %d\n", bds[12], bds[11]);
+    fprintf(stderr, "gribUnzip: reclen %d; bdslen %d\n", recLen, bdsLen);
+    */
+
+    tmpLen = destLen;
+#if defined (HAVE_LIBAEC)
+    strm.next_in   = source;
+    strm.avail_in  = sourceLen;
+    strm.next_out  = dest;
+    strm.avail_out = tmpLen;
+
+    status = aec_buffer_decode(&strm);
+    if ( status != AEC_OK )
+      Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+
+    tmpLen = strm.total_out;
+#else
+    status = SZ_BufftoBuffDecompress(dest, &tmpLen, source, sourceLen, &sz_param);
+    if ( status != SZ_OK )
+      {
+	if ( status == SZ_NO_ENCODER_ERROR )
+	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_PARAM_ERROR )
+	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_MEM_ERROR )
+	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_OUTBUFF_FULL )
+	  Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else
+	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
+#endif
+    /*
+    fprintf(stderr, "gribUnzip: sl = %ld  dl = %ld   tl = %ld\n",
+	    (long)sourceLen, (long)destLen,(long) tmpLen);
+    */
+    if ( tmpLen != destLen )
+      Warning("unzip size differ: code %3d level %3d  ibuflen %ld ubuflen %ld",
+	      PDS_Parameter, PDS_Level2, (long) destLen, (long) tmpLen);
+
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      {
+	long nelem;
+	unsigned char *pbuf;
+	nelem = tmpLen/3;
+	pbuf = (unsigned char*) malloc(tmpLen);
+	for ( i = 0; i < nelem; i++ )
+	  {
+	    pbuf[3*i  ] = dest[        i];
+	    pbuf[3*i+1] = dest[  nelem+i];
+	    pbuf[3*i+2] = dest[2*nelem+i];
+	  }
+	memcpy(dest, pbuf, tmpLen);
+	free(pbuf);
+      }
+#endif
+
+    bds_ubits = BDS_Flag & 15;
+    BDS_Flag -= bds_ubits;
+
+    if ( (bdsLen%2) == 1 )
+      {
+	BDS_Flag += 8;
+	bds[bdsLen++] = 0;
+      }
+
+    SetLen3(bds, 0, bdsLen);
+
+    gribLen = (bds - dbuf) + bdsLen;
+    
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
+
+    if ( llarge )
+      {
+	long itemp;
+        bdsLen = gribLen - 4;
+	/*
+	  If a very large product, the section 4 length field holds
+	  the number of bytes in the product after section 4 upto
+	  the end of the padding bytes.
+	  This is a fixup to get round the restriction on product lengths
+	  due to the count being only 24 bits. It is only possible because
+	  the (default) rounding for GRIB products is 120 bytes.
+	*/
+	while ( gribLen%120 ) dbuf[gribLen++] = 0;
+
+	if ( gribLen != recLen )
+	  fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
+	
+	itemp = gribLen / (-120);
+	itemp = JP23SET - itemp + 1;
+	
+	SetLen3(dbuf, 4, itemp);
+
+	bdsLen = gribLen - bdsLen;
+	    
+	SetLen3(bds, 0, bdsLen);
+      }
+    else
+      {
+	SetLen3(dbuf, 4, recLen);
+      }
+    /*
+    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
+    */
+    if ( llarge )
+      while ( gribLen%120 ) dbuf[gribLen++] = 0;
+    else
+      while ( gribLen & 7 ) dbuf[gribLen++] = 0;
+    /*
+    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
+    */
+  }
+#else
+  if ( libszwarn )
+    {
+      Warning("Decompression disabled, szlib or libaec not available!");
+      libszwarn = 0;
+    }
+#endif
+
+  return (gribLen);
+}
+#include <stdio.h>
+#include <math.h>
 
 
 /* calculate_pfactor: source code from grib_api-1.8.0 */
@@ -56379,31 +55708,369 @@ double calculate_pfactor(const double* spectralField, long fieldTruncation, long
   return pFactor;
 }
 
-
-void scaleComplex(double *fpdata, int pcStart, int pcScale, int trunc, int inv)
+static
+int rowina2(double *p, int ko, int ki, double *pw,
+	    int kcode, double msval, int *kret)
 {
-  double power;
-  double *scale = (double*) malloc((trunc+1)*sizeof(double));
-  int  n, m;
-  int  index;
-
-  if ( scale == NULL ) SysError("No Memory!");
-
-  if ( pcScale < -10000 || pcScale > 10000 )
-    {
-      fprintf(stderr, " scaleComplex: Invalid power given %6d\n", pcScale);
-      return;
-   }
-
-  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+  /* System generated locals */
+  int pw_dim1, pw_offset, i_1;
 
-  if ( pcScale == 0 ) return;
+  /* Local variables */
+  double zwt1, zrdi, zpos;
+  int jl, ip;
+  double zdo, zwt;
 
-  power = (double) pcScale / 1000.;
-  scale[0] = 1.0;
+  /* Parameter adjustments */
+  --p;
+  pw_dim1 = ko + 3;
+  pw_offset = pw_dim1;
+  pw -= pw_offset;
 
-  for ( n = 1; n <= trunc; n++ )
-    {
+  /* **** ROWINA2 - Interpolation of row of values. */
+  /*     Input Parameters. */
+  /*     ----------------- */
+  /*     P      - Row of values to be interpolated. */
+  /*              Dimension must be at least KO. */
+  /*     KO     - Number of values required. */
+  /*     KI     - Number of values in P on input. */
+  /*     PW     - Working array. */
+  /*              Dimension must be at least (0:KO+2,3). */
+  /*     KCODE  - Interpolation required. */
+  /*              1 , linear. */
+  /*              3 , cubic. */
+  /*     PMSVAL - Value used for missing data indicator. */
+
+  /*     Output Parameters. */
+  /*     ------------------ */
+  /*     P     - Now contains KO values. */
+  /*     KRET  - Return code */
+  /*             0, OK */
+  /*             Non-zero, error */
+
+  /*     Author. */
+  /*     ------- */
+  /*     J.D.Chambers    ECMWF     22.07.94 */
+
+  /*     ********************************    */
+  /*     Section 1.  Linear interpolation .. */
+  /*     ********************************    */
+
+  *kret = 0;
+
+  if ( kcode == 1 )
+    {
+      /*    Move input values to work array */
+      for ( jl = 1; jl <= ki; ++jl )
+	pw[jl + pw_dim1] = p[jl];
+
+      /*    Arrange wrap-around value in work array */
+      pw[ki + 1 + pw_dim1] = p[1];
+
+      /*    Set up constants to be used to figure out weighting for */
+      /*    values in interpolation. */
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+
+      /*    Loop through the output points */
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+
+	  /*    Calculate weight from the start of row */
+	  zpos = (jl - 1) * zdo;
+	  zwt = zpos * zrdi;
+
+	  /*    Get the current array position(minus 1) from the weight - */
+	  /*    note the implicit truncation. */
+	  ip = (int) zwt;
+
+	  /*    If the left value is missing, use the right value */
+	  if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
+	    {
+	      p[jl] = pw[ip + 2 + pw_dim1];
+	    }
+	  /*    If the right value is missing, use the left value */
+	  else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
+	    {
+	      p[jl] = pw[ip + 1 + pw_dim1];
+	    }
+	  /*    If neither missing, interpolate ... */
+	  else
+	    {
+
+	      /*       Adjust the weight to range (0.0 to 1.0) */
+	      zwt -= ip;
+
+	      /*       Interpolate using the weighted values on either side */
+	      /*       of the output point position */
+	      p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
+		zwt * pw[ip + 2 + pw_dim1];
+	    }
+	}
+
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
+
+    }
+  else if ( kcode == 3 )
+    {
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          if ( IS_EQUAL(p[jl], msval) )
+	    {
+	      fprintf(stderr," ROWINA2: ");
+	      fprintf(stderr," Cubic interpolation not supported");
+	      fprintf(stderr," for fields containing missing data.\n");
+	      *kret = 1;
+	      goto L900;
+	    }
+          pw[jl + pw_dim1] = p[jl];
+	}
+      pw[pw_dim1] = p[ki];
+      pw[ki + 1 + pw_dim1] = p[1];
+      pw[ki + 2 + pw_dim1] = p[2];
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          pw[jl + (pw_dim1 << 1)] =
+	        - pw[jl - 1 + pw_dim1] / 3.0 -
+	          pw[jl     + pw_dim1] * 0.5 +
+	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+          pw[jl + 1 + pw_dim1 * 3] =
+                  pw[jl - 1 + pw_dim1] / 6.0 -
+                  pw[jl     + pw_dim1] +
+                  pw[jl + 1 + pw_dim1] * 0.5 +
+                  pw[jl + 2 + pw_dim1] / 3.0;
+	}
+
+      scm0_double(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		  &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+          zpos = (jl - 1) * zdo;
+          zwt = zpos * zrdi;
+          ip = (int) zwt + 1;
+          zwt = zwt + 1.0 - ip;
+          zwt1 = 1.0 - zwt;
+          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+	}
+
+    }
+  else
+    {
+      /*    **************************************    */
+      /*    Section 3.  Invalid interpolation code .. */
+      /*    **************************************    */
+      fprintf(stderr," ROWINA2:");
+      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
+      *kret = 2;
+    }
+
+L900:
+    return 0;
+} /* rowina2 */
+
+
+
+int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
+	    double *ztemp, double msval, int *kret)
+{
+   /* System generated locals */
+   int i_1, i_2;
+   int kcode = 1;
+
+   /* Local variables */
+   int ilii, ilio, icode;
+   double *zline = NULL;
+   double *zwork = NULL;
+   int iregno, iquano, j210, j220, j230, j240, j225;
+
+
+   zline = (double*) malloc(2*klon*sizeof(double));
+   if ( zline == NULL ) SysError("No Memory!");
+
+   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
+   if ( zwork == NULL ) SysError("No Memory!");
+
+   /* Parameter adjustments */
+   --pfield;
+   --kpoint;
+
+/* **** QU2REG - Convert quasi-regular grid data to regular. */
+/*     Input Parameters. */
+/*     ----------------- */
+/*     PFIELD     - Array containing quasi-regular grid */
+/*                  data. */
+/*     KPOINT     - Array containing list of the number of */
+/*                  points on each latitude (or longitude) of */
+/*                  the quasi-regular grid. */
+/*     KLAT       - Number of latitude lines */
+/*     KLON       - Number of longitude lines */
+/*     KCODE      - Interpolation required. */
+/*                  1 , linear - data quasi-regular on */
+/*                               latitude lines. */
+/*                  3 , cubic -  data quasi-regular on */
+/*                               latitude lines. */
+/*                  11, linear - data quasi-regular on */
+/*                               longitude lines. */
+/*                  13, cubic -  data quasi-regular on */
+/*                               longitude lines. */
+/*     PMSVAL     - Value used for missing data indicator. */
+/*     Output Parameters. */
+/*     ------------------ */
+/*     KRET       - return code */
+/*                  0 = OK */
+/*                  non-zero indicates fatal error */
+/*     PFIELD     - Array containing regular grid data. */
+/*     Author. */
+/*     ------- */
+/*     J.D.Chambers     ECMWF      22.07.94 */
+/*     J.D.Chambers     ECMWF      13.09.94 */
+/*     Add return code KRET and remove calls to ABORT. */
+
+
+/* ------------------------------ */
+/* Section 1. Set initial values. */
+/* ------------------------------ */
+
+   *kret = 0;
+
+/* Check input parameters. */
+
+   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
+      fprintf(stderr," QU2REG :");
+      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
+      *kret = 1;
+      goto L900;
+   }
+
+/* Set array indices to 0. */
+
+   ilii = 0;
+   ilio = 0;
+
+/* Establish values of loop parameters. */
+
+   if (kcode > 10) {
+
+/*    Quasi-regular along longitude lines. */
+
+      iquano = klon;
+      iregno = klat;
+      icode = kcode - 10;
+   } else {
+
+/*    Quasi-regular along latitude lines. */
+
+      iquano = klat;
+      iregno = klon;
+      icode = kcode;
+   }
+
+/*     -------------------------------------------------------- */
+/**    Section 2. Interpolate field from quasi to regular grid. */
+/*     -------------------------------------------------------- */
+
+   i_1 = iquano;
+   for (j230 = 1; j230 <= i_1; ++j230) {
+
+      if (iregno != kpoint[j230]) {
+
+/*       Line contains less values than required,so */
+/*       extract quasi-regular grid values for a line */
+
+         i_2 = kpoint[j230];
+         for (j210 = 1; j210 <= i_2; ++j210) {
+            ++ilii;
+            zline[j210 - 1] = pfield[ilii];
+         }
+
+/*       and interpolate this line. */
+
+         rowina2(zline, iregno, kpoint[j230], zwork, icode, msval, kret);
+         if (*kret != 0) goto L900;
+
+/*       Add regular grid values for this line to the
+         temporary array. */
+
+         i_2 = iregno;
+         for (j220 = 1; j220 <= i_2; ++j220) {
+            ++ilio;
+            ztemp[ilio - 1] = zline[j220 - 1];
+         }
+
+      } else {
+
+/*       Line contains the required number of values, so add */
+/*       this line to the temporary array. */
+
+         i_2 = iregno;
+         for (j225 = 1; j225 <= i_2; ++j225) {
+            ++ilio;
+            ++ilii;
+            ztemp[ilio - 1] = pfield[ilii];
+         }
+      }
+   }
+
+/* Copy temporary array to user array. */
+
+   i_1 = klon * klat;
+   for (j240 = 1; j240 <= i_1; ++j240) {
+      pfield[j240] = ztemp[j240 - 1];
+   }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+   free(zline);
+   free(zwork);
+
+   return 0;
+} /* qu2reg2 */
+
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
+{
+  double power;
+  double *scale = (double*) malloc((trunc+1)*sizeof(double));
+  int  n, m;
+  int  index;
+
+  if ( scale == NULL ) SysError("No Memory!");
+
+  if ( pcScale < -10000 || pcScale > 10000 )
+    {
+      fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
+      return;
+   }
+
+  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+
+  if ( pcScale == 0 ) return;
+
+  power = (double) pcScale / 1000.;
+  scale[0] = 1.0;
+
+  for ( n = 1; n <= trunc; n++ )
+    {
       if (pcScale != 1000)
          scale[n] = pow((double) (n*(n+1)), power);
       else
@@ -56440,9 +56107,9 @@ void scaleComplex(double *fpdata, int pcStart, int pcScale, int trunc, int inv)
 }
 
 
-void scatterComplex(double *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
 {
-  double *fphelp = (double*) malloc(nsp*sizeof(double));
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
   int  m, n;
   int  index, inext;
 
@@ -56479,9 +56146,9 @@ void scatterComplex(double *fpdata, int pcStart, int trunc, int nsp)
 }
 
 
-void gatherComplex(double *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
 {
-  double *fphelp = (double*) malloc(nsp*sizeof(double));
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
   int  m, n;
   int  index, inext;
 
@@ -56518,14 +56185,14 @@ void gatherComplex(double *fpdata, int pcStart, int trunc, int nsp)
 }
 
 
-void scm0(double *pdl, double *pdr, double *pfl, double *pfr, int klg)
+void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
 {
   /* System generated locals */
   double r_1;
 
   /* Local variables */
-  double zfac, zeps, zbeta;
   int jl;
+  double zfac, zeps, zbeta;
   double zalpha;
 
   /* **** SCM0   - Apply SCM0 limiter to derivative estimates. */
@@ -56563,178 +56230,9 @@ void scm0(double *pdl, double *pdr, double *pfl, double *pfr, int klg)
     }
 } /* scm0 */
 
-
-int rowina2(double *p, int ko, int ki, double *pw,
-	    int kcode, double msval, int *kret)
-{
-  /* System generated locals */
-  int pw_dim1, pw_offset, i_1;
-
-  /* Local variables */
-  double zwt1, zrdi, zpos;
-  int jl, ip;
-  double zdo, zwt;
-
-  /* Parameter adjustments */
-  --p;
-  pw_dim1 = ko + 3;
-  pw_offset = pw_dim1;
-  pw -= pw_offset;
-
-  /* **** ROWINA2 - Interpolation of row of values. */
-  /*     Input Parameters. */
-  /*     ----------------- */
-  /*     P      - Row of values to be interpolated. */
-  /*              Dimension must be at least KO. */
-  /*     KO     - Number of values required. */
-  /*     KI     - Number of values in P on input. */
-  /*     PW     - Working array. */
-  /*              Dimension must be at least (0:KO+2,3). */
-  /*     KCODE  - Interpolation required. */
-  /*              1 , linear. */
-  /*              3 , cubic. */
-  /*     PMSVAL - Value used for missing data indicator. */
-
-  /*     Output Parameters. */
-  /*     ------------------ */
-  /*     P     - Now contains KO values. */
-  /*     KRET  - Return code */
-  /*             0, OK */
-  /*             Non-zero, error */
-
-  /*     Author. */
-  /*     ------- */
-  /*     J.D.Chambers    ECMWF     22.07.94 */
-
-  /*     ********************************    */
-  /*     Section 1.  Linear interpolation .. */
-  /*     ********************************    */
-
-  *kret = 0;
-
-  if ( kcode == 1 )
-    {
-      /*    Move input values to work array */
-      for ( jl = 1; jl <= ki; ++jl )
-	pw[jl + pw_dim1] = p[jl];
-
-      /*    Arrange wrap-around value in work array */
-      pw[ki + 1 + pw_dim1] = p[1];
-
-      /*    Set up constants to be used to figure out weighting for */
-      /*    values in interpolation. */
-      zrdi = (double) ki;
-      zdo = 1.0 / (double) ko;
-
-      /*    Loop through the output points */
-      for ( jl = 1; jl <= ko; ++jl )
-	{
-
-	  /*    Calculate weight from the start of row */
-	  zpos = (jl - 1) * zdo;
-	  zwt = zpos * zrdi;
-
-	  /*    Get the current array position(minus 1) from the weight - */
-	  /*    note the implicit truncation. */
-	  ip = (int) zwt;
-
-	  /*    If the left value is missing, use the right value */
-	  if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
-	    {
-	      p[jl] = pw[ip + 2 + pw_dim1];
-	    }
-	  /*    If the right value is missing, use the left value */
-	  else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
-	    {
-	      p[jl] = pw[ip + 1 + pw_dim1];
-	    }
-	  /*    If neither missing, interpolate ... */
-	  else
-	    {
-
-	      /*       Adjust the weight to range (0.0 to 1.0) */
-	      zwt -= ip;
-
-	      /*       Interpolate using the weighted values on either side */
-	      /*       of the output point position */
-	      p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
-		zwt * pw[ip + 2 + pw_dim1];
-	    }
-	}
-
-      /*     *******************************    */
-      /*     Section 2.  Cubic interpolation .. */
-      /*     *******************************    */
-
-    }
-  else if ( kcode == 3 )
-    {
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          if ( IS_EQUAL(p[jl], msval) )
-	    {
-	      fprintf(stderr," ROWINA2: ");
-	      fprintf(stderr," Cubic interpolation not supported");
-	      fprintf(stderr," for fields containing missing data.\n");
-	      *kret = 1;
-	      goto L900;
-	    }
-          pw[jl + pw_dim1] = p[jl];
-	}
-      pw[pw_dim1] = p[ki];
-      pw[ki + 1 + pw_dim1] = p[1];
-      pw[ki + 2 + pw_dim1] = p[2];
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          pw[jl + (pw_dim1 << 1)] =
-	        - pw[jl - 1 + pw_dim1] / 3.0 -
-	          pw[jl     + pw_dim1] * 0.5 +
-	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
-          pw[jl + 1 + pw_dim1 * 3] =
-                  pw[jl - 1 + pw_dim1] / 6.0 -
-                  pw[jl     + pw_dim1] +
-                  pw[jl + 1 + pw_dim1] * 0.5 +
-                  pw[jl + 2 + pw_dim1] / 3.0;
-	}
-
-      scm0(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
-	   &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
-
-      zrdi = (double) ki;
-      zdo = 1.0 / (double) ko;
-      for ( jl = 1; jl <= ko; ++jl )
-	{
-          zpos = (jl - 1) * zdo;
-          zwt = zpos * zrdi;
-          ip = (int) zwt + 1;
-          zwt = zwt + 1.0 - ip;
-          zwt1 = 1.0 - zwt;
-          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
-                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
-                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
-                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
-	}
-
-    }
-  else
-    {
-      /*    **************************************    */
-      /*    Section 3.  Invalid interpolation code .. */
-      /*    **************************************    */
-      fprintf(stderr," ROWINA2:");
-      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
-      *kret = 2;
-    }
-
-L900:
-    return 0;
-} /* rowina2 */
-
-
-int rowina3(double *p, int ko, int ki, double *pw,
-	    int kcode, double msval, int *kret, int omisng, int operio, int oveggy)
+static
+int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
+			int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
 {
   /*
 C---->
@@ -56821,10 +56319,12 @@ C     -----------------------------------------------------------------
   int pw_dim1, pw_offset, i_1;
 
   /* Local variables */
-  double zwt1, zrdi, zpos;
   int jl, ip;
+  double zwt1, zrdi, zpos;
   double zdo, zwt;
 
+  UNUSED(omisng);
+
   /* Parameter adjustments */
   --p;
   pw_dim1 = ko + 3;
@@ -56898,27 +56398,25 @@ C     -----------------------------------------------------------------
 	      /*    If neither missing, interpolate ... */
 	      else
 		{
-		  /*       Interpolate using the weighted values on either side */
-		  /*       of the output point position */
-		  p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
-		    zwt * pw[ip + 2 + pw_dim1];
+		  /*  Interpolate using the weighted values on either side */
+		  /*  of the output point position */
+		  p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
+		                  zwt * pw[ip+2 + pw_dim1];
 		}
 	    }
 	}
-
-      /*     *******************************    */
-      /*     Section 2.  Cubic interpolation .. */
-      /*     *******************************    */
-
     }
   else if ( kcode == 3 )
     {
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
       i_1 = ki;
       for ( jl = 1; jl <= i_1; ++jl )
 	{
           if ( IS_EQUAL(p[jl], msval) )
 	    {
-	      fprintf(stderr," ROWINA2: ");
+	      fprintf(stderr," ROWINA3: ");
 	      fprintf(stderr," Cubic interpolation not supported");
 	      fprintf(stderr," for fields containing missing data.\n");
 	      *kret = 1;
@@ -56943,8 +56441,8 @@ C     -----------------------------------------------------------------
                   pw[jl + 2 + pw_dim1] / 3.0;
 	}
 
-      scm0(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
-	   &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+      TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		       &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
 
       zrdi = (double) ki;
       zdo = 1.0 / (double) ko;
@@ -56967,7 +56465,7 @@ C     -----------------------------------------------------------------
       /*    **************************************    */
       /*    Section 3.  Invalid interpolation code .. */
       /*    **************************************    */
-      fprintf(stderr," ROWINA2:");
+      fprintf(stderr," ROWINA3:");
       fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
       *kret = 2;
     }
@@ -56977,169 +56475,8 @@ L900:
 } /* rowina3 */
 
 
-int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
-	    double *ztemp, double msval, int *kret)
-{
-   /* System generated locals */
-   int i_1, i_2;
-   int kcode = 1;
-
-   /* Local variables */
-   int ilii, ilio, icode;
-   double *zline = NULL;
-   double *zwork = NULL;
-   int iregno, iquano, j210, j220, j230, j240, j225;
-
-
-   zline = (double*) malloc(2*klon*sizeof(double));
-   if ( zline == NULL ) SysError("No Memory!");
-
-   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
-   if ( zwork == NULL ) SysError("No Memory!");
-
-   /* Parameter adjustments */
-   --pfield;
-   --kpoint;
-
-/* **** QU2REG - Convert quasi-regular grid data to regular. */
-/*     Input Parameters. */
-/*     ----------------- */
-/*     PFIELD     - Array containing quasi-regular grid */
-/*                  data. */
-/*     KPOINT     - Array containing list of the number of */
-/*                  points on each latitude (or longitude) of */
-/*                  the quasi-regular grid. */
-/*     KLAT       - Number of latitude lines */
-/*     KLON       - Number of longitude lines */
-/*     KCODE      - Interpolation required. */
-/*                  1 , linear - data quasi-regular on */
-/*                               latitude lines. */
-/*                  3 , cubic -  data quasi-regular on */
-/*                               latitude lines. */
-/*                  11, linear - data quasi-regular on */
-/*                               longitude lines. */
-/*                  13, cubic -  data quasi-regular on */
-/*                               longitude lines. */
-/*     PMSVAL     - Value used for missing data indicator. */
-/*     Output Parameters. */
-/*     ------------------ */
-/*     KRET       - return code */
-/*                  0 = OK */
-/*                  non-zero indicates fatal error */
-/*     PFIELD     - Array containing regular grid data. */
-/*     Author. */
-/*     ------- */
-/*     J.D.Chambers     ECMWF      22.07.94 */
-/*     J.D.Chambers     ECMWF      13.09.94 */
-/*     Add return code KRET and remove calls to ABORT. */
-
-
-/* ------------------------------ */
-/* Section 1. Set initial values. */
-/* ------------------------------ */
-
-   *kret = 0;
-
-/* Check input parameters. */
-
-   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
-      fprintf(stderr," QU2REG :");
-      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
-      *kret = 1;
-      goto L900;
-   }
-
-/* Set array indices to 0. */
-
-   ilii = 0;
-   ilio = 0;
-
-/* Establish values of loop parameters. */
-
-   if (kcode > 10) {
-
-/*    Quasi-regular along longitude lines. */
-
-      iquano = klon;
-      iregno = klat;
-      icode = kcode - 10;
-   } else {
-
-/*    Quasi-regular along latitude lines. */
-
-      iquano = klat;
-      iregno = klon;
-      icode = kcode;
-   }
-
-/*     -------------------------------------------------------- */
-/**    Section 2. Interpolate field from quasi to regular grid. */
-/*     -------------------------------------------------------- */
-
-   i_1 = iquano;
-   for (j230 = 1; j230 <= i_1; ++j230) {
-
-      if (iregno != kpoint[j230]) {
-
-/*       Line contains less values than required,so */
-/*       extract quasi-regular grid values for a line */
-
-         i_2 = kpoint[j230];
-         for (j210 = 1; j210 <= i_2; ++j210) {
-            ++ilii;
-            zline[j210 - 1] = pfield[ilii];
-         }
-
-/*       and interpolate this line. */
-
-         rowina2(zline, iregno, kpoint[j230], zwork, icode, msval, kret);
-         if (*kret != 0) goto L900;
-
-/*       Add regular grid values for this line to the
-         temporary array. */
-
-         i_2 = iregno;
-         for (j220 = 1; j220 <= i_2; ++j220) {
-            ++ilio;
-            ztemp[ilio - 1] = zline[j220 - 1];
-         }
-
-      } else {
-
-/*       Line contains the required number of values, so add */
-/*       this line to the temporary array. */
-
-         i_2 = iregno;
-         for (j225 = 1; j225 <= i_2; ++j225) {
-            ++ilio;
-            ++ilii;
-            ztemp[ilio - 1] = pfield[ilii];
-         }
-      }
-   }
-
-/* Copy temporary array to user array. */
-
-   i_1 = klon * klat;
-   for (j240 = 1; j240 <= i_1; ++j240) {
-      pfield[j240] = ztemp[j240 - 1];
-   }
-
-/* -------------------------------------------------------- */
-/* Section 9. Return to calling routine. Format statements. */
-/* -------------------------------------------------------- */
-
-L900:
-
-   free(zline);
-   free(zwork);
-
-   return 0;
-} /* qu2reg2 */
-
-
-int qu2reg3(double *pfield, int *kpoint, int klat, int klon,
-	    double msval, int *kret, int omisng, int operio, int oveggy)
+int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
+			T msval, int *kret, int omisng, int operio, int oveggy)
 {
   /*
 C**** QU2REG3 - Convert quasi-regular grid data to regular.
@@ -57243,18 +56580,18 @@ C
 
    /* Local variables */
    int ilii, ilio, icode;
-   double *ztemp = NULL;
-   double *zline = NULL;
-   double *zwork = NULL;
    int iregno, iquano, j210, j220, j230, j240, j225;
+   T *ztemp = NULL;
+   T *zline = NULL;
+   T *zwork = NULL;
 
-   ztemp = (double*) malloc(klon*klat*sizeof(double));
+   ztemp = (T*) malloc(klon*klat*sizeof(T));
    if ( ztemp == NULL ) SysError("No Memory!");
 
-   zline = (double*) malloc(2*klon*sizeof(double));
+   zline = (T*) malloc(2*klon*sizeof(T));
    if ( zline == NULL ) SysError("No Memory!");
 
-   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
+   zwork = (T*) malloc(3*(2*klon+3)*sizeof(T));
    if ( zwork == NULL ) SysError("No Memory!");
 
    /* Parameter adjustments */
@@ -57319,7 +56656,7 @@ C
 
 /*       and interpolate this line. */
 
-         rowina3(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
+         TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
          if (*kret != 0) goto L900;
 
 /*       Add regular grid values for this line to the
@@ -57364,529 +56701,3182 @@ L900:
 
    return 0;
 } /* qu2reg3 */
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
 
+#endif /* T */
 
-FILE *grprsm = NULL;
-double fref;
-double fmaxval;
-int nfref;
-int nfmaxval;
-int nrnd;
-int ndbg;
-int nvck;
-int nonoff;
-int noabort;
-int num2ok;
-int next2o;
-int nloc2o;
-int nsubce;
-int grib_calendar = -1;
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
 
+void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
+{
+  double power;
+  double *scale = (double*) malloc((trunc+1)*sizeof(double));
+  int  n, m;
+  int  index;
 
-void gribSetCalendar(int calendar)
+  if ( scale == NULL ) SysError("No Memory!");
+
+  if ( pcScale < -10000 || pcScale > 10000 )
+    {
+      fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
+      return;
+   }
+
+  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+
+  if ( pcScale == 0 ) return;
+
+  power = (double) pcScale / 1000.;
+  scale[0] = 1.0;
+
+  for ( n = 1; n <= trunc; n++ )
+    {
+      if (pcScale != 1000)
+         scale[n] = pow((double) (n*(n+1)), power);
+      else
+         scale[n] =     (double) (n*(n+1));
+    }
+
+  if ( inv )
+    for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+
+  /* Scale the values */
+
+  index = 0;
+
+  for ( m = 0;   m < pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n >= pcStart )
+	  {
+	    fpdata[index  ] *= scale[n];
+	    fpdata[index+1] *= scale[n];
+	  }
+	index += 2;
+      }
+
+  for ( m = pcStart; m <= trunc; m++ )
+    for ( n = m;     n <= trunc; n++ )
+      {
+	fpdata[index  ] *= scale[n];
+	fpdata[index+1] *= scale[n];
+	index += 2;
+      }
+
+  free(scale);
+}
+
+
+void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
 {
-  grib_calendar = calendar;
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
 }
 
 
-void grsdef(void)
+void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+{
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
+}
+
+
+void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
+{
+  /* System generated locals */
+  double r_1;
+
+  /* Local variables */
+  int jl;
+  double zfac, zeps, zbeta;
+  double zalpha;
+
+  /* **** SCM0   - Apply SCM0 limiter to derivative estimates. */
+  /* output: */
+  /*   pdl   = the limited derivative at the left edge of the interval */
+  /*   pdr   = the limited derivative at the right edge of the interval */
+  /* inputs */
+  /*   pdl   = the original derivative at the left edge */
+  /*   pdr   = the original derivative at the right edge */
+  /*   pfl   = function value at the left edge of the interval */
+  /*   pfr   = function value at the right edge of the interval */
+  /*   klg   = number of intervals where the derivatives are limited */
+
+  /*  define constants */
+
+  zeps = 1.0e-12;
+  zfac = (1.0 - zeps) * 3.0;
+
+  for ( jl = 0; jl < klg; ++jl )
+    {
+      if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
+	{
+	  zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
+	  zbeta  = pdr[jl] / (pfr[jl] - pfl[jl]);
+	  if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
+	  if ( zbeta  <= 0.0 ) pdr[jl] = 0.0;
+	  if ( zalpha > zfac ) pdl[jl] = zfac * (pfr[jl] - pfl[jl]);
+	  if ( zbeta  > zfac ) pdr[jl] = zfac * (pfr[jl] - pfl[jl]);
+	}
+      else
+	{
+	  pdl[jl] = 0.0;
+	  pdr[jl] = 0.0;
+	}
+    }
+} /* scm0 */
+
+static
+int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
+			int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
 {
   /*
 C---->
-C**** GRSDEF - Initial (default) setting of common area variables
-C              for GRIBEX package.
+C**** ROWINA3 - Interpolation of row of values.
 C
 C     Purpose.
 C     --------
 C
-C     Sets initial values for common area variables for all
-C     routines of GRIBEX package, if not already done.
+C     Interpolate a row of values.
+C
 C
 C**   Interface.
 C     ----------
 C
-C     CALL GRSDEF
+C     CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
+C
 C
 C     Input Parameters.
 C     -----------------
 C
-C     None.
+C     P      - Row of values to be interpolated.
+C              Dimension must be at least KO.
 C
-C     Output Parameters.
-C     ------------------
+C     KO     - Number of values required.
 C
-C     None.
+C     KI     - Number of values in P on input.
 C
-C     Method.
-C     -------
+C     PW     - Working array.
+C              Dimension must be at least (0:KO+2,3).
 C
-C     Self-explanatory.
+C     KCODE  - Interpolation required.
+C              1 , linear.
+C              3 , cubic.
 C
-C     Externals.
-C     ----------
+C     PMSVAL - Value used for missing data indicator.
 C
-C     None.
+C     OMISNG - True if missing values are present in field.
 C
-C     Reference.
-C     ----------
+C     OPERIO - True if input field is periodic.
 C
-C     See subroutine GRIBEX.
+C     OVEGGY - True if 'nearest neighbour' processing must be used
+C              for interpolation
+C
+C     Output Parameters.
+C     ------------------
+C
+C     P     - Now contains KO values.
+C     KRET  - Return code
+C             0, OK
+C             Non-zero, error
+C
+C
+C     Method.
+C     -------
+C
+C     Linear or cubic interpolation performed as required.
 C
 C     Comments.
 C     ---------
 C
-C     None
+C     This is a version of ROWINA which allows for missing data
+C     values and hence for bitmapped fields.
+C
 C
 C     Author.
 C     -------
 C
-C     J. Clochard, Meteo France, for ECMWF - March 1998.
+C     J.D.Chambers    ECMWF     22.07.94
+C
 C
 C     Modifications.
 C     --------------
 C
-C     J. Clochard, Meteo France, for ECMWF - June 1999.
-C     Add variable NSUBCE.
-C     Use a static variable to determine if initialisation has already
-C     been done. NUSER removed .
-C     Reverse defaults for NEXT2O and NLOC2O, for consistency with
-C     version 13.023 of software .
+C     J.D.Chambers    ECMWF     13.09.94
+C     Add return code KRET and remove calls to ABORT.
 C
-  */
-  /*
-C     ----------------------------------------------------------------
-C*    Section 0 . Definition of variables.
-C     ----------------------------------------------------------------
-  */
-  char *envString;
-  char *env_stream;
-  static int lfirst = TRUE;
-  extern int CGRIBEX_Const;
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C
+C
+C     -----------------------------------------------------------------
+*/
+  /* System generated locals */
+  int pw_dim1, pw_offset, i_1;
 
-  if ( ! lfirst ) return;
+  /* Local variables */
+  int jl, ip;
+  double zwt1, zrdi, zpos;
+  double zdo, zwt;
 
-  /*
-    ----------------------------------------------------------------
-    Section 1 . Set values, conditionally.
-    ----------------------------------------------------------------
-  */
-  /*
-    Common area variables have not been set. Set them.
-    
-    User supplied reference value.
-  */
-  fref   = 0.0;
-  /*
-    Reference value supplied by user flag. Set to off.
-  */
-  nfref  = 0;
-  /*
-    User supplied maximum value.
-  */
-  fmaxval   = 0.0;
-  /*
-    Maximum value supplied by user flag. Set to off.
-  */
-  nfmaxval  = 0;
-  /*
-    Set rounding to 120 bytes on.
-  */
-  nrnd   = 1;
-  /*
-    Set GRIB calendar.
-  */
-  if ( grib_calendar == -1 )
+  UNUSED(omisng);
+
+  /* Parameter adjustments */
+  --p;
+  pw_dim1 = ko + 3;
+  pw_offset = pw_dim1;
+  pw -= pw_offset;
+
+  *kret = 0;
+
+  if ( kcode == 1 )
     {
-      grib_calendar = CALENDAR_PROLEPTIC;
-  
-      envString = getenv("GRIB_CALENDAR");
-      if ( envString )
+      /*    Move input values to work array */
+      for ( jl = 1; jl <= ki; ++jl )
+	pw[jl + pw_dim1] = p[jl];
+
+      if ( operio )
 	{
-	  if      ( strncmp(envString, "standard", 8) == 0 )
-	    grib_calendar = CALENDAR_STANDARD;
-	  else if ( strncmp(envString, "proleptic", 9) == 0 )
-	    grib_calendar = CALENDAR_PROLEPTIC;
-	  else if ( strncmp(envString, "360days", 7) == 0 )
-	    grib_calendar = CALENDAR_360DAYS;
-	  else if ( strncmp(envString, "365days", 7) == 0 )
-	    grib_calendar = CALENDAR_365DAYS;
-	  else if ( strncmp(envString, "366days", 7) == 0 )
-	    grib_calendar = CALENDAR_366DAYS;
-	  else if ( strncmp(envString, "none", 4) == 0 )
-	    grib_calendar = CALENDAR_NONE;
+	  /* Arrange wrap-around value in work array */
+	  pw[ki + 1 + pw_dim1] = p[1];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) ki;
+	  zdo = 1.0 / (double) ko;
+	}
+      else
+	{
+	  /* Repeat last value, to cope with "implicit truncation" below */
+	  pw[ki + 1 + pw_dim1] = p[ki];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) (ki-1);
+	  zdo = 1.0 / (double) (ko-1);
+ 	}
+
+      /*    Loop through the output points */
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+
+	  /* Calculate weight from the start of row */
+	  zpos = (jl - 1) * zdo;
+	  zwt = zpos * zrdi;
+
+	  /* Get the current array position(minus 1) from the weight - */
+	  /* note the implicit truncation. */
+	  ip = (int) zwt;
+		  
+	  /* Adjust the weight to range (0.0 to 1.0) */
+	  zwt -= ip;
+
+          /* If 'nearest neighbour' processing must be used */
+	  if ( oveggy )
+	    {
+              if ( zwt < 0.5 )
+                p[jl] = pw[ip + 1 + pw_dim1];
+	      else
+		p[jl] = pw[ip + 2 + pw_dim1];
+	    }
+	  else
+	    {
+	      /*    If the left value is missing, use the right value */
+	      if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 2 + pw_dim1];
+		}
+	      /*    If the right value is missing, use the left value */
+	      else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 1 + pw_dim1];
+		}
+	      /*    If neither missing, interpolate ... */
+	      else
+		{
+		  /*  Interpolate using the weighted values on either side */
+		  /*  of the output point position */
+		  p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
+		                  zwt * pw[ip+2 + pw_dim1];
+		}
+	    }
+	}
+    }
+  else if ( kcode == 3 )
+    {
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          if ( IS_EQUAL(p[jl], msval) )
+	    {
+	      fprintf(stderr," ROWINA3: ");
+	      fprintf(stderr," Cubic interpolation not supported");
+	      fprintf(stderr," for fields containing missing data.\n");
+	      *kret = 1;
+	      goto L900;
+	    }
+          pw[jl + pw_dim1] = p[jl];
+	}
+      pw[pw_dim1] = p[ki];
+      pw[ki + 1 + pw_dim1] = p[1];
+      pw[ki + 2 + pw_dim1] = p[2];
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          pw[jl + (pw_dim1 << 1)] =
+	        - pw[jl - 1 + pw_dim1] / 3.0 -
+	          pw[jl     + pw_dim1] * 0.5 +
+	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+          pw[jl + 1 + pw_dim1 * 3] =
+                  pw[jl - 1 + pw_dim1] / 6.0 -
+                  pw[jl     + pw_dim1] +
+                  pw[jl + 1 + pw_dim1] * 0.5 +
+                  pw[jl + 2 + pw_dim1] / 3.0;
+	}
+
+      TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		       &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+          zpos = (jl - 1) * zdo;
+          zwt = zpos * zrdi;
+          ip = (int) zwt + 1;
+          zwt = zwt + 1.0 - ip;
+          zwt1 = 1.0 - zwt;
+          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+	}
+
+    }
+  else
+    {
+      /*    **************************************    */
+      /*    Section 3.  Invalid interpolation code .. */
+      /*    **************************************    */
+      fprintf(stderr," ROWINA3:");
+      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
+      *kret = 2;
+    }
+
+L900:
+    return 0;
+} /* rowina3 */
+
+
+int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
+			T msval, int *kret, int omisng, int operio, int oveggy)
+{
+  /*
+C**** QU2REG3 - Convert quasi-regular grid data to regular.
+C
+C     Purpose.
+C     --------
+C
+C     Convert quasi-regular grid data to regular,
+C     using either a linear or cubic interpolation.
+C
+C
+C**   Interface.
+C     ----------
+C
+C     CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
+C    X            OVEGGY)
+C
+C
+C     Input Parameters.
+C     -----------------
+C
+C     PFIELD     - Array containing quasi-regular grid data.
+C
+C     KPOINT     - Array containing list of the number of
+C                  points on each latitude (or longitude) of
+C                  the quasi-regular grid.
+C
+C     KLAT       - Number of latitude lines
+C
+C     KLON       - Number of longitude lines
+C
+C     KCODE      - Interpolation required.
+C                  1 , linear - data quasi-regular on latitude lines.
+C                  3 , cubic -  data quasi-regular on latitude lines.
+C                  11, linear - data quasi-regular on longitude lines.
+C                  13, cubic -  data quasi-regular on longitude lines.
+C
+C     PMSVAL     - Value used for missing data indicator.
+C
+C     OMISNG     - True if missing values are present in field.
+C
+C     OPERIO     - True if input field is periodic.
+C
+C     OVEGGY     - True if 'nearest neighbour' processing must be used
+C                  for interpolation
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     KRET       - return code
+C                  0 = OK
+C                  non-zero indicates fatal error
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     PFIELD     - Array containing regular grid data.
+C
+C
+C     Method.
+C     -------
+C
+C     Data is interpolated and expanded into a temporary array,
+C     which is then copied back into the user's array.
+C     Returns an error code if an invalid interpolation is requested
+C     or field size exceeds array dimensions.
+C
+C     Comments.
+C     ---------
+C
+C     This routine is an adaptation of QU2REG to allow missing data
+C     values, and hence bit mapped fields.
+C
+C
+C     Author.
+C     -------
+C
+C     J.D.Chambers     ECMWF      22.07.94
+C
+C
+C     Modifications.
+C     --------------
+C
+C     J.D.Chambers     ECMWF      13.09.94
+C     Add return code KRET and remove calls to ABORT.
+C
+C     J.D.Chambers     ECMWF        Feb 1997
+C     Allow for 64-bit pointers
+C
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C     Fix message for longitude number out of bounds, and routine
+C     name in title and formats.
+C
+*/
+   /* System generated locals */
+   int i_1, i_2;
+   int kcode = 1;
+
+   /* Local variables */
+   int ilii, ilio, icode;
+   int iregno, iquano, j210, j220, j230, j240, j225;
+   T *ztemp = NULL;
+   T *zline = NULL;
+   T *zwork = NULL;
+
+   ztemp = (T*) malloc(klon*klat*sizeof(T));
+   if ( ztemp == NULL ) SysError("No Memory!");
+
+   zline = (T*) malloc(2*klon*sizeof(T));
+   if ( zline == NULL ) SysError("No Memory!");
+
+   zwork = (T*) malloc(3*(2*klon+3)*sizeof(T));
+   if ( zwork == NULL ) SysError("No Memory!");
+
+   /* Parameter adjustments */
+   --pfield;
+   --kpoint;
+
+/* ------------------------------ */
+/* Section 1. Set initial values. */
+/* ------------------------------ */
+
+   *kret = 0;
+
+/* Check input parameters. */
+
+   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
+      fprintf(stderr," QU2REG :");
+      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
+      *kret = 1;
+      goto L900;
+   }
+
+/* Set array indices to 0. */
+
+   ilii = 0;
+   ilio = 0;
+
+/* Establish values of loop parameters. */
+
+   if (kcode > 10) {
+
+/*    Quasi-regular along longitude lines. */
+
+      iquano = klon;
+      iregno = klat;
+      icode = kcode - 10;
+   } else {
+
+/*    Quasi-regular along latitude lines. */
+
+      iquano = klat;
+      iregno = klon;
+      icode = kcode;
+   }
+
+/*     -------------------------------------------------------- */
+/**    Section 2. Interpolate field from quasi to regular grid. */
+/*     -------------------------------------------------------- */
+
+   i_1 = iquano;
+   for (j230 = 1; j230 <= i_1; ++j230) {
+
+      if (iregno != kpoint[j230]) {
+
+/*       Line contains less values than required,so */
+/*       extract quasi-regular grid values for a line */
+
+         i_2 = kpoint[j230];
+         for (j210 = 1; j210 <= i_2; ++j210) {
+            ++ilii;
+            zline[j210 - 1] = pfield[ilii];
+         }
+
+/*       and interpolate this line. */
+
+         TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
+         if (*kret != 0) goto L900;
+
+/*       Add regular grid values for this line to the
+         temporary array. */
+
+         i_2 = iregno;
+         for (j220 = 1; j220 <= i_2; ++j220) {
+            ++ilio;
+            ztemp[ilio - 1] = zline[j220 - 1];
+         }
+
+      } else {
+
+/*       Line contains the required number of values, so add */
+/*       this line to the temporary array. */
+
+         i_2 = iregno;
+         for (j225 = 1; j225 <= i_2; ++j225) {
+            ++ilio;
+            ++ilii;
+            ztemp[ilio - 1] = pfield[ilii];
+         }
+      }
+   }
+
+/* Copy temporary array to user array. */
+
+   i_1 = klon * klat;
+   for (j240 = 1; j240 <= i_1; ++j240) {
+      pfield[j240] = ztemp[j240 - 1];
+   }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+   free(zwork);
+   free(zline);
+   free(ztemp);
+
+   return 0;
+} /* qu2reg3 */
+
+#endif /* T */
+#include <string.h>
+
+
+
+int gribVersion(unsigned char *is, size_t buffersize)
+{
+  if ( buffersize < 8 )
+    Error("Buffer too small (current size %d)!", (int) buffersize);
+
+  return (GRIB_EDITION(is));
+}
+
+static 
+double GET_Real(unsigned char *grib)
+{
+  int iexp, imant;
+
+  iexp  = GET_UINT1(grib[0]);
+  imant = GET_UINT3(grib[1], grib[2], grib[3]);
+
+  return (decfp2(iexp, imant));
+}
+
+static 
+int decodeIS(unsigned char *is, int *isec0, int *iret)
+{
+  int isLen = 0;
+  int grib1offset;
+  int lgrib = FALSE, lbudg = FALSE, ltide = FALSE;
+
+  /*
+    Octets 1 - 4 : The letters G R I B.
+    Four 8 bit fields.
+  */
+  /*
+    Check letters -> GRIB, BUDG or TIDE.
+  */
+  /*
+    Check that 'GRIB' is found where expected.
+  */
+  if ( GRIB_START(is) ) lgrib = TRUE;
+  /*
+    ECMWF pseudo-grib data uses 'BUDG' and 'TIDE'.
+  */
+  if ( BUDG_START(is) ) lbudg = TRUE;
+  if ( TIDE_START(is) ) ltide = TRUE;
+  /*
+    Data is not GRIB or pseudo-grib.
+  */
+  if ( lgrib == FALSE && lbudg == FALSE && ltide == FALSE )
+    {
+      *iret = 305;
+      gprintf(__func__, "Input data is not GRIB or pseudo-grib.");
+      gprintf(__func__, "Return code = %d", *iret);
+    }
+  if ( lbudg == TRUE || ltide == TRUE )
+    {
+      *iret = 305;
+      gprintf(__func__, "Pseudo-grib data unsupported.");
+      gprintf(__func__, "Return code = %d", *iret);
+    }
+
+  /*
+    Octets 5 - 7 : Length of message.
+    One 24 bit field.
+  */
+  ISEC0_GRIB_Len = GRIB1_SECLEN(is);
+  /*
+    Octet 8 : GRIB Edition Number.
+    One 8 bit field.
+  */
+  ISEC0_GRIB_Version = GRIB_EDITION(is);
+
+  if ( ISEC0_GRIB_Version > 1 )
+    Error("GRIB version %d unsupported!", ISEC0_GRIB_Version);
+
+  grib1offset = ISEC0_GRIB_Version * 4;
+
+  isLen = 4 + grib1offset;
+
+  return (isLen);
+}
+
+static 
+void decodePDS_ECMWF_local_Extension_1(unsigned char *pds, int *isec1)
+{
+  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier       */
+  isec1[37] = GET_UINT1(pds[41]);         /* Class                      */
+  isec1[38] = GET_UINT1(pds[42]);         /* Type                       */
+  isec1[39] = GET_UINT2(pds[43],pds[44]); /* Stream                     */
+  /* isec1[40] = GET_UINT4(pds[45],pds[46],pds[47],pds[48]); */
+  memcpy((char*) &isec1[40], &pds[45], 4);
+  isec1[41] = GET_UINT1(pds[49]);         /* Forecast number            */
+  isec1[42] = GET_UINT1(pds[50]);         /* Total number of forecasts  */
+}
+
+static 
+void decodePDS_DWD_local_Extension_254(unsigned char *pds, int *isec1)
+{
+  long i;
+  int isvn;
+
+  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
+  for ( i = 0; i < 11; i++ ) 
+    { 
+      isec1[37+i] =  GET_UINT1(pds[41+i]);
+    } 
+
+  isvn = GET_UINT2(pds[52],pds[53]);
+  
+  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
+  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
+
+}
+
+static 
+void decodePDS_DWD_local_Extension_253(unsigned char *pds, int *isec1)
+{
+  long i;
+  int isvn;
+
+  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
+  for ( i = 0; i < 11; i++ ) 
+    { 
+      isec1[37+i] =  GET_UINT1(pds[41+i]);
+    } 
+
+  isvn = GET_UINT2(pds[52],pds[53]);
+  
+  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
+  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
+  isec1[50] =  GET_UINT1(pds[54]);         /* User id, specified by table          */
+  isec1[51] =  GET_UINT2(pds[55],pds[56]); /* Experiment identifier                */
+  isec1[52] =  GET_UINT2(pds[57],pds[58]); /* Ensemble identification by table     */
+  isec1[53] =  GET_UINT2(pds[59],pds[60]); /* Number of ensemble members           */
+  isec1[54] =  GET_UINT2(pds[61],pds[62]); /* Actual number of ensemble member     */
+  isec1[55] =  GET_UINT1(pds[63]);         /* Model major version number           */
+  isec1[56] =  GET_UINT1(pds[64]);         /* Model minor version number           */
+
+}
+
+static 
+void decodePDS_MPIM_local_Extension_1(unsigned char *pds, int *isec1)
+{
+  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier            */
+  isec1[37] = GET_UINT1(pds[41]);         /* type of ensemble forecast       */
+  isec1[38] = GET_UINT2(pds[42],pds[43]); /* individual ensemble member      */
+  isec1[39] = GET_UINT2(pds[44],pds[45]); /* number of forecasts in ensemble */
+}
+
+static 
+int decodePDS(unsigned char *pds, int *isec0, int *isec1)
+{
+  int pdsLen;
+
+  pdsLen = PDS_Len;
+
+  ISEC1_CodeTable      = PDS_CodeTable;
+  ISEC1_CenterID       = PDS_CenterID;
+  ISEC1_ModelID        = PDS_ModelID;
+  ISEC1_GridDefinition = PDS_GridDefinition;
+  ISEC1_Sec2Or3Flag    = PDS_Sec2Or3Flag;
+  ISEC1_Parameter      = PDS_Parameter;
+  ISEC1_LevelType      = PDS_LevelType;
+
+  if ( (ISEC1_LevelType !=  20) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_99)        && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)  && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)  && 
+       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)    && 
+       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)     && 
+       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)    && 
+       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) && 
+       (ISEC1_LevelType != 115) && 
+       (ISEC1_LevelType != 117) && 
+       (ISEC1_LevelType != 125) && 
+       (ISEC1_LevelType != 127) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_SEADEPTH)  && 
+       (ISEC1_LevelType != 210) )
+    {
+      ISEC1_Level1 = PDS_Level1;
+      ISEC1_Level2 = PDS_Level2;
+    }
+  else
+    {
+      ISEC1_Level1 = PDS_Level;
+      ISEC1_Level2 = 0;
+    }
+
+  /* ISEC1_Year        = PDS_Year; */
+  ISEC1_Month          = PDS_Month;
+  ISEC1_Day            = PDS_Day;
+  ISEC1_Hour           = PDS_Hour;
+  ISEC1_Minute         = PDS_Minute;
+  ISEC1_TimeUnit       = PDS_TimeUnit;
+  ISEC1_TimePeriod1    = PDS_TimePeriod1;
+  ISEC1_TimePeriod2    = PDS_TimePeriod2;
+  ISEC1_TimeRange      = PDS_TimeRange;
+  ISEC1_AvgNum         = PDS_AvgNum;
+  ISEC1_AvgMiss        = PDS_AvgMiss;
+
+  if ( ISEC0_GRIB_Version == 1 )
+    {
+      ISEC1_Year           = PDS_Year;
+      ISEC1_Century        = PDS_Century;
+      ISEC1_SubCenterID    = PDS_Subcenter;
+      ISEC1_DecScaleFactor = PDS_DecimalScale;
+    }
+  else
+    {
+      int year;
+      year                 = GET_UINT1(pds[12]);
+      if ( year <= 100 )
+	{
+	  ISEC1_Year       = year;
+	  ISEC1_Century    = 1;
+	}
+      else
+	{
+	  ISEC1_Year       = year%100;
+	  ISEC1_Century    = 1 + (year-ISEC1_Year)/100;
+	}
+      ISEC1_SubCenterID    = 0;
+      ISEC1_DecScaleFactor = 0;
+    }
+
+  if ( ISEC1_Year < 0 )
+    {
+      ISEC1_Year    = -ISEC1_Year;
+      ISEC1_Century = -ISEC1_Century;
+    }
+
+  ISEC1_LocalFLag = 0;
+  if ( pdsLen > 28 )
+    {
+      int localextlen;
+      localextlen = pdsLen-28;
+
+      if ( localextlen > 4000 )
+	{
+	  Warning("PDS larger than 4000 bytes not supported!");
+	}
+      else
+	{
+	  ISEC1_LocalFLag = 1;
+
+	  if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
+	    {
+	      if ( pds[40] == 254 ) 
+		{
+		  decodePDS_DWD_local_Extension_254(pds, isec1);
+		}
+	      else if ( pds[40] == 253 )
+		{ 
+		  decodePDS_DWD_local_Extension_253(pds, isec1);
+		}
+	    }
+	  else if ( (ISEC1_CenterID    == 98 && ISEC1_LocalFLag ==  1) ||
+		    (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag ==  1) ||
+		    (ISEC1_CenterID    ==  7 && ISEC1_SubCenterID == 98) )
+	    {
+	      if ( pds[40] == 1 )
+		decodePDS_ECMWF_local_Extension_1(pds, isec1);
+	    }
+	  else if ( ISEC1_CenterID    == 252 && ISEC1_LocalFLag ==  1 )
+	    {
+	      if ( pds[40] == 1 )
+		decodePDS_MPIM_local_Extension_1(pds, isec1);	      
+	    }
+	  else
+	    {
+	      long i;
+	      for ( i = 0; i < localextlen; i++ )
+		{
+		  isec1[24+i] = pds[28+i];
+		}
+	    }
+	}
+    }
+
+  return (pdsLen);
+}
+
+
+void gribPrintSec2_double(int *isec0, int *isec2, double *fsec2) {gribPrintSec2DP(isec0, isec2, fsec2);}
+void gribPrintSec3_double(int *isec0, int *isec3, double *fsec3) {gribPrintSec3DP(isec0, isec3, fsec3);}
+void gribPrintSec4_double(int *isec0, int *isec4, double *fsec4) {gribPrintSec4DP(isec0, isec4, fsec4);}
+void gribPrintSec2_float(int *isec0, int *isec2, float *fsec2) {gribPrintSec2SP(isec0, isec2, fsec2);}
+void gribPrintSec3_float(int *isec0, int *isec3, float *fsec3) {gribPrintSec3SP(isec0, isec3, fsec3);}
+void gribPrintSec4_float(int *isec0, int *isec4, float *fsec4) {gribPrintSec4SP(isec0, isec4, fsec4);}
+
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+static 
+void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				     T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  unsigned int jmask;
+  long i;
+  unsigned int tbits = 0;
+  int n_bits = NumBits;
+  int t_bits = 0;
+      
+  jmask = (1 << n_bits) - 1;
+  for ( i = 0; i < jlend; i++ )
+    {
+      if (n_bits - t_bits > 8)
+	{
+	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+	  bits += 2;
+	  t_bits += 16;
+	}
+
+      while ( t_bits < n_bits )
+	{
+	  tbits = (tbits * 256) + *bits++;
+	  t_bits += 8;
+	}
+      t_bits -= n_bits;
+      fpdata[i] = (tbits >> t_bits) & jmask;
+    }
+  /* at least this vectorizes :) */
+  for ( i = 0; i < jlend; i++ )
+    fpdata[i] = fmin + zscale*fpdata[i];
+}
+
+#if !defined(_MASK_AND_SHIFT_)
+#define _MASK_AND_SHIFT_
+static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+#endif
+
+static 
+void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				      T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  long i;
+  int n_bits = NumBits;
+  int c_bits, j_bits;
+  double jj;
+
+  /* older unoptimized code, not often used */
+  c_bits = 8;
+  for ( i = 0; i < jlend; i++ )
+    {
+      jj = 0.0;
+      j_bits = n_bits;
+      while (c_bits <= j_bits)
+	{
+	  if (c_bits == 8)
+	    {
+	      jj = jj * 256.0  + (double) (*bits++);
+	      j_bits -= 8;
+	    }
+	  else
+	    {
+	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
+	      bits++;
+	      j_bits -= c_bits;
+	      c_bits = 8;
+	    }
+	}
+
+      if (j_bits)
+	{
+	  c_bits -= j_bits;
+	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+	}
+      
+      fpdata[i] = fmin + zscale*jj;
+    }
+} 
+
+static 
+void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits, 
+			      T fmin, T zscale, T *restrict fpdata)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_decode, end_decode;
+#endif
+
+  long i;
+  T dval;
+#if defined (VECTORCODE)
+  GRIBPACK *lgrib = NULL;
+
+  if ( numBits%8 == 0 )
+    {
+      long jlenc = jlend * numBits / 8;
+      if ( jlenc > 0 ) 
+	{
+	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
+	  if ( lgrib == NULL ) SysError("No Memory!");
+
+	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
+	}
+    }
+
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)lgrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
+	  	 (int)lgrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+
+  if ( lgrib ) free(lgrib);
+
+#else
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)igrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(6, "unpack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_decode = mach_absolute_time();
+#endif
+      
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+	  printf("AVX selected ...\n");
+	  avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#elif defined _ENABLE_SSE4_1
+	  printf("SSE4 selected ...\n");
+	  sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#else
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+#endif
+	}
+      else
+	{
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+	}
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_decode = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(6);
+#endif
+    }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
+		 (int)igrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+#endif
+}
+
+#endif /* T */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+static 
+void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				     T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  unsigned int jmask;
+  long i;
+  unsigned int tbits = 0;
+  int n_bits = NumBits;
+  int t_bits = 0;
+      
+  jmask = (1 << n_bits) - 1;
+  for ( i = 0; i < jlend; i++ )
+    {
+      if (n_bits - t_bits > 8)
+	{
+	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+	  bits += 2;
+	  t_bits += 16;
+	}
+
+      while ( t_bits < n_bits )
+	{
+	  tbits = (tbits * 256) + *bits++;
+	  t_bits += 8;
+	}
+      t_bits -= n_bits;
+      fpdata[i] = (tbits >> t_bits) & jmask;
+    }
+  /* at least this vectorizes :) */
+  for ( i = 0; i < jlend; i++ )
+    fpdata[i] = fmin + zscale*fpdata[i];
+}
+
+#if !defined(_MASK_AND_SHIFT_)
+#define _MASK_AND_SHIFT_
+static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+#endif
+
+static 
+void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				      T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  long i;
+  int n_bits = NumBits;
+  int c_bits, j_bits;
+  double jj;
+
+  /* older unoptimized code, not often used */
+  c_bits = 8;
+  for ( i = 0; i < jlend; i++ )
+    {
+      jj = 0.0;
+      j_bits = n_bits;
+      while (c_bits <= j_bits)
+	{
+	  if (c_bits == 8)
+	    {
+	      jj = jj * 256.0  + (double) (*bits++);
+	      j_bits -= 8;
+	    }
+	  else
+	    {
+	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
+	      bits++;
+	      j_bits -= c_bits;
+	      c_bits = 8;
+	    }
+	}
+
+      if (j_bits)
+	{
+	  c_bits -= j_bits;
+	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+	}
+      
+      fpdata[i] = fmin + zscale*jj;
+    }
+} 
+
+static 
+void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits, 
+			      T fmin, T zscale, T *restrict fpdata)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_decode, end_decode;
+#endif
+
+  long i;
+  T dval;
+#if defined (VECTORCODE)
+  GRIBPACK *lgrib = NULL;
+
+  if ( numBits%8 == 0 )
+    {
+      long jlenc = jlend * numBits / 8;
+      if ( jlenc > 0 ) 
+	{
+	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
+	  if ( lgrib == NULL ) SysError("No Memory!");
+
+	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
+	}
+    }
+
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)lgrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
+	  	 (int)lgrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+
+  if ( lgrib ) free(lgrib);
+
+#else
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)igrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(6, "unpack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_decode = mach_absolute_time();
+#endif
+      
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+	  printf("AVX selected ...\n");
+	  avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#elif defined _ENABLE_SSE4_1
+	  printf("SSE4 selected ...\n");
+	  sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#else
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+#endif
+	}
+      else
+	{
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+	}
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_decode = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(6);
+#endif
+    }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
+		 (int)igrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+#endif
+}
+
+#endif /* T */
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+static 
+int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
+{
+  /* int imisng = 0; */
+  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
+  int  locnv = 0, locnl;
+  int  jlenl;
+  long i;
+  int iexp, imant;
+  int ipvpl, ipl;
+  int gdsLen = 0;
+#if defined (VECTORCODE)
+  unsigned char *igrib;
+  GRIBPACK *lgrib = NULL;
+  size_t lGribLen = 0;
+#endif
+
+  *numGridVals = 0;
+
+  memset(isec2, 0, 22*sizeof(int));
+
+  gdsLen = GDS_Len;
+
+  ipvpl = GDS_PVPL;
+  if ( ipvpl == 0 ) ipvpl = 0xFF;
+
+  if ( ipvpl != 0xFF )
+    { /* Either vct or reduced grid */
+      if ( GDS_NV != 0 )
+	{ /* we have vct */
+	  VertCoorTab = TRUE;
+	  ipl =  4*GDS_NV + ipvpl - 1;
+	  if ( ipl < gdsLen )
+	    {
+	      ReducedGrid = TRUE;
+	    }
+	}
+      else
+	{
+	  VertCoorTab = FALSE;
+	  ReducedGrid = TRUE;
+	}
+      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
+    }
+ 
+  if ( ISEC0_GRIB_Version == 0 )
+    {
+      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
+      else                   VertCoorTab = FALSE;
+    }
+  
+  if ( ReducedGrid )
+    {
+      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      jlenl = (gdsLen - locnl)  >> 1;
+      if ( jlenl == GDS_NumLat )
+	{
+	  *numGridVals = 0;
+	  ISEC2_Reduced = TRUE;
+	  for ( i = 0; i < jlenl; i++ )
+	    {
+	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
+	      *numGridVals += ISEC2_RowLon(i);
+	    }
+	}
+      else
+	{
+	  ReducedGrid = FALSE;
+	}
+    }
+
+  ISEC2_GridType = GDS_GridType;
+
+  /*
+     Gaussian grid definition.
+  */
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      ISEC2_NumLat    = GDS_NumLat;
+      if ( ! ReducedGrid )
+	{
+	  ISEC2_NumLon = GDS_NumLon;
+	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+	}
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_LastLat   = GDS_LastLat;
+      ISEC2_LastLon   = GDS_LastLon;
+      ISEC2_LonIncr   = GDS_LonIncr;
+
+      ISEC2_NumPar    = GDS_NumPar;
+      ISEC2_ScanFlag  = GDS_ScanFlag;
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  ISEC2_LatSP     = GDS_LatSP;
+	  ISEC2_LonSP     = GDS_LonSP;
+	  FSEC2_RotAngle  = GDS_RotAngle;
+	}
+      /*
+	if ( Lons != Longitudes || Lats != Latitudes )
+	Error("Latitude/Longitude Conflict");
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+    {
+      ISEC2_NumLon    = GDS_NumLon;
+      ISEC2_NumLat    = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
+      ISEC2_Lambert_dx    = GDS_Lambert_dx;
+      ISEC2_Lambert_dy    = GDS_Lambert_dy;
+      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
+      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
+      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
+      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
+      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
+      ISEC2_ScanFlag      = GDS_ScanFlag;
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
+    {
+      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
+      ISEC2_PentaK  = GDS_PentaK;
+      ISEC2_PentaM  = GDS_PentaM;
+      ISEC2_RepType = GDS_RepType;
+      ISEC2_RepMode = GDS_RepMode;
+      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
+      isec2[ 6] = 0;
+      isec2[ 7] = 0;
+      isec2[ 8] = 0;
+      isec2[ 9] = 0;
+      isec2[10] = 0;
+      /*
+      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+    {
+      ISEC2_GME_NI2    = GDS_GME_NI2;
+      ISEC2_GME_NI3    = GDS_GME_NI3;
+      ISEC2_GME_ND     = GDS_GME_ND;
+      ISEC2_GME_NI     = GDS_GME_NI;
+      ISEC2_GME_AFlag  = GDS_GME_AFlag;
+      ISEC2_GME_LatPP  = GDS_GME_LatPP;
+      ISEC2_GME_LonPP  = GDS_GME_LonPP;
+      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
+      ISEC2_GME_BFlag  = GDS_GME_BFlag;
+      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
+      /*
+      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else
+    {
+      ISEC2_NumLon = GDS_NumLon;
+      ISEC2_NumLat = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      Message("Gridtype %d unsupported", ISEC2_GridType);
+    }
+
+  /*    vertical coordinate parameters for hybrid levels.     */
+  /*    get number of vertical coordinate parameters, if any. */
+
+  ISEC2_NumVCP = 0;
+
+  isec2[17] = 0;
+  isec2[18] = 0;
+
+  if ( VertCoorTab == TRUE )
+    {
+      if ( ISEC0_GRIB_Version  == 0 )
+	{
+	  locnv = 32;
+	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
+	}
+      else
+	{
+	  locnv = GDS_PVPL - 1;
+	  ISEC2_NumVCP = GDS_NV;
+	}
+#if defined (SX)
+      lGribLen = 4*ISEC2_NumVCP;	      
+      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
+
+      igrib = &gds[locnv];
+      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (lgrib[4*i  ]);
+	  imant  =((lgrib[4*i+1]) << 16) +
+	          ((lgrib[4*i+2]) <<  8) +
+	           (lgrib[4*i+3]);
+	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+	}
+
+      free(lgrib);
+#else
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (gds[locnv+4*i  ]);
+	  imant  =((gds[locnv+4*i+1]) << 16) +
+	          ((gds[locnv+4*i+2]) <<  8) +
+	           (gds[locnv+4*i+3]);
+	  fsec2[10+i] = decfp2(iexp,imant);
+	}
+#endif
+    }
+
+  return (gdsLen);
+}
+
+static
+int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4, 
+			  T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
+{
+  unsigned char *igrib;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int lcompress;
+  int jup, kup, mup;
+  int locnd;
+  long jlend;
+  long i;
+  int bds_flag, jscale, imiss;
+  int bds_ubits;
+  int ioff = 0;
+  int iexp, imant;
+  int zoff;
+  int bds_head = 11;
+  double zscale = 0.;
+  T fmin = 0.;
+  T *fpdata = fsec4;
+  int bdsLen;
+  extern int CGRIBEX_Fix_ZSE;
+
+  *iret = 0;
+  igrib = bds;
+
+  memset(isec4, 0, 42*sizeof(int));
+
+  /* get length of binary data block. */
+
+  bdsLen = BDS_Len;
+  /*
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
+
+  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
+
+  bds_flag = BDS_Flag;
+
+  /* 0------- grid point           */
+  /* 1------- spherical harmonics  */
+
+  lspherc = bds_flag >> 7;
+
+  if ( lspherc ) isec4[2] = 128;
+  else           isec4[2] = 0;
+
+  /* -0------  simple packing */
+  /* -1------ complex packing */
+
+  lcomplex = (bds_flag >> 6)&1;
+
+  if ( lcomplex ) isec4[3] = 64;
+  else            isec4[3] =  0;
+
+  /* ---0---- No additional flags */
+  /* ---1---- No additional flags */
+
+  lcompress = (bds_flag >> 4)&1; /* compress */
+
+  if ( lcompress )
+    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
+  else
+    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+
+  /* ----++++ number of unused bits at end of section) */
+
+  bds_ubits = bds_flag & 0xF;
+  
+  /* scale factor (2 bytes) */;
+
+  jscale = BDS_BinScale;
+
+  /* check for missing data indicators. */
+
+  iexp  = bds[ 6];
+  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
+
+  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
+
+  /* convert reference value and scale factor. */
+
+  if ( ! (dfunc == 'J') )
+    if ( imiss == 0 )
+      {
+	fmin = BDS_RefValue;
+	
+	if ( jscale < 0 )
+	  zscale = 1.0/intpow2(-jscale);
+	else
+	  zscale = intpow2(jscale);
+      }
+
+  /* get number of bits in each data value. */
+
+  ISEC4_NumBits = BDS_NumBits;
+
+  /* octet number of start of packed data */
+  /* calculated from start of block 4 - 1 */
+
+  locnd = zoff + bds_head;
+
+  /* if data is in spherical harmonic form, distinguish   */
+  /* between simple/complex packing (lcomplex = 0/1)      */
+
+  if ( lspherc )
+    {
+      if ( !lcomplex )
+	{
+	  /*    no unpacked binary data present */
+
+	  jup = kup = mup = 0;
+
+	  /*    octet number of start of packed data */
+	  /*    calculated from start of block 4 - 1 */
+
+	  ioff   = 1;
+	  locnd += 4*ioff;  /* RealCoef */
+
+	  /*    get real (0,0) coefficient in grib format and     */
+	  /*    convert to floating point.                        */
+
+	  if ( dfunc != 'J' )
+	    {
+	      if ( imiss ) *fpdata++ = 0.0;
+	      else         *fpdata++ = BDS_RealCoef;
+	    }
+	}
+      else /* complex packed spherical harmonics */
+	{
+	  isec4[15] = BDS_PackData;
+	  /*    scaling factor */
+	  isec4[16] = BDS_Power;
+
+	  /*    pentagonal resolution parameters of the */
+	  /*    unpacked section of data field          */
+
+	  jup = bds[zoff+15];
+	  kup = bds[zoff+16];
+	  mup = bds[zoff+17];
+
+	  isec4[zoff+17] = jup;
+	  isec4[zoff+18] = kup;
+	  isec4[zoff+19] = mup;
+
+	  /*    unpacked binary data */
+
+	  locnd += 4; /* 2 + power */
+	  locnd += 3; /* j, k, m   */
+	  ioff   = (jup+1)*(jup+2);
+
+	  if ( dfunc != 'J' )
+	    for ( i = 0; i < ioff; i++ )
+	      {
+		if ( imiss )
+		  *fpdata++ = 0.0;
+		else
+		  {
+		    iexp   = (bds[locnd+4*i  ]);
+		    imant  =((bds[locnd+4*i+1]) << 16) +
+		            ((bds[locnd+4*i+2]) <<  8) +
+		             (bds[locnd+4*i+3]);
+
+		    *fpdata++ = decfp2(iexp,imant);
+		  }
+	      }
+	  
+	  locnd += 4*ioff;  /* RealCoef */
+	}
+    }
+  else
+    {
+      if ( lcomplex )
+	{
+	  *iret = 1999;
+	  gprintf(__func__, " Second order packed grids unsupported!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+    }
+
+  /* Decode data values to floating point and store in fsec4.  */
+  /* First calculate the number of data values.                */
+  /* Take into account that spherical harmonics can be packed  */
+  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
+
+  jlend = bdsLen - locnd;
+
+  if ( ISEC4_NumBits == 0 )
+    {
+      if ( jlend > 1 )
+	{
+	  *iret = 2001;
+	  gprintf(__func__, " Number of bits per data value = 0!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      if ( numGridVals == 0 )
+	{
+	  *iret = 2002;
+	  gprintf(__func__, " Constant field unsupported for this grid type!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      jlend = numGridVals;
+      jlend -= ioff;
+    }
+  else
+    {
+      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
+    }
+
+  ISEC4_NumValues        = jlend + ioff;
+  ISEC4_NumNonMissValues = 0;
+
+  if ( lcompress )
+    {
+      size_t len;
+
+      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
+	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+      else
+        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+
+      ISEC4_NumValues = len*8/ISEC4_NumBits;
+
+      if ( lspherc )
+	{
+	  if ( lcomplex )
+	    ISEC4_NumValues += ioff;
+	  else
+	    ISEC4_NumValues++;
+	}
+    }
+
+  if ( dfunc == 'J' ) return (bdsLen);
+
+  /* check length of output array. */
+  
+  if ( ISEC4_NumValues > fsec4len )
+    {
+      *iret = 710;
+      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
+      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
+      gprintf(__func__, " Return code =  %d", *iret);
+      return (0);
+    }
+
+  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+  else
+    {
+      igrib += locnd;
+
+      TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
+    }
+
+  if ( lspherc && lcomplex )
+    {
+      int pcStart, pcScale;
+      pcStart = isec4[19];
+      pcScale = isec4[16];
+      TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
+      TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
+    }
+
+  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
+    if ( lspherc && !lcomplex )
+      {
+        /* 20100705: Fix ZeroShiftError - Edi Kirk */
+	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
+	  {
+	    T zserr = fsec4[1];
+	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+	  }
+      }
+
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double)-decscale);
+      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+    }
+
+  return (bdsLen);
+}
+
+
+void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
+			     int kleng, int *kword, int dfunc, int *iret)
+{
+  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
+  int gribLen = 0;
+  int gdsIncluded = FALSE;
+  int bmsIncluded = FALSE;
+  int bitmapSize = 0;
+  int imaskSize = 0;
+  int ldebug = FALSE;
+  int llarge = FALSE, l_iorj = FALSE;
+  int lsect2 = FALSE, lsect3 = FALSE;
+  int numGridVals = 0;
+  static int lmissvalinfo = 1;
+
+  UNUSED(kleng);
+
+  *iret = 0;
+
+  grsdef();
+
+  ISEC2_Reduced = FALSE;
+
+  /*
+    ----------------------------------------------------------------
+    IS Indicator Section (Section 0)
+    ----------------------------------------------------------------
+  */
+  is = (unsigned char *) &kgrib[0];
+
+  isLen = decodeIS(is, isec0, iret);
+
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( ISEC0_GRIB_Len < 0 )
+    {
+      if ( ldebug )
+	gprintf(__func__, "Special case, negative length multiplied by -120");
+      llarge = TRUE;
+      ISEC0_GRIB_Len *= (-120);
+    }
+  /*
+    When decoding or calculating length, previous editions
+    of the GRIB code must be taken into account.
+
+    In the table below, covering sections 0 and 1 of the GRIB
+    code, octet numbering is from the beginning of the GRIB
+    message;
+    * indicates that the value is not available in the code edition;
+    R indicates reserved, should be set to 0;
+    Experimental edition is considered as edition -1.
+
+    GRIB code edition -1 has fixed length of 20 octets for
+    section 1, the length not included in the message.
+    GRIB code edition 0 has fixed length of 24 octets for
+    section 1, the length being included in the message.
+    GRIB code edition 1 can have different lengths for section
+    1, the minimum being 28 octets, length being included in
+    the message.
+
+                                         Octet numbers for code
+                                                  editions
+
+                 Contents.                   -1      0      1
+                 ---------                ----------------------
+       Letters GRIB                          1-4    1-4    1-4
+       Total length of GRIB message.          *      *     5-7
+       GRIB code edition number               *      *      8
+       Length of Section 1.                   *     5-7    9-11
+       Reserved octet (R).                    *      8(R)   *
+       Version no. of Code Table 2.           *      *     12
+       Identification of centre.              5      9     13
+       Generating process.                    6     10     14
+       Grid definition .                      7     11     15
+       Flag (Code Table 1).                   8     12     16
+       Indicator of parameter.                9     13     17
+       Indicator of type of level.           10     14     18
+       Height, pressure etc of levels.      11-12  15-16  19-20
+       Year of century.                      13     17     21
+       Month.                                14     18     22
+       Day.                                  15     19     23
+       Hour.                                 16     20     24
+       Minute.                               17     21     25
+       Indicator of unit of time.            18     22     26
+       P1 - Period of time.                  19     23     27
+       P2 - Period of time                  20(R)   24     28
+       or reserved octet (R).
+       Time range indicator.                21(R)   25     29
+       or reserved octet (R).
+       Number included in average.       22-23(R)  26-27  30-31
+       or reserved octet (R).
+       Number missing from average.         24(R)  28(R)   32
+       or reserved octet (R).
+       Century of data.                       *      *     33
+       Designates sub-centre if not 0.        *      *     34
+       Decimal scale factor.                  *      *    35-36
+       Reserved. Set to 0.                    *      *    37-48
+       (Need not be present)
+       For originating centre use only.       *      *    49-nn
+       (Need not be present)
+
+    Identify which GRIB code edition is being decoded.
+
+    In GRIB edition 1, the edition number is in octet 8.
+    In GRIB edition 0, octet 8 is reserved and set to 0.
+    In GRIB edition -1, octet 8 is a flag field and can have a
+    a valid value of 0, 1, 2 or 3.
+
+    However, GRIB edition number 0 has a fixed
+    length of 24, included in the message, for section 1, so
+    if the value extracted from octets 5-7 is 24 and that from
+    octet 8 is 0, it is safe to assume edition 0 of the code.
+
+  */
+  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
+    {
+      /*
+	Set length of GRIB message to missing data value.
+      */
+      ISEC0_GRIB_Len = 0;
+    }
+  /*
+    If Grib Edition 1 and only length is required, go to section 9.
+  */
+  if ( dfunc == 'L' ) goto LABEL900;
+
+  /*
+    ----------------------------------------------------------------
+    PDS Product Definition Section (Section 1)
+    ----------------------------------------------------------------
+  */ 
+  pds = is + isLen;
+
+  pdsLen = decodePDS(pds, isec0, isec1);
+
+  /*
+    ----------------------------------------------------------------
+    GDS Grid Description Section (Section 2)
+    ----------------------------------------------------------------
+  */
+  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
+
+  if ( gdsIncluded )
+    {
+      gds = is + isLen + pdsLen;
+
+      gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+
+  isec3[0] = 0;
+  if ( bmsIncluded )
+    {
+      bms = is + isLen + pdsLen + gdsLen;
+
+      bmsLen = BMS_Len;
+      imaskSize = (bmsLen - 6)<<3;
+      bitmapSize = imaskSize - BMS_UnusedBits;
+      /*
+      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
+      */
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BDS Binary Data Section (Section 4)
+    ----------------------------------------------------------------
+  */
+  bds = is + isLen + pdsLen + gdsLen + bmsLen;
+
+  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
+
+  bdsLen = TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, 
+				 fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
+
+  if ( *iret != 0 ) return;
+
+  ISEC4_NumNonMissValues = ISEC4_NumValues;
+
+  if ( bitmapSize > 0 )
+    {
+      if ( dfunc != 'L' && dfunc != 'J' )
+	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
+	  {
+	    lmissvalinfo = 0;
+	    FSEC3_MissVal = GRIB_MISSVAL;
+	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
+	  }
+
+      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
+      ISEC4_NumValues        = bitmapSize;
+
+      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
+	{
+	  long i, j;
+	  GRIBPACK *pbitmap;
+	  GRIBPACK bitmap;
+	  GRIBPACK *imask;
+
+	  /*
+	  unsigned char *bitmap;
+	  bitmap = BMS_Bitmap;
+	  j = ISEC4_NumNonMissValues;
+	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+	    {
+	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
+		fsec4[i] = fsec4[--j];
+	      else
+		fsec4[i] = FSEC3_MissVal;
+	    }
+	  */
+
+	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
+
+#if defined (VECTORCODE)
+	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
+	  pbitmap = imask;
+#else
+	  pbitmap = BMS_Bitmap;
+#endif
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	  for ( i = imaskSize/8-1; i >= 0; i-- )
+	    {
+	      bitmap = pbitmap[i];
+	      imask[i*8+0] = 1 & (bitmap >> 7);
+	      imask[i*8+1] = 1 & (bitmap >> 6);
+	      imask[i*8+2] = 1 & (bitmap >> 5);
+	      imask[i*8+3] = 1 & (bitmap >> 4);
+	      imask[i*8+4] = 1 & (bitmap >> 3);
+	      imask[i*8+5] = 1 & (bitmap >> 2);
+	      imask[i*8+6] = 1 & (bitmap >> 1);
+	      imask[i*8+7] = 1 & (bitmap);
+	    }
+
+	  j = 0;
+	  for ( i = 0; i < ISEC4_NumValues; i++ )
+	    if ( imask[i] ) j++;
+
+	  if ( ISEC4_NumNonMissValues != j )
+	    {
+	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
+		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
+			j, ISEC4_NumNonMissValues);
+
+	      ISEC4_NumNonMissValues = j;
+	    }
+
+	  if ( dfunc != 'J' )
+	    {
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
+	    }
+
+	  free(imask);
+	}
+    }
+
+  if ( ISEC2_Reduced )
+    {
+      int nlon, nlat;
+      int lsect3, lperio = 1, lveggy;
+      int ilat;
+      int nvalues = 0;
+      int dlon;
+
+      nlat = ISEC2_NumLat;
+      nlon = ISEC2_RowLonPtr[0];
+      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+      for ( ilat = 1; ilat < nlat; ++ilat )
+	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
+
+      dlon = ISEC2_LastLon-ISEC2_FirstLon;
+      if ( dlon < 0 ) dlon += 360000;
+	  
+      if ( nvalues != ISEC4_NumValues )
+	{
+	  *iret = -801;
+	}
+      //printf("nlat %d  nlon %d \n", nlat, nlon);
+      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
+
+      if ( dfunc == 'R' && *iret == -801 )
+	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
+		ISEC4_NumValues, nvalues);
+      
+      if ( dfunc == 'R' && *iret != -801 )
+	{
+	  ISEC2_Reduced = 0;
+	  ISEC2_NumLon = nlon;
+	  ISEC4_NumValues = nlon*nlat;
+
+	  lsect3 = bitmapSize > 0;
+	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
+	          ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
+	           (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+	
+	  (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
+	      
+	  if ( bitmapSize > 0 )
+	    {
+	      long i;
+	      int j = 0;
+	      
+	      for ( i = 0; i < ISEC4_NumValues; i++ )
+		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
+		  
+	      ISEC4_NumNonMissValues = j;
+	    }
+	}
+    }
+
+
+  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
+  esLen = 4;
+
+  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+
+  if ( ISEC0_GRIB_Len )
+    if ( ISEC0_GRIB_Len < gribLen )
+      Warning("Length of GRIB message is inconsistent (grib_message_size=7867 < grib_record_size=9718)!", ISEC0_GRIB_Len, gribLen);
+
+  ISEC0_GRIB_Len = gribLen;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+
+  /*
+    ----------------------------------------------------------------
+    Section 9 . Abort/return to calling routine.
+    ----------------------------------------------------------------
+  */
+ LABEL900:;
+
+  if ( ldebug )
+    {
+      gprintf(__func__, "Section 9.");
+      gprintf(__func__, "Output values set -");
+
+      gribPrintSec0(isec0);
+      gribPrintSec1(isec0, isec1);
+      /*
+	Print section 2 if present.
+      */
+      if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
+
+      if ( ! l_iorj )
+	{
+	  /*
+	    Print section 3 if present.
+	  */
+	  if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
+
+	  TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
+	  /*
+	    Special print for 2D spectra wave field real values in
+	    section 4
+	  */
+	  if ( (isec1[ 0] ==  140) && 
+	       (isec1[ 1] ==   98) && 
+	       (isec1[23] ==    1) && 
+	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
+	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
+	    gribPrintSec4Wave(isec4);
+	}
+    }
+}
+
+#endif /* T */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+static 
+int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
+{
+  /* int imisng = 0; */
+  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
+  int  locnv = 0, locnl;
+  int  jlenl;
+  long i;
+  int iexp, imant;
+  int ipvpl, ipl;
+  int gdsLen = 0;
+#if defined (VECTORCODE)
+  unsigned char *igrib;
+  GRIBPACK *lgrib = NULL;
+  size_t lGribLen = 0;
+#endif
+
+  *numGridVals = 0;
+
+  memset(isec2, 0, 22*sizeof(int));
+
+  gdsLen = GDS_Len;
+
+  ipvpl = GDS_PVPL;
+  if ( ipvpl == 0 ) ipvpl = 0xFF;
+
+  if ( ipvpl != 0xFF )
+    { /* Either vct or reduced grid */
+      if ( GDS_NV != 0 )
+	{ /* we have vct */
+	  VertCoorTab = TRUE;
+	  ipl =  4*GDS_NV + ipvpl - 1;
+	  if ( ipl < gdsLen )
+	    {
+	      ReducedGrid = TRUE;
+	    }
+	}
+      else
+	{
+	  VertCoorTab = FALSE;
+	  ReducedGrid = TRUE;
+	}
+      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
+    }
+ 
+  if ( ISEC0_GRIB_Version == 0 )
+    {
+      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
+      else                   VertCoorTab = FALSE;
+    }
+  
+  if ( ReducedGrid )
+    {
+      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      jlenl = (gdsLen - locnl)  >> 1;
+      if ( jlenl == GDS_NumLat )
+	{
+	  *numGridVals = 0;
+	  ISEC2_Reduced = TRUE;
+	  for ( i = 0; i < jlenl; i++ )
+	    {
+	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
+	      *numGridVals += ISEC2_RowLon(i);
+	    }
+	}
+      else
+	{
+	  ReducedGrid = FALSE;
+	}
+    }
+
+  ISEC2_GridType = GDS_GridType;
+
+  /*
+     Gaussian grid definition.
+  */
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      ISEC2_NumLat    = GDS_NumLat;
+      if ( ! ReducedGrid )
+	{
+	  ISEC2_NumLon = GDS_NumLon;
+	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+	}
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_LastLat   = GDS_LastLat;
+      ISEC2_LastLon   = GDS_LastLon;
+      ISEC2_LonIncr   = GDS_LonIncr;
+
+      ISEC2_NumPar    = GDS_NumPar;
+      ISEC2_ScanFlag  = GDS_ScanFlag;
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  ISEC2_LatSP     = GDS_LatSP;
+	  ISEC2_LonSP     = GDS_LonSP;
+	  FSEC2_RotAngle  = GDS_RotAngle;
 	}
+      /*
+	if ( Lons != Longitudes || Lats != Latitudes )
+	Error("Latitude/Longitude Conflict");
+      */
     }
-  /*
-    Set debug print off.
-  */
-  ndbg   = 0;
-  
-  envString = getenv("GRIBEX_DEBUG");
-  if ( envString != NULL )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
     {
-      if ( !strncmp(envString, "ON", 2) )
-        ndbg = 1;
-      else if( *envString == '1')
-        ndbg = 1;
-      else if( *envString == '2')
-        ndbg = 2;
-      else
-        ndbg = 0;
+      /*
+      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
+      */
     }
-  /*
-    Set GRIBEX compatibility mode.
-  */
-  envString = getenv("GRIB_GRIBEX_MODE_ON");
-  if ( envString != NULL )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
     {
-      if ( atoi(envString) == 1 ) CGRIBEX_Const = 0;
+      /*
+      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
+      */
     }
-
-  /*
-    Set GRIB value checking on.
-  */
-  nvck   = 1;
-  
-  envString = getenv("GRIBEX_CHECK");
-  if ( envString )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
     {
-      if ( !strncmp(envString, "OFF", 3) )
-        nvck = 0;
-      else
-        nvck = 1;
+      ISEC2_NumLon    = GDS_NumLon;
+      ISEC2_NumLat    = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
+      ISEC2_Lambert_dx    = GDS_Lambert_dx;
+      ISEC2_Lambert_dy    = GDS_Lambert_dy;
+      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
+      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
+      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
+      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
+      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
+      ISEC2_ScanFlag      = GDS_ScanFlag;
     }
-  /*
-    See if output stream needs changing
-  */
-  grprsm = stdout;
-  env_stream = getenv("GRPRS_STREAM");
-  if ( env_stream )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
     {
-      if ( isdigit((int) env_stream[0]) )
+      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
+      ISEC2_PentaK  = GDS_PentaK;
+      ISEC2_PentaM  = GDS_PentaM;
+      ISEC2_RepType = GDS_RepType;
+      ISEC2_RepMode = GDS_RepMode;
+      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
+      isec2[ 6] = 0;
+      isec2[ 7] = 0;
+      isec2[ 8] = 0;
+      isec2[ 9] = 0;
+      isec2[10] = 0;
+      /*
+      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+    {
+      ISEC2_GME_NI2    = GDS_GME_NI2;
+      ISEC2_GME_NI3    = GDS_GME_NI3;
+      ISEC2_GME_ND     = GDS_GME_ND;
+      ISEC2_GME_NI     = GDS_GME_NI;
+      ISEC2_GME_AFlag  = GDS_GME_AFlag;
+      ISEC2_GME_LatPP  = GDS_GME_LatPP;
+      ISEC2_GME_LonPP  = GDS_GME_LonPP;
+      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
+      ISEC2_GME_BFlag  = GDS_GME_BFlag;
+      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
+      /*
+      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else
+    {
+      ISEC2_NumLon = GDS_NumLon;
+      ISEC2_NumLat = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      Message("Gridtype %d unsupported", ISEC2_GridType);
+    }
+
+  /*    vertical coordinate parameters for hybrid levels.     */
+  /*    get number of vertical coordinate parameters, if any. */
+
+  ISEC2_NumVCP = 0;
+
+  isec2[17] = 0;
+  isec2[18] = 0;
+
+  if ( VertCoorTab == TRUE )
+    {
+      if ( ISEC0_GRIB_Version  == 0 )
 	{
-	  int unit;
-	  unit = atoi(env_stream);
-	  if ( unit < 1 || unit > 99 )
-	    Warning("Invalid number for GRPRS_STREAM: %d", unit);
-	  else if ( unit == 2 )
-	    grprsm = stderr;
-	  else if ( unit == 6 )
-	    grprsm = stdout;
-	  else
-	    {
-	      char filename[] = "unit.00";
-	      sprintf(filename, "%2.2d", unit);
-	      grprsm = fopen(filename, "w");
-	      if ( ! grprsm )
-		SysError("GRPRS_STREAM = %d", unit);
-	    }
+	  locnv = 32;
+	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
 	}
       else
 	{
-	  if ( env_stream[0] )
-	    {
-	      grprsm = fopen(env_stream, "w");
-	      if ( ! grprsm )
-		SysError("GRPRS_STREAM = %s", env_stream);
-	    }
+	  locnv = GDS_PVPL - 1;
+	  ISEC2_NumVCP = GDS_NV;
+	}
+#if defined (SX)
+      lGribLen = 4*ISEC2_NumVCP;	      
+      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
+
+      igrib = &gds[locnv];
+      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (lgrib[4*i  ]);
+	  imant  =((lgrib[4*i+1]) << 16) +
+	          ((lgrib[4*i+2]) <<  8) +
+	           (lgrib[4*i+3]);
+	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+	}
+
+      free(lgrib);
+#else
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (gds[locnv+4*i  ]);
+	  imant  =((gds[locnv+4*i+1]) << 16) +
+	          ((gds[locnv+4*i+2]) <<  8) +
+	           (gds[locnv+4*i+3]);
+	  fsec2[10+i] = decfp2(iexp,imant);
 	}
+#endif
     }
+
+  return (gdsLen);
+}
+
+static
+int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4, 
+			  T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
+{
+  unsigned char *igrib;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int lcompress;
+  int jup, kup, mup;
+  int locnd;
+  long jlend;
+  long i;
+  int bds_flag, jscale, imiss;
+  int bds_ubits;
+  int ioff = 0;
+  int iexp, imant;
+  int zoff;
+  int bds_head = 11;
+  double zscale = 0.;
+  T fmin = 0.;
+  T *fpdata = fsec4;
+  int bdsLen;
+  extern int CGRIBEX_Fix_ZSE;
+
+  *iret = 0;
+  igrib = bds;
+
+  memset(isec4, 0, 42*sizeof(int));
+
+  /* get length of binary data block. */
+
+  bdsLen = BDS_Len;
   /*
-    Set P factor switch to default, user supplies the P factor.
-  */
-  nonoff = 0;
-  /*
-    Set abort flag to NO abort
-  */
-  noabort = 1;
-  /*
-    Mark common area values set by user.
-  */
-  lfirst = FALSE;
-  /*
-    Exhaustive use of all possible second-order packing methods
-    for HOPER='K'. Set to off.
-  */
-  num2ok  = 0;
-  /*
-    Use of extended second-order packing methods for grid-point
-    encoding (HOPER='C' and 'K'). Set to on.
-  */
-  next2o  = 1;
-  /*
-    Use of non-local second-order packing methods for grid-point
-    encoding (HOPER='C' and 'K'). Set to on.
-  */
-  nloc2o  = 1;
-  /*
-    Use of (all valid) sub-centre values for ECMWF fields encoding .
-    encoding. Set to off.
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
   */
-  nsubce  = 0;
-}
+  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
 
-/* pack 8-bit bytes from 64-bit words to a packed buffer */
-/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (unsigned char) up[i]; */
+  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
 
-long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc)
-{
-#if defined (CRAY)
-  (void) _pack(up, cp, bc, tc);
-#else
-  U_BYTEORDER;
-  unsigned char *cp0;
-  unsigned INT64 upi, *up0, *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
-  long head, trail, inner, i, j;
-  long ipack = sizeof(INT64);
+  bds_flag = BDS_Flag;
+
+  /* 0------- grid point           */
+  /* 1------- spherical harmonics  */
+
+  lspherc = bds_flag >> 7;
+
+  if ( lspherc ) isec4[2] = 128;
+  else           isec4[2] = 0;
+
+  /* -0------  simple packing */
+  /* -1------ complex packing */
+
+  lcomplex = (bds_flag >> 6)&1;
+
+  if ( lcomplex ) isec4[3] = 64;
+  else            isec4[3] =  0;
+
+  /* ---0---- No additional flags */
+  /* ---1---- No additional flags */
+
+  lcompress = (bds_flag >> 4)&1; /* compress */
+
+  if ( lcompress )
+    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
+  else
+    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+
+  /* ----++++ number of unused bits at end of section) */
+
+  bds_ubits = bds_flag & 0xF;
   
-  /* Bytes until first word boundary in destination buffer */
+  /* scale factor (2 bytes) */;
 
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
+  jscale = BDS_BinScale;
 
-  inner = bc - head;
+  /* check for missing data indicators. */
 
-  /* Trailing bytes which do not make a full word */
+  iexp  = bds[ 6];
+  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
 
-  trail = inner & (ipack-1);
+  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
 
-  /* Number of bytes/words to be processed in fast loop */
+  /* convert reference value and scale factor. */
 
-  inner -= trail;
-  inner /= ipack;
+  if ( ! (dfunc == 'J') )
+    if ( imiss == 0 )
+      {
+	fmin = BDS_RefValue;
+	
+	if ( jscale < 0 )
+	  zscale = 1.0/intpow2(-jscale);
+	else
+	  zscale = intpow2(jscale);
+      }
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
-  ip4 = ip0 + 4;
-  ip5 = ip0 + 5;
-  ip6 = ip0 + 6;
-  ip7 = ip0 + 7;
+  /* get number of bits in each data value. */
 
-  up0 = (unsigned INT64 *) (cp + head);
+  ISEC4_NumBits = BDS_NumBits;
 
-  /* Here we should process any bytes until the first word boundary 
-   * of our destination buffer 
-   * That code is missing so far  because our output buffer is 
-   * word aligned by FORTRAN 
-   */
+  /* octet number of start of packed data */
+  /* calculated from start of block 4 - 1 */
 
-  j = 0;
+  locnd = zoff + bds_head;
 
-  if ( IS_BIGENDIAN() )
+  /* if data is in spherical harmonic form, distinguish   */
+  /* between simple/complex packing (lcomplex = 0/1)      */
+
+  if ( lspherc )
     {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-      for ( i = 0 ; i < inner ; i++ )
+      if ( !lcomplex )
 	{
-	  upi =             (   ip0[j]          << 56 ) 
-	                 |  ( ( ip1[j] & 0xFF ) << 48 )
-	                 |  ( ( ip2[j] & 0xFF ) << 40 )
-	                 |  ( ( ip3[j] & 0xFF ) << 32 )
-	                 |  ( ( ip4[j] & 0xFF ) << 24 ) ;
-	  up0[i] = upi   |  ( ( ip5[j] & 0xFF ) << 16 )
-	                 |  ( ( ip6[j] & 0xFF ) <<  8 )
-	                 |    ( ip7[j] & 0xFF ) ;
-	  j += ipack;
+	  /*    no unpacked binary data present */
+
+	  jup = kup = mup = 0;
+
+	  /*    octet number of start of packed data */
+	  /*    calculated from start of block 4 - 1 */
+
+	  ioff   = 1;
+	  locnd += 4*ioff;  /* RealCoef */
+
+	  /*    get real (0,0) coefficient in grib format and     */
+	  /*    convert to floating point.                        */
+
+	  if ( dfunc != 'J' )
+	    {
+	      if ( imiss ) *fpdata++ = 0.0;
+	      else         *fpdata++ = BDS_RealCoef;
+	    }
+	}
+      else /* complex packed spherical harmonics */
+	{
+	  isec4[15] = BDS_PackData;
+	  /*    scaling factor */
+	  isec4[16] = BDS_Power;
+
+	  /*    pentagonal resolution parameters of the */
+	  /*    unpacked section of data field          */
+
+	  jup = bds[zoff+15];
+	  kup = bds[zoff+16];
+	  mup = bds[zoff+17];
+
+	  isec4[zoff+17] = jup;
+	  isec4[zoff+18] = kup;
+	  isec4[zoff+19] = mup;
+
+	  /*    unpacked binary data */
+
+	  locnd += 4; /* 2 + power */
+	  locnd += 3; /* j, k, m   */
+	  ioff   = (jup+1)*(jup+2);
+
+	  if ( dfunc != 'J' )
+	    for ( i = 0; i < ioff; i++ )
+	      {
+		if ( imiss )
+		  *fpdata++ = 0.0;
+		else
+		  {
+		    iexp   = (bds[locnd+4*i  ]);
+		    imant  =((bds[locnd+4*i+1]) << 16) +
+		            ((bds[locnd+4*i+2]) <<  8) +
+		             (bds[locnd+4*i+3]);
+
+		    *fpdata++ = decfp2(iexp,imant);
+		  }
+	      }
+	  
+	  locnd += 4*ioff;  /* RealCoef */
 	}
     }
   else
     {
-      for ( i = 0 ; i < inner ; i++ )
+      if ( lcomplex )
 	{
-	  upi =             (   ip7[j]          << 56 ) 
-	                 |  ( ( ip6[j] & 0xFF ) << 48 )
-                         |  ( ( ip5[j] & 0xFF ) << 40 )
-                         |  ( ( ip4[j] & 0xFF ) << 32 )
-                         |  ( ( ip3[j] & 0xFF ) << 24 ) ;
-	  up0[i] = upi   |  ( ( ip2[j] & 0xFF ) << 16 )
-                         |  ( ( ip1[j] & 0xFF ) <<  8 )
-                         |    ( ip0[j] & 0xFF ) ;
-	  j += ipack;
+	  *iret = 1999;
+	  gprintf(__func__, " Second order packed grids unsupported!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+    }
+
+  /* Decode data values to floating point and store in fsec4.  */
+  /* First calculate the number of data values.                */
+  /* Take into account that spherical harmonics can be packed  */
+  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
+
+  jlend = bdsLen - locnd;
+
+  if ( ISEC4_NumBits == 0 )
+    {
+      if ( jlend > 1 )
+	{
+	  *iret = 2001;
+	  gprintf(__func__, " Number of bits per data value = 0!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      if ( numGridVals == 0 )
+	{
+	  *iret = 2002;
+	  gprintf(__func__, " Constant field unsupported for this grid type!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      jlend = numGridVals;
+      jlend -= ioff;
+    }
+  else
+    {
+      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
+    }
+
+  ISEC4_NumValues        = jlend + ioff;
+  ISEC4_NumNonMissValues = 0;
+
+  if ( lcompress )
+    {
+      size_t len;
+
+      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
+	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+      else
+        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+
+      ISEC4_NumValues = len*8/ISEC4_NumBits;
+
+      if ( lspherc )
+	{
+	  if ( lcomplex )
+	    ISEC4_NumValues += ioff;
+	  else
+	    ISEC4_NumValues++;
 	}
     }
 
-  cp0 = (unsigned char *) ( up0 + inner );
-  if ( trail > 0 )
+  if ( dfunc == 'J' ) return (bdsLen);
+
+  /* check length of output array. */
+  
+  if ( ISEC4_NumValues > fsec4len )
+    {
+      *iret = 710;
+      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
+      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
+      gprintf(__func__, " Return code =  %d", *iret);
+      return (0);
+    }
+
+  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+  else
+    {
+      igrib += locnd;
+
+      TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
+    }
+
+  if ( lspherc && lcomplex )
     {
-      up0[inner] = 0;
-      for ( i = 0 ; i < trail ; i ++ )
-	{
-	  *cp0 = (unsigned char) ip0[ipack*inner+i];
-	  cp0++;
-	}
+      int pcStart, pcScale;
+      pcStart = isec4[19];
+      pcScale = isec4[16];
+      TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
+      TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
     }
 
-  if ( tc != -1 )
+  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
+    if ( lspherc && !lcomplex )
+      {
+        /* 20100705: Fix ZeroShiftError - Edi Kirk */
+	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
+	  {
+	    T zserr = fsec4[1];
+	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+	  }
+      }
+
+  if ( decscale )
     {
-      bc++;
-      *cp0 = (unsigned char) tc;
+      T scale = (T) pow(10.0, (double)-decscale);
+      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
     }
-#endif
-  return (bc);
+
+  return (bdsLen);
 }
 
-/* unpack 8-bit bytes from a packed buffer with 64-bit words */
-/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT64) cp[i]; */
 
-long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc)
+void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
+			     int kleng, int *kword, int dfunc, int *iret)
 {
-  U_BYTEORDER;
-  const unsigned char *cp0;
-  unsigned INT64 *up0;
-  unsigned INT64 *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
-  long head, trail, inner, i, j;
-  long offset;
-  long ipack = sizeof(INT64);
+  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
+  int gribLen = 0;
+  int gdsIncluded = FALSE;
+  int bmsIncluded = FALSE;
+  int bitmapSize = 0;
+  int imaskSize = 0;
+  int ldebug = FALSE;
+  int llarge = FALSE, l_iorj = FALSE;
+  int lsect2 = FALSE, lsect3 = FALSE;
+  int numGridVals = 0;
+  static int lmissvalinfo = 1;
 
-  /* Bytes until first word boundary in source buffer */
+  UNUSED(kleng);
 
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
-  if ( head > bc ) head = bc;
+  *iret = 0;
 
-  inner = bc - head;
+  grsdef();
 
-  /* Trailing bytes which do not make a full word */
- 
-  trail = inner & (ipack-1);
- 
-  /* Number of bytes/words to be processed in fast loop */
+  ISEC2_Reduced = FALSE;
 
-  inner -= trail;
-  inner /= ipack;
+  /*
+    ----------------------------------------------------------------
+    IS Indicator Section (Section 0)
+    ----------------------------------------------------------------
+  */
+  is = (unsigned char *) &kgrib[0];
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
-  ip4 = ip0 + 4;
-  ip5 = ip0 + 5;
-  ip6 = ip0 + 6;
-  ip7 = ip0 + 7;
+  isLen = decodeIS(is, isec0, iret);
 
-  up0 = (unsigned INT64 *) (cp + head);
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( ISEC0_GRIB_Len < 0 )
+    {
+      if ( ldebug )
+	gprintf(__func__, "Special case, negative length multiplied by -120");
+      llarge = TRUE;
+      ISEC0_GRIB_Len *= (-120);
+    }
+  /*
+    When decoding or calculating length, previous editions
+    of the GRIB code must be taken into account.
 
-  /* Process any bytes until the first word boundary 
-   * of our source buffer 
-   */
-  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT64) cp[i];
+    In the table below, covering sections 0 and 1 of the GRIB
+    code, octet numbering is from the beginning of the GRIB
+    message;
+    * indicates that the value is not available in the code edition;
+    R indicates reserved, should be set to 0;
+    Experimental edition is considered as edition -1.
 
-  j = 0;
+    GRIB code edition -1 has fixed length of 20 octets for
+    section 1, the length not included in the message.
+    GRIB code edition 0 has fixed length of 24 octets for
+    section 1, the length being included in the message.
+    GRIB code edition 1 can have different lengths for section
+    1, the minimum being 28 octets, length being included in
+    the message.
 
-  if ( IS_BIGENDIAN() )
-    {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  ip0[j] = (up0[i] >> 56) & 0xFF;
-	  ip1[j] = (up0[i] >> 48) & 0xFF;
-	  ip2[j] = (up0[i] >> 40) & 0xFF;
-	  ip3[j] = (up0[i] >> 32) & 0xFF;
-	  ip4[j] = (up0[i] >> 24) & 0xFF;
-	  ip5[j] = (up0[i] >> 16) & 0xFF;
-	  ip6[j] = (up0[i] >>  8) & 0xFF;
-	  ip7[j] = (up0[i])       & 0xFF;
+                                         Octet numbers for code
+                                                  editions
 
-	  j += ipack;
-	}
-    }
-  else
-    {
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  ip7[j] = (up0[i] >> 56) & 0xFF;
-	  ip6[j] = (up0[i] >> 48) & 0xFF;
-	  ip5[j] = (up0[i] >> 40) & 0xFF;
-	  ip4[j] = (up0[i] >> 32) & 0xFF;
-	  ip3[j] = (up0[i] >> 24) & 0xFF;
-	  ip2[j] = (up0[i] >> 16) & 0xFF;
-	  ip1[j] = (up0[i] >>  8) & 0xFF;
-	  ip0[j] = (up0[i])       & 0xFF;
+                 Contents.                   -1      0      1
+                 ---------                ----------------------
+       Letters GRIB                          1-4    1-4    1-4
+       Total length of GRIB message.          *      *     5-7
+       GRIB code edition number               *      *      8
+       Length of Section 1.                   *     5-7    9-11
+       Reserved octet (R).                    *      8(R)   *
+       Version no. of Code Table 2.           *      *     12
+       Identification of centre.              5      9     13
+       Generating process.                    6     10     14
+       Grid definition .                      7     11     15
+       Flag (Code Table 1).                   8     12     16
+       Indicator of parameter.                9     13     17
+       Indicator of type of level.           10     14     18
+       Height, pressure etc of levels.      11-12  15-16  19-20
+       Year of century.                      13     17     21
+       Month.                                14     18     22
+       Day.                                  15     19     23
+       Hour.                                 16     20     24
+       Minute.                               17     21     25
+       Indicator of unit of time.            18     22     26
+       P1 - Period of time.                  19     23     27
+       P2 - Period of time                  20(R)   24     28
+       or reserved octet (R).
+       Time range indicator.                21(R)   25     29
+       or reserved octet (R).
+       Number included in average.       22-23(R)  26-27  30-31
+       or reserved octet (R).
+       Number missing from average.         24(R)  28(R)   32
+       or reserved octet (R).
+       Century of data.                       *      *     33
+       Designates sub-centre if not 0.        *      *     34
+       Decimal scale factor.                  *      *    35-36
+       Reserved. Set to 0.                    *      *    37-48
+       (Need not be present)
+       For originating centre use only.       *      *    49-nn
+       (Need not be present)
 
-	  j += ipack;
-	}
-    }
+    Identify which GRIB code edition is being decoded.
 
-  if ( trail > 0 )
+    In GRIB edition 1, the edition number is in octet 8.
+    In GRIB edition 0, octet 8 is reserved and set to 0.
+    In GRIB edition -1, octet 8 is a flag field and can have a
+    a valid value of 0, 1, 2 or 3.
+
+    However, GRIB edition number 0 has a fixed
+    length of 24, included in the message, for section 1, so
+    if the value extracted from octets 5-7 is 24 and that from
+    octet 8 is 0, it is safe to assume edition 0 of the code.
+
+  */
+  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
     {
-      offset = head + ipack*inner;
-      cp0 = cp + offset;
-      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT64) cp0[i];
+      /*
+	Set length of GRIB message to missing data value.
+      */
+      ISEC0_GRIB_Len = 0;
     }
   /*
-  if ( tc != -1 ) {
-    bc++;
-    *cp0 = (unsigned char) tc;
-  }
+    If Grib Edition 1 and only length is required, go to section 9.
   */
-  return (bc);
-}
+  if ( dfunc == 'L' ) goto LABEL900;
 
-/* pack 8-bit bytes from 32-bit words to a packed buffer */
-/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (char) up[i]; */
+  /*
+    ----------------------------------------------------------------
+    PDS Product Definition Section (Section 1)
+    ----------------------------------------------------------------
+  */ 
+  pds = is + isLen;
 
-#if  defined  (INT32)
-long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
-{
-  U_BYTEORDER;
-  unsigned char *cp0;
-  unsigned INT32 *up0, *ip0, *ip1, *ip2, *ip3;
-  long head, trail, inner, i, j;
-  long ipack = sizeof(INT32);
-  
-  /* Bytes until first word boundary in destination buffer */
+  pdsLen = decodePDS(pds, isec0, isec1);
 
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
+  /*
+    ----------------------------------------------------------------
+    GDS Grid Description Section (Section 2)
+    ----------------------------------------------------------------
+  */
+  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
 
-  inner = bc - head;
+  if ( gdsIncluded )
+    {
+      gds = is + isLen + pdsLen;
 
-  /* Trailing bytes which do not make a full word */
+      gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
+    }
 
-  trail = inner & (ipack-1);
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
 
-  /* Number of bytes/words to be processed in fast loop */
+  isec3[0] = 0;
+  if ( bmsIncluded )
+    {
+      bms = is + isLen + pdsLen + gdsLen;
 
-  inner -= trail;
-  inner /= ipack;
+      bmsLen = BMS_Len;
+      imaskSize = (bmsLen - 6)<<3;
+      bitmapSize = imaskSize - BMS_UnusedBits;
+      /*
+      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
+      */
+    }
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
+  /*
+    ----------------------------------------------------------------
+    BDS Binary Data Section (Section 4)
+    ----------------------------------------------------------------
+  */
+  bds = is + isLen + pdsLen + gdsLen + bmsLen;
 
-  up0 = (unsigned INT32 *) (cp + head);
+  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
 
-  /* Here we should process any bytes until the first word boundary 
-   * of our destination buffer 
-   * That code is missing so far  because our output buffer is 
-   * word aligned by FORTRAN 
-   */
+  bdsLen = TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, 
+				 fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
 
-  j = 0;
+  if ( *iret != 0 ) return;
 
-  if ( IS_BIGENDIAN() )
+  ISEC4_NumNonMissValues = ISEC4_NumValues;
+
+  if ( bitmapSize > 0 )
     {
+      if ( dfunc != 'L' && dfunc != 'J' )
+	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
+	  {
+	    lmissvalinfo = 0;
+	    FSEC3_MissVal = GRIB_MISSVAL;
+	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
+	  }
+
+      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
+      ISEC4_NumValues        = bitmapSize;
+
+      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
+	{
+	  long i, j;
+	  GRIBPACK *pbitmap;
+	  GRIBPACK bitmap;
+	  GRIBPACK *imask;
+
+	  /*
+	  unsigned char *bitmap;
+	  bitmap = BMS_Bitmap;
+	  j = ISEC4_NumNonMissValues;
+	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+	    {
+	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
+		fsec4[i] = fsec4[--j];
+	      else
+		fsec4[i] = FSEC3_MissVal;
+	    }
+	  */
+
+	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
+
+#if defined (VECTORCODE)
+	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
+	  pbitmap = imask;
+#else
+	  pbitmap = BMS_Bitmap;
+#endif
+
 #if defined (CRAY)
 #pragma _CRI ivdep
 #endif
@@ -57896,95 +59886,34 @@ long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
 #ifdef __uxpch__
 #pragma loop novrec
 #endif
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  up0[i] =          (   ip0[j]          << 24 ) 
-	                 |  ( ( ip1[j] & 0xFF ) << 16 )
-	                 |  ( ( ip2[j] & 0xFF ) <<  8 )
-	                 |    ( ip3[j] & 0xFF ) ;
-	  j += ipack;
-	}
-    }
-  else
-    {
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  up0[i] =          (   ip3[j]          << 24 ) 
-	                 |  ( ( ip2[j] & 0xFF ) << 16 )
-                         |  ( ( ip1[j] & 0xFF ) <<  8 )
-                         |    ( ip0[j] & 0xFF ) ;
-	  j += ipack;
-	}
-    }
-
-  cp0 = (unsigned char *) ( up0 + inner );
-  if ( trail > 0 )
-    {
-      up0[inner] = 0;
-      for ( i = 0 ; i < trail ; i ++ )
-	{
-	  *cp0 = (unsigned char) ip0[ipack*inner+i];
-	  cp0++;
-	}
-    }
-
-  if ( tc != -1 )
-    {
-      bc++;
-      *cp0 = (unsigned char) tc;
-    }
-
-  return (bc);
-}
-#endif
-
-/* unpack 8-bit bytes from a packed buffer with 32-bit words */
-/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT32) cp[i]; */
-
-#if  defined  (INT32)
-long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
-{
-  U_BYTEORDER;
-  const unsigned char *cp0;
-  unsigned INT32 *up0;
-  unsigned INT32 *ip0, *ip1, *ip2, *ip3;
-  long head, trail, inner, i, j;
-  long offset;
-  long ipack = sizeof(INT32);
-
-  /* Bytes until first word boundary in source buffer */
-
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
-  if ( head > bc ) head = bc;
-
-  inner = bc - head;
-
-  /* Trailing bytes which do not make a full word */
- 
-  trail = inner & (ipack-1);
- 
-  /* Number of bytes/words to be processed in fast loop */
-
-  inner -= trail;
-  inner /= ipack;
-
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
+	  for ( i = imaskSize/8-1; i >= 0; i-- )
+	    {
+	      bitmap = pbitmap[i];
+	      imask[i*8+0] = 1 & (bitmap >> 7);
+	      imask[i*8+1] = 1 & (bitmap >> 6);
+	      imask[i*8+2] = 1 & (bitmap >> 5);
+	      imask[i*8+3] = 1 & (bitmap >> 4);
+	      imask[i*8+4] = 1 & (bitmap >> 3);
+	      imask[i*8+5] = 1 & (bitmap >> 2);
+	      imask[i*8+6] = 1 & (bitmap >> 1);
+	      imask[i*8+7] = 1 & (bitmap);
+	    }
 
-  up0 = (unsigned INT32 *) (cp + head);
+	  j = 0;
+	  for ( i = 0; i < ISEC4_NumValues; i++ )
+	    if ( imask[i] ) j++;
 
-  /* Process any bytes until the first word boundary 
-   * of our source buffer 
-   */
-  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT32) cp[i];
+	  if ( ISEC4_NumNonMissValues != j )
+	    {
+	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
+		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
+			j, ISEC4_NumNonMissValues);
 
-  j = 0;
+	      ISEC4_NumNonMissValues = j;
+	    }
 
-  if ( IS_BIGENDIAN() )
-    {
+	  if ( dfunc != 'J' )
+	    {
 #if defined (CRAY)
 #pragma _CRI ivdep
 #endif
@@ -57994,1814 +59923,2675 @@ long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
 #ifdef __uxpch__
 #pragma loop novrec
 #endif
-      for ( i = 0 ; i < inner ; i++ )
+	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
+	    }
+
+	  free(imask);
+	}
+    }
+
+  if ( ISEC2_Reduced )
+    {
+      int nlon, nlat;
+      int lsect3, lperio = 1, lveggy;
+      int ilat;
+      int nvalues = 0;
+      int dlon;
+
+      nlat = ISEC2_NumLat;
+      nlon = ISEC2_RowLonPtr[0];
+      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+      for ( ilat = 1; ilat < nlat; ++ilat )
+	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
+
+      dlon = ISEC2_LastLon-ISEC2_FirstLon;
+      if ( dlon < 0 ) dlon += 360000;
+	  
+      if ( nvalues != ISEC4_NumValues )
 	{
-	  ip0[j] = (up0[i] >> 24) & 0xFF;
-	  ip1[j] = (up0[i] >> 16) & 0xFF;
-	  ip2[j] = (up0[i] >>  8) & 0xFF;
-	  ip3[j] = (up0[i])       & 0xFF;
+	  *iret = -801;
+	}
+      //printf("nlat %d  nlon %d \n", nlat, nlon);
+      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
 
-	  j += ipack;
+      if ( dfunc == 'R' && *iret == -801 )
+	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
+		ISEC4_NumValues, nvalues);
+      
+      if ( dfunc == 'R' && *iret != -801 )
+	{
+	  ISEC2_Reduced = 0;
+	  ISEC2_NumLon = nlon;
+	  ISEC4_NumValues = nlon*nlat;
+
+	  lsect3 = bitmapSize > 0;
+	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
+	          ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
+	           (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+	
+	  (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
+	      
+	  if ( bitmapSize > 0 )
+	    {
+	      long i;
+	      int j = 0;
+	      
+	      for ( i = 0; i < ISEC4_NumValues; i++ )
+		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
+		  
+	      ISEC4_NumNonMissValues = j;
+	    }
 	}
     }
-  else
-    {
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  ip3[j] = (up0[i] >> 24) & 0xFF;
-	  ip2[j] = (up0[i] >> 16) & 0xFF;
-	  ip1[j] = (up0[i] >>  8) & 0xFF;
-	  ip0[j] = (up0[i])       & 0xFF;
 
-	  j += ipack;
-	}
-    }
 
-  if ( trail > 0 )
-    {
-      offset = head + ipack*inner;
-      cp0 = cp + offset;
-      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT32) cp0[i];
-    }
+  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
+  esLen = 4;
+
+  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+
+  if ( ISEC0_GRIB_Len )
+    if ( ISEC0_GRIB_Len < gribLen )
+      Warning("Length of GRIB message is inconsistent (grib_message_size=7867 < grib_record_size=9718)!", ISEC0_GRIB_Len, gribLen);
+
+  ISEC0_GRIB_Len = gribLen;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+
   /*
-  if ( tc != -1 ) {
-    bc++;
-    *cp0 = (unsigned char) tc;
-  }
+    ----------------------------------------------------------------
+    Section 9 . Abort/return to calling routine.
+    ----------------------------------------------------------------
   */
+ LABEL900:;
 
-  return (bc);
+  if ( ldebug )
+    {
+      gprintf(__func__, "Section 9.");
+      gprintf(__func__, "Output values set -");
+
+      gribPrintSec0(isec0);
+      gribPrintSec1(isec0, isec1);
+      /*
+	Print section 2 if present.
+      */
+      if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
+
+      if ( ! l_iorj )
+	{
+	  /*
+	    Print section 3 if present.
+	  */
+	  if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
+
+	  TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
+	  /*
+	    Special print for 2D spectra wave field real values in
+	    section 4
+	  */
+	  if ( (isec1[ 0] ==  140) && 
+	       (isec1[ 1] ==   98) && 
+	       (isec1[23] ==    1) && 
+	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
+	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
+	    gribPrintSec4Wave(isec4);
+	}
+    }
 }
-#endif
-#include <stdio.h>
 
-void prtbin(int kin, int knbit, int *kout, int *kerr)
-{
-  /*
+#endif /* T */
 
-    Produces a decimal number with ones and zeroes
-    corresponding to the ones and zeroes of the input
-    binary number.
-    eg input number 1011 binary, output number 1011 decimal.
+/* GRIB block 0 - indicator block */
+static
+void encodeIS(GRIBPACK *lGrib, long *gribLen)
+{
+  long z = *gribLen;
 
+  lGrib[0] = 'G';
+  lGrib[1] = 'R';
+  lGrib[2] = 'I';
+  lGrib[3] = 'B';
 
-    Input Parameters:
-    
-       kin   - Integer variable containing binary number.
+  /* 
+   * lGrib[4]-lGrib[6] contains full length of grib record. 
+   * included before finished CODEGB
+   */
 
-       knbit - Number of bits in binary number.
+  z = 7;   
+  Put1Byte(1); /* grib version */
+  z = 8;
 
-    Output Parameters:
+  *gribLen = z;
+}
 
-       kout  - Integer variable containing decimal value
-               with ones and zeroes corresponding to those of
-	       the input binary number.
+/* GRIB block 5 - end block */
+static
+void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
+{
+  long z = *gribLen;
 
-       kerr  - 0, If no error.
-               1, Number of bits in binary number exceeds
-	          maximum allowed or is less than 1.
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
 
+  if ( z > JP23SET )
+    {
+      long itemp;
+      long bdslen = z - 4;
+      /*
+      fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET);
+      exit(1);
+      */
+      /*
+	If a very large product, the section 4 length field holds
+	the number of bytes in the product after section 4 upto
+	the end of the padding bytes.
+	This is a fixup to get round the restriction on product lengths
+	due to the count being only 24 bits. It is only possible because
+	the (default) rounding for GRIB products is 120 bytes.
+      */
+      while ( z%120 ) lGrib[z++] = 0;
 
-    Converted from EMOS routine PRTBIN.
+      if ( z > JP23SET*120 )
+	{
+	  fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET*120);
+	  exit(1);
+	}
 
-       Uwe Schulzweida   MPIfM   01/04/2001
+      itemp = z / (-120);
+      itemp = JP23SET - itemp + 1;
 
-  */
-  int idec;
-  int ik;
-  int itemp;
-  int j;
+      lGrib[4] = itemp >> 16;
+      lGrib[5] = itemp >>  8;
+      lGrib[6] = itemp;
 
-  /*
-    Check length of binary number to ensure decimal number
-    generated will fit in the computer word - in this case will
-    it fit in a Cray 48 bit integer?
-  */
-  if ( knbit < 1 || knbit > 14 )
-    {
-      *kerr = 1;
-      printf(" prtbin : Error in binary number length - %3d bits.\n", knbit);
-      return;
+      bdslen = z - bdslen;
+      lGrib[bdsstart  ] = bdslen >> 16;
+      lGrib[bdsstart+1] = bdslen >>  8;
+      lGrib[bdsstart+2] = bdslen;
     }
   else
-    *kerr = 0;
-  /*
-    -----------------------------------------------------------------
-    Section 1. Generate required number.
-    -----------------------------------------------------------------
-  */
-  *kout = 0;
-  ik    = kin;
-  idec  = 1;
-
-  for ( j = 0; j < knbit; j++ )
     {
-      itemp = ik - ( (ik/2)*2 );
-      *kout = (*kout) + itemp * idec;
-      ik    = ik / 2;
-      idec  = idec * 10;
+      lGrib[4] = z >> 16;
+      lGrib[5] = z >>  8;
+      lGrib[6] = z;
+
+      while ( z%8 ) lGrib[z++] = 0;
     }
 
-  return;
+  *gribLen = z;
 }
 
+/* GRIB block 1 - product definition block. */
 
-void ref2ibm(double *pref, int kbits)
+#define DWD_extension_253_len 38
+#define DWD_extension_254_len 26
+#define ECMWF_extension_1_len 24
+#define MPIM_extension_1_len  18
+
+static
+long getLocalExtLen(int *isec1)
 {
-  /*
+  long extlen = 0;
 
-    Purpose:
-    --------
+  if ( ISEC1_LocalFLag )
+    {
+      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
+	{
+	  if      ( isec1[36] == 254 ) extlen = DWD_extension_254_len;
+	  else if ( isec1[36] == 253 ) extlen = DWD_extension_253_len;
+	}
+      else if ( ISEC1_CenterID == 98 )
+        {
+	  if ( isec1[36] == 1 )   extlen = ECMWF_extension_1_len;
+        }
+      else if ( ISEC1_CenterID == 252 )
+        {
+	  if ( isec1[36] == 1 ) extlen = MPIM_extension_1_len;
+        }
+    }
 
-    Code and check reference value in IBM format
+  return (extlen);
+}
 
-    Input Parameters:
-    -----------------
+static
+long getPdsLen(int *isec1)
+{
+  long pdslen = 28;
 
-    pref       - Reference value
-    kbits      - Number of bits per computer word.
+  pdslen += getLocalExtLen(isec1);
 
-    Output Parameters:
-    ------------------
+  return (pdslen);
+}
 
-    pref       - Reference value
+static
+void encodePDS_DWD_local_Extension_254(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-    Method:
-    -------
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-2; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
 
-    Codes in IBM format, then decides to ensure that reference 
-    value used for packing is not different from that stored
-    because of packing differences.
+  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
+  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
 
-    Externals.
-    ----------
+  *zs = z;
+}
 
-    confp3    - Encode into IBM floating point format.
-    decfp2    - Decode from IBM floating point format.
+static
+void encodePDS_DWD_local_Extension_253(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-    Reference:
-    ----------
+  localextlen = DWD_extension_254_len;
+  for ( i = 0; i < localextlen-2; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
 
-    None.
+  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
+  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
+  Put1Byte(isec1[50]);        /* 55 User id, specified by table       */
+  Put2Byte(isec1[51]);        /* 56 Experiment identifier             */
+  Put2Byte(isec1[52]);        /* 58 Ensemble identification by table  */
+  Put2Byte(isec1[53]);        /* 60 Number of ensemble members        */
+  Put2Byte(isec1[54]);        /* 62 Actual number of ensemble member  */
+  Put1Byte(isec1[55]);        /* 64 Model major version number        */ 
+  Put1Byte(isec1[56]);        /* 65 Model minor version number        */ 
+  Put1Byte(0);                /* 66 Blank for even buffer length      */
 
-    Comments:
-    --------
+  *zs = z;
+}
 
-    None.
+static
+void encodePDS_ECMWF_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  // int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-    Author:
-    -------
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-12; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+                              /* 12 bytes explicitly encoded below:         */
+  Put1Byte(isec1[36]);        /* ECMWF local GRIB use definition identifier */
+                              /*    1=MARS labelling or ensemble fcst. data */
+  Put1Byte(isec1[37]);        /* Class                                      */
+  Put1Byte(isec1[38]);        /* Type                                       */
+  Put2Byte(isec1[39]);        /* Stream                                     */
 
-    J.D.Chambers     ECMWF      17:05:94
+  /* Version number or experiment identifier    */
+  Put1Byte(((unsigned char*) &isec1[40])[0]);
+  Put1Byte(((unsigned char*) &isec1[40])[1]);
+  Put1Byte(((unsigned char*) &isec1[40])[2]);
+  Put1Byte(((unsigned char*) &isec1[40])[3]);
 
-    Modifications:
-    --------------
+  Put1Byte(isec1[41]);        /* Ensemble forecast number                   */
+  Put1Byte(isec1[42]);        /* Total number of forecasts in ensemble      */
+  Put1Byte(0);                /* (Spare)                                    */
 
-    Uwe Schulzweida   MPIfM   01/04/2001
+  *zs = z;
+}
 
-    Convert to C from EMOS library version 130
+static
+void encodePDS_MPIM_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  // int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-  */
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-6; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+                              /* 6 bytes explicitly encoded below:          */
+  Put1Byte(isec1[36]);        /* MPIM local GRIB use definition identifier  */
+                              /*    (extension identifier)                  */
+  Put1Byte(isec1[37]);        /* type of ensemble forecast                  */
+  Put2Byte(isec1[38]);        /* individual ensemble member                 */
+  Put2Byte(isec1[39]);        /* number of forecasts in ensemble            */
 
-  static int itrnd;
-  static int kexp, kmant;
-  static double ztemp, zdumm;
-  extern int CGRIBEX_Debug;
+  *zs = z;
+}
 
-  /* ----------------------------------------------------------------- */
-  /*   Section 1. Convert to and from IBM format.                      */
-  /* ----------------------------------------------------------------- */
+/* GRIB BLOCK 1 - PRODUCT DESCRIPTION SECTION */
+static
+void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
+{
+  GRIBPACK *lGrib = lpds;
+  long z = 0;
+  int ival, century, year;
 
-  /*  Convert floating point reference value to IBM representation. */
+  century = ISEC1_Century;
+  year    = ISEC1_Year;
 
-  itrnd = 1;
-  zdumm = ztemp = *pref;
-  confp3(zdumm, &kexp, &kmant, kbits, itrnd);
+  if ( century < 0 )
+    {
+      century = -century;
+      year    = -year;
+    }
 
-  if ( kexp == 0 && kmant == 0 ) return;
+  Put3Byte(pdsLen);               /*  0 Length of Block 1        */
+  Put1Byte(ISEC1_CodeTable);      /*  3 Local table number       */
+  Put1Byte(ISEC1_CenterID);       /*  4 Identification of centre */
+  Put1Byte(ISEC1_ModelID);        /*  5 Identification of model  */
+  Put1Byte(ISEC1_GridDefinition); /*  6 Grid definition          */
+  Put1Byte(ISEC1_Sec2Or3Flag);    /*  7 Block 2 included         */
+  Put1Byte(ISEC1_Parameter);      /*  8 Parameter Code           */
+  Put1Byte(ISEC1_LevelType);      /*  9 Type of level            */
+  if ( (ISEC1_LevelType !=  20) &&
+       (ISEC1_LevelType != GRIB1_LTYPE_99)         &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)   &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)   &&
+       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)     &&
+       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)      &&
+       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)     &&
+       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH)  &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
+       (ISEC1_LevelType != 115) &&
+       (ISEC1_LevelType != 117) &&
+       (ISEC1_LevelType != 125) &&
+       (ISEC1_LevelType != 127) &&
+       (ISEC1_LevelType != 160) &&
+       (ISEC1_LevelType != 210) )
+    {
+      Put1Byte(ISEC1_Level1);
+      Put1Byte(ISEC1_Level2);
+    }
+  else
+    {
+      Put2Byte(ISEC1_Level1);     /* 10 Level                    */    
+    }
 
-  /*  Set reference value to that actually stored in the GRIB code. */
+  Put1Int(year);                  /* 12 Year of Century          */
+  Put1Byte(ISEC1_Month);          /* 13 Month                    */
+  Put1Byte(ISEC1_Day);            /* 14 Day                      */
+  Put1Byte(ISEC1_Hour);           /* 15 Hour                     */
+  Put1Byte(ISEC1_Minute);         /* 16 Minute                   */
 
-  *pref = decfp2(kexp, kmant);
+  Put1Byte(ISEC1_TimeUnit);       /* 17 Time unit                */
+  if ( ISEC1_TimeRange == 10 )
+    {
+      Put1Byte(ISEC1_TimePeriod1);
+      Put1Byte(ISEC1_TimePeriod2);
+    }
+  else if ( ISEC1_TimeRange == 113 || ISEC1_TimeRange ==   0 )
+    {
+      Put1Byte(ISEC1_TimePeriod1);
+      Put1Byte(0);
+    }
+  else if ( ISEC1_TimeRange ==   5 || ISEC1_TimeRange ==   4 || 
+	    ISEC1_TimeRange ==   3 || ISEC1_TimeRange ==   2 )
+    {
+      Put1Byte(0);
+      Put1Byte(ISEC1_TimePeriod2);
+    }
+  else
+    {
+      Put1Byte(0);
+      Put1Byte(0); 
+    }
+  Put1Byte(ISEC1_TimeRange);      /* 20 Timerange flag           */
+  Put2Byte(ISEC1_AvgNum);         /* 21 Average                  */
 
-  /*  If the nearest number which can be represented in */
-  /*  GRIB format is greater than the reference value,  */
-  /*  find the nearest number in GRIB format lower      */
-  /*  than the reference value.                         */
+  Put1Byte(ISEC1_AvgMiss);        /* 23 Missing from averages    */
+  Put1Byte(century);              /* 24 Century                  */
+  Put1Byte(ISEC1_SubCenterID);    /* 25 Subcenter                */
+  Put2Byte(ISEC1_DecScaleFactor); /* 26 Decimal scale factor     */
 
-  if ( ztemp < *pref )
+  if ( ISEC1_LocalFLag )
     {
-      /*  Convert floating point to GRIB representation */
-      /*  using truncation to ensure that the converted */
-      /*  number is smaller than the original one.      */
+      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
+	{
+	  if      ( isec1[36] == 254 ) encodePDS_DWD_local_Extension_254(lGrib, &z, isec1);
+	  else if ( isec1[36] == 253 ) encodePDS_DWD_local_Extension_253(lGrib, &z, isec1);
+	}
+      else if ( ISEC1_CenterID == 98 )
+	{
+	  if ( isec1[36] == 1 ) encodePDS_ECMWF_local_Extension_1(lGrib, &z, isec1);
+	}
+      else if ( ISEC1_CenterID == 252 )
+	{
+	  if ( isec1[36] == 1 ) encodePDS_MPIM_local_Extension_1(lGrib, &z, isec1);
+	}
+      else
+	{
+	  long i, localextlen;
+	  localextlen = getLocalExtLen(isec1);
+	  for ( i = 0; i < localextlen; i++ )
+	    {
+	      Put1Byte(isec1[24+i]);
+	    }
+	}
+    }
+}
 
-      itrnd = 0;
-      zdumm = *pref = ztemp;
-      confp3(zdumm, &kexp, &kmant, kbits, itrnd);
+int  BitsPerInt = (int) (sizeof(int) * 8);
 
-      /*  Set reference value to that stored in the GRIB code. */
 
-      *pref = decfp2(kexp, kmant);
 
-      if ( ztemp < *pref )
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+static
+void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
+				     const T *data, T zref, T factor, size_t *gz)
+{
+  size_t i, z = *gz;
+  unsigned int ival;
+  int cbits, jbits;
+  unsigned int c;
+  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+    
+  /* code from gribw routine flist2bitstream */
+
+  cbits = 8;
+  c = 0;
+  for ( i = packStart; i < datasize; i++ )
+    {
+      /* note float -> unsigned int .. truncate */
+      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+      /*
+	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
+	if ( ival < 0 ) ival = 0;
+      */
+      jbits = numBits;
+      while ( cbits <= jbits ) 
 	{
-	  if ( CGRIBEX_Debug )
+	  if ( cbits == 8 )
 	    {
-	      Message("Reference value error.");
-	      Message("Notify Met.Applications Section.");
-	      Message("ZTEMP = ", ztemp);
-	      Message("PREF = ", pref);
+	      jbits -= 8;
+	      lGrib[z++] = (ival >> jbits) & 0xFF;
 	    }
-	  *pref = ztemp;
+	  else
+	    {
+	      jbits -= cbits;
+	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+	      cbits = 8;
+	      c = 0;
+	    }
+	}
+      /* now jbits < cbits */
+      if ( jbits )
+	{
+	  c = (c << jbits) + (ival & mask[jbits]);
+	  cbits -= jbits;
 	}
     }
+  if ( cbits != 8 ) lGrib[z++] = c << cbits;
 
-  return;
-} /* ref2ibm */
-#include <string.h>
-
-
-int correct_bdslen(int bdslen, long recsize, long gribpos)
-{
-  /*
-    If a very large product, the section 4 length field holds
-    the number of bytes in the product after section 4 upto
-    the end of the padding bytes.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
-  return (bdslen);
+  *gz = z;
 }
 
-
-int grib1Sections(unsigned char *gribbuffer, long bufsize, unsigned char **pdsp,
-		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp)
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+				    const T *restrict data, T zref, T factor, size_t *gz)
 {
-  unsigned char *pds, *gds, *bms, *bds;
-  unsigned char *bufpointer, *is, *section;
-  int gribversion, grib1offset;
-  long gribsize = 0, recsize;
-  int bdslen;
+  size_t i, z = *gz;
+  uint16_t ui16;
+  T tmp;
 
-  section = gribbuffer;
-  is = gribbuffer;
-  if ( ! GRIB_START(section) )
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; i++ )
     {
-      fprintf(stderr, "Wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
+      tmp = ((data[i] - zref) * factor + 0.5);
+      ui16 = (uint16_t) tmp;
+      lGrib[z  ] = ui16 >>  8;
+      lGrib[z+1] = ui16;
+      z += 2;
     }
 
-  recsize = gribrec_len(section[4], section[5], section[6]);
+  *gz = z;
+}
 
-  gribversion = GRIB_EDITION(section);
-  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
+static
+void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize, 
+			      GRIBPACK *restrict lGrib,
+			      const T *restrict data, 
+			      T zref, T factor, size_t *gz)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_minmax, end_minmax;
+#endif
 
-  if ( gribversion == 1 )
-    grib1offset = 4;
-  else
-    grib1offset = 0;
+  uint32_t ui32;
+  size_t i, z = *gz;
+  T tmp;
 
-  pds = is + 4 + grib1offset;
-  bufpointer = pds + PDS_Len;
-  gribsize += 4 + grib1offset + PDS_Len;
+  data += packStart;
+  datasize -= packStart;
 
-  if ( PDS_HAS_GDS )
-    {
-      gds = bufpointer;
-      bufpointer += GDS_Len;
-      gribsize += GDS_Len;
-    }
-  else
+  if      ( numBits ==  8 )
     {
-      gds = NULL;
-    }
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit base");
+#endif
 
-  if ( PDS_HAS_BMS )
-    {
-      bms = bufpointer;
-      bufpointer += BMS_Len;
-      gribsize += BMS_Len;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+	  lGrib[z  ] = (uint16_t) tmp;
+          z++;
+	}
+
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
     }
-  else
+  else if ( numBits == 16 )
     {
-      bms = NULL;
-    }
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_minmax = mach_absolute_time();
+#endif
 
-  bds = bufpointer;
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, gribsize);
-  bufpointer += bdslen;
-  gribsize += bdslen;
-  gribsize += 4;
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+          avx_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#elif defined _ENABLE_SSE4_1
+          sse41_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#else
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+#endif
+        }
+      else
+        {
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+        }
 
-  if ( gribsize > bufsize )
-    {
-      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", bufsize, gribsize);
-      return (1);
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_minmax = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
     }
-
-  *pdsp = pds;
-  *gdsp = gds;
-  *bmsp = bms;
-  *bdsp = bds;
-
-  /* end section - "7777" in ascii */
-  if ( !GRIB_FIN(bufpointer) )
+  else if ( numBits == 24 )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
-      return (-2);
-    }
-
-  return (0);
-}
-
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit base");
+#endif
 
-int grib2Sections(unsigned char *gribbuffer, long bufsize, unsigned char **idsp,
-		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
-		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp)
-{
-  unsigned char *section;
-  long sec_len;
-  int sec_num;
-  int gribversion;
-  int i, msec;
-  long gribsize;
-  long grib_len = 0;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 16;
+          lGrib[z+1] =  ui32 >>  8;
+          lGrib[z+2] =  ui32;
+          z += 3;
+	}
 
-  *idsp = NULL;
-  *lusp = NULL;
-  *gdsp = NULL;
-  *pdsp = NULL;
-  *drsp = NULL;
-  *bmsp = NULL;
-  *bdsp = NULL;
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
+    }
+  else if ( numBits == 32 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit base");
+#endif
 
-  section = gribbuffer;
-  sec_len = 16;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 24;
+          lGrib[z+1] =  ui32 >> 16;
+          lGrib[z+2] =  ui32 >>  8;
+          lGrib[z+3] =  ui32;
+          z += 4;
+	}
 
-  if ( !GRIB_START(section) )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
+    }
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-
-  gribversion = GRIB_EDITION(section);
-  if ( gribversion != 2 )
+  else if ( numBits == 0 )
     {
-      fprintf(stderr, "wrong GRIB version %d\n", gribversion);
-      return (-1);      
     }
-
-  gribsize = 0;
-  for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | section[8+i];
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 1 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "ids %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 1 )
+  else
     {
-      fprintf(stderr, "Unexpected section1 number %d\n", sec_num);
-      return (-1);
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  *idsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 2 and 3 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "lus %d %ld\n", sec_num, sec_len);
+  *gz = z;
+}
 
-  if ( sec_num == 2 )
-    {
-      *lusp = section;
+static
+void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize, 
+				       GRIBPACK *restrict lGrib,
+				       const T *restrict data, 
+				       T zref, T factor, size_t *gz)
+{
+  U_BYTEORDER;
+  size_t i, j, z = *gz;
+#ifdef _ARCH_PWR6
+#define __UNROLL_DEPTH_2 8
+#else
+#define __UNROLL_DEPTH_2 8
+#endif
+  size_t residual;
+  size_t ofs;
+  T dval[__UNROLL_DEPTH_2];
+  unsigned long ival;
 
-      grib_len += sec_len;
-      section  += sec_len;
+  data += packStart;
+  datasize -= packStart;
+  residual =  datasize % __UNROLL_DEPTH_2;
+  ofs = datasize - residual;
 
-      /* section 3 */
-      sec_len = GRIB2_SECLEN(section);
-      sec_num = GRIB2_SECNUM(section);
-      //fprintf(stderr, "gds %d %ld\n", sec_num, sec_len);
+  // reducing FP operations to single FMA is slowing down on pwr6 ...
 
-      *gdsp = section;
-    }
-  else if ( sec_num == 3 )
+  if      ( numBits ==  8 )
     {
-      *gdsp = section;
+      unsigned char *cgrib = (unsigned char *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      *cgrib++ =  (unsigned long) dval[j];
+	    }
+	  z += __UNROLL_DEPTH_2;
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  *cgrib++ = (unsigned long) dval[j];
+	}
+      z += residual;
+
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
     }
-  else
+  else if ( numBits == 16 )
     {
-      fprintf(stderr, "Unexpected section3 number %d\n", sec_num);
-      return (-1);
+      unsigned short *sgrib = (unsigned short *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *sgrib++ = (unsigned long) dval[j];
+		}
+	      z += 2*__UNROLL_DEPTH_2;
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] = ival >>  8;
+		  lGrib[z+1] = ival;
+		  z += 2;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *sgrib++ = (unsigned long) dval[j];
+	    }
+	  z += 2*residual;
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] = ival >>  8;
+	      lGrib[z+1] = ival;
+	      z += 2;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
     }
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 4 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "pds %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 4 )
+  else if ( numBits == 24 )
     {
-      fprintf(stderr, "Unexpected section4 number %d\n", sec_num);
-      return (-1);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 16;
+	      lGrib[z+1] =  ival >>  8;
+	      lGrib[z+2] =  ival;
+	      z += 3;
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  ival = (unsigned long) dval[j];
+	  lGrib[z  ] =  ival >> 16;
+	  lGrib[z+1] =  ival >>  8;
+	  lGrib[z+2] =  ival;
+	  z += 3;
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
     }
-
-  *pdsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 5 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "drs %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 5 )
+  else if ( numBits == 32 )
     {
-      fprintf(stderr, "Unexpected section5 number %d\n", sec_num);
-      return (-1);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit unrolled");
+#endif
+      unsigned int *igrib = (unsigned int *) (lGrib + z);
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *igrib = (unsigned long) dval[j];
+		  igrib++;
+		  z += 4;
+		}
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] =  ival >> 24;
+		  lGrib[z+1] =  ival >> 16;
+		  lGrib[z+2] =  ival >>  8;
+		  lGrib[z+3] =  ival;
+		  z += 4;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *igrib = (unsigned long) dval[j];
+	      igrib++;
+	      z += 4;
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 24;
+	      lGrib[z+1] =  ival >> 16;
+	      lGrib[z+2] =  ival >>  8;
+	      lGrib[z+3] =  ival;
+	      z += 4;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
     }
-
-  *drsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 6 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "bms %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 6 )
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      fprintf(stderr, "Unexpected section6 number %d\n", sec_num);
-      return (-1);
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-
-  *bmsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 7 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "bds %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 7 )
+  else if ( numBits == 0 )
     {
-      fprintf(stderr, "Unexpected section7 number %d\n", sec_num);
-      return (-1);
     }
-
-  *bdsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* skip multi GRIB sections */
-  msec = 1;
-  while ( !GRIB_FIN(section) )
+  else
     {
-      sec_len = GRIB2_SECLEN(section);
-      sec_num = GRIB2_SECNUM(section);
+      Error("Unimplemented packing factor %d!", numBits);
+    }
 
-      if ( sec_num < 1 || sec_num > 7 ) break;
+  *gz = z;
+#undef __UNROLL_DEPTH_2
+}
 
-      if ( sec_num == 7 )
-	fprintf(stderr, "Skipped unsupported multi GRIB section %d!\n", ++msec);
+#endif /* T */
 
-      if ( (grib_len + sec_len) > gribsize ) break;
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
 
-      grib_len += sec_len;
-      section  += sec_len;
-    }
+static
+void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
+				     const T *data, T zref, T factor, size_t *gz)
+{
+  size_t i, z = *gz;
+  unsigned int ival;
+  int cbits, jbits;
+  unsigned int c;
+  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+    
+  /* code from gribw routine flist2bitstream */
 
-  /* end section - "7777" in ASCII */
-  if ( !GRIB_FIN(section) )
+  cbits = 8;
+  c = 0;
+  for ( i = packStart; i < datasize; i++ )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-2);
+      /* note float -> unsigned int .. truncate */
+      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+      /*
+	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
+	if ( ival < 0 ) ival = 0;
+      */
+      jbits = numBits;
+      while ( cbits <= jbits ) 
+	{
+	  if ( cbits == 8 )
+	    {
+	      jbits -= 8;
+	      lGrib[z++] = (ival >> jbits) & 0xFF;
+	    }
+	  else
+	    {
+	      jbits -= cbits;
+	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+	      cbits = 8;
+	      c = 0;
+	    }
+	}
+      /* now jbits < cbits */
+      if ( jbits )
+	{
+	  c = (c << jbits) + (ival & mask[jbits]);
+	  cbits -= jbits;
+	}
     }
+  if ( cbits != 8 ) lGrib[z++] = c << cbits;
 
-  return (0);
+  *gz = z;
 }
 
-
-int gribGinfo(off_t recpos, long recsize, unsigned char *gribbuffer,
-	      int *intnum, float *fltnum, off_t *bignum)
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+				    const T *restrict data, T zref, T factor, size_t *gz)
 {
-  unsigned char *pds, *gds, *bms, *bds;
-  unsigned char *bufpointer, *is, *section;
-  int gribversion, grib1offset;
-  long gribsize = 0;
-  off_t dpos, bpos = 0;
-  int bdslen;
-  float bsf;
+  size_t i, z = *gz;
+  uint16_t ui16;
+  T tmp;
 
-  section = gribbuffer;
-  is = gribbuffer;
-  if ( ! GRIB_START(section) )
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; i++ )
     {
-      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
+      tmp = ((data[i] - zref) * factor + 0.5);
+      ui16 = (uint16_t) tmp;
+      lGrib[z  ] = ui16 >>  8;
+      lGrib[z+1] = ui16;
+      z += 2;
     }
 
-  gribversion = GRIB_EDITION(section);
-  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
+  *gz = z;
+}
 
-  if ( gribversion == 1 )
-    grib1offset = 4;
-  else
-    grib1offset = 0;
+static
+void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize, 
+			      GRIBPACK *restrict lGrib,
+			      const T *restrict data, 
+			      T zref, T factor, size_t *gz)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_minmax, end_minmax;
+#endif
 
-  pds = is + 4 + grib1offset;
-  bufpointer = pds + PDS_Len;
-  gribsize += 4 + grib1offset + PDS_Len;
+  uint32_t ui32;
+  size_t i, z = *gz;
+  T tmp;
 
-  if ( PDS_HAS_GDS )
-    {
-      gds = bufpointer;
-      bufpointer += GDS_Len;
-      gribsize += GDS_Len;
-    }
-  else
-    {
-      gds = NULL;
-    }
+  data += packStart;
+  datasize -= packStart;
 
-  if ( PDS_HAS_BMS )
+  if      ( numBits ==  8 )
     {
-      bms = bufpointer;
-      bufpointer += BMS_Len;
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit base");
+#endif
 
-      bpos = recpos + gribsize + 6;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+	  lGrib[z  ] = (uint16_t) tmp;
+          z++;
+	}
 
-      gribsize += BMS_Len;
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
     }
-  else
+  else if ( numBits == 16 )
     {
-      bms = NULL;
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_minmax = mach_absolute_time();
+#endif
+
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+          avx_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#elif defined _ENABLE_SSE4_1
+          sse41_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#else
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+#endif
+        }
+      else
+        {
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+        }
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_minmax = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
     }
+  else if ( numBits == 24 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit base");
+#endif
 
-  bds = bufpointer;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 16;
+          lGrib[z+1] =  ui32 >>  8;
+          lGrib[z+2] =  ui32;
+          z += 3;
+	}
 
-  dpos = recpos + gribsize + 11;
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
+    }
+  else if ( numBits == 32 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit base");
+#endif
 
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
-  bufpointer += bdslen;
-  gribsize += bdslen;
-  gribsize += 4;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 24;
+          lGrib[z+1] =  ui32 >> 16;
+          lGrib[z+2] =  ui32 >>  8;
+          lGrib[z+3] =  ui32;
+          z += 4;
+	}
 
-  if ( gribsize > recsize )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
+    }
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", recsize, gribsize);
-      return (1);
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-
-  /* end section - "7777" in ascii */
-  if ( !GRIB_FIN(bufpointer) )
+  else if ( numBits == 0 )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  bsf = BDS_BinScale;
-  if ( bsf > 32767 ) bsf = 32768-bsf;
-  bsf = pow(2.0,(double)bsf);
+  *gz = z;
+}
 
-  bignum[0] = dpos;
-  if ( bms ) bignum[1] = bpos;
-  else       bignum[1] = -999;
-  intnum[0] = BDS_NumBits;
+static
+void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize, 
+				       GRIBPACK *restrict lGrib,
+				       const T *restrict data, 
+				       T zref, T factor, size_t *gz)
+{
+  U_BYTEORDER;
+  size_t i, j, z = *gz;
+#ifdef _ARCH_PWR6
+#define __UNROLL_DEPTH_2 8
+#else
+#define __UNROLL_DEPTH_2 8
+#endif
+  size_t residual;
+  size_t ofs;
+  T dval[__UNROLL_DEPTH_2];
+  unsigned long ival;
 
-  /*  fltnum[0] = 1.0; */
-  fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
-  fltnum[1] = bsf;
-  fltnum[2] = BDS_RefValue;
-  /*
-  printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
-  printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
-  */
-  return (0);
-}
+  data += packStart;
+  datasize -= packStart;
+  residual =  datasize % __UNROLL_DEPTH_2;
+  ofs = datasize - residual;
 
+  // reducing FP operations to single FMA is slowing down on pwr6 ...
 
-void grib1PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int GridType, level, nerr;
-  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-  int bdslen;
+  if      ( numBits ==  8 )
+    {
+      unsigned char *cgrib = (unsigned char *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      *cgrib++ =  (unsigned long) dval[j];
+	    }
+	  z += __UNROLL_DEPTH_2;
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  *cgrib++ = (unsigned long) dval[j];
+	}
+      z += residual;
 
-  if ( header )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
+    }
+  else if ( numBits == 16 )
+    {
+      unsigned short *sgrib = (unsigned short *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *sgrib++ = (unsigned long) dval[j];
+		}
+	      z += 2*__UNROLL_DEPTH_2;
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] = ival >>  8;
+		  lGrib[z+1] = ival;
+		  z += 2;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *sgrib++ = (unsigned long) dval[j];
+	    }
+	  z += 2*residual;
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] = ival >>  8;
+	      lGrib[z+1] = ival;
+	      z += 2;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
+    }
+  else if ( numBits == 24 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 16;
+	      lGrib[z+1] =  ival >>  8;
+	      lGrib[z+2] =  ival;
+	      z += 3;
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  ival = (unsigned long) dval[j];
+	  lGrib[z  ] =  ival >> 16;
+	  lGrib[z+1] =  ival >>  8;
+	  lGrib[z+2] =  ival;
+	  z += 3;
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
+    }
+  else if ( numBits == 32 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit unrolled");
+#endif
+      unsigned int *igrib = (unsigned int *) (lGrib + z);
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *igrib = (unsigned long) dval[j];
+		  igrib++;
+		  z += 4;
+		}
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] =  ival >> 24;
+		  lGrib[z+1] =  ival >> 16;
+		  lGrib[z+2] =  ival >>  8;
+		  lGrib[z+3] =  ival;
+		  z += 4;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *igrib = (unsigned long) dval[j];
+	      igrib++;
+	      z += 4;
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 24;
+	      lGrib[z+1] =  ival >> 16;
+	      lGrib[z+2] =  ival >>  8;
+	      lGrib[z+3] =  ival;
+	      z += 4;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
+    }
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      fprintf(stdout, 
-      "  Rec : Off Position   Size : V PDS  GDS    BMS    BDS : Code Level :  LType GType: CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-
-  is = gribbuffer;
-
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  else if ( numBits == 0 )
     {
-      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
-      return;
     }
-
-  if ( gds == NULL )
-    GridType = -1;
   else
-    GridType = GDS_GridType;
-
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else if ( PDS_LevelType == 109 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
-
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
-
-  if ( ((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130) )
     {
-      int s1, s2;
-      s1 = gribrec_len(bds[14], bds[15], bds[16]);
-      s2 = gribrec_len(gribbuffer[4], gribbuffer[5], gribbuffer[6]);
-      cr = ((double)s1)/s2;
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d%4d%5d%7d%7d : %3d%7d : %5d %5d %6.4g\n",
-	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
-	  PDS_Len, GDS_Len, BMS_Len, bdslen,
-	  PDS_Parameter, level, PDS_LevelType, GridType, cr);
+  *gz = z;
+#undef __UNROLL_DEPTH_2
 }
 
+#endif /* T */
 
-void grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int nerr;
-  unsigned char *is  = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  unsigned char *ids = NULL, *lus = NULL, *drs = NULL;
-  long ids_len = 0, lus_len = 0, gds_len = 0, pds_len = 0, drs_len = 0, bms_len = 0, bds_len = 0;
-  int gridtype, paramnum, level1type /*, level2type*/;
-  int level1 /*, level1sf*/;
-  /* int level2, level2sf; */
-  double cr = 1;
 
-  if ( header )
-    {
-      fprintf(stdout, 
-      "  Rec : Off Position   Size : V IDS LUS GDS PDS  DRS    BMS    BDS : Code Level :  LType GType: CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
-    }
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
 
-  is = gribbuffer;
+/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
+static
+void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
+{
+  long z = *gribLen;
+  int exponent, mantissa;
+  long i;
+  int ival;
+  int pvoffset = 0xFF;
+  int gdslen = 32;
+  unsigned lonIncr, latIncr;
 
-  nerr = grib2Sections(gribbuffer, recsize, &ids, &lus, &gds, &pds, &drs, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
-      return;
-    }
+  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
 
-  if ( ids ) ids_len = GRIB2_SECLEN(ids);
-  if ( lus ) lus_len = GRIB2_SECLEN(lus);
-  if ( gds ) gds_len = GRIB2_SECLEN(gds);
-  if ( pds ) pds_len = GRIB2_SECLEN(pds);
-  if ( drs ) drs_len = GRIB2_SECLEN(drs);
-  if ( bms ) bms_len = GRIB2_SECLEN(bms);
-  if ( bds ) bds_len = GRIB2_SECLEN(bds);
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
 
-  /*
-  if ( (BDS_Flag >> 4)&1 && BDS_Z == 128 )
-    {
-      int s1, s2;
-      s1 = ((int) ((bds[14]<<16)+(bds[15]<<8)+bds[16]));
-      s2 = ((int) ((gribbuffer[4]<<16)+(gribbuffer[5]<<8)+gribbuffer[6]));
-      cr = ((double)s1)/s2;
-    }
-  */
-  gridtype   = GET_UINT2(gds[12],gds[13]);
-  paramnum   = GET_UINT1(pds[10]);
-  level1type = GET_UINT1(pds[22]);
-  /* level1sf   = GET_UINT1(pds[23]); */
-  level1     = GET_UINT4(pds[24],pds[25],pds[26],pds[27]);
-  /* level2type = GET_UINT1(pds[28]); */
-  /* level2sf   = GET_UINT1(pds[29]); */
-  /* level2     = GET_UINT4(pds[30],pds[31],pds[32],pds[33]); */
-  /*
-  printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
-  */
-  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %3d%7d : %5d %5d %6.4g\n",
-	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
-	  ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len,
-	  paramnum, level1, level1type, gridtype, cr);
-}
+  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
 
+  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
 
-void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  gdslen += ISEC2_NumVCP * 4;
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
+  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
+  Put1Byte(pvoffset);           /*  4    PV */
+  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
-  else if ( gribversion == 2 )
-    grib2PrintALL(nrec, offset, recpos, recsize, gribbuffer);
-  else
+  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, offset, recpos, recsize, gribversion); 
+      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
+      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
+      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
+      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
+      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
+      PutnZero(18);             /* 14-31 reserved                 */
     }
-}
-
-
-void grib1PrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int century, subcenter, decimalscale, nerr;
-  int fc_num = 0;
-  int year = 0, date;
-
-  if ( header )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
     {
-      fprintf(stdout, 
-      "  Rec : PDS Tab Cen Sub Ver Grid Code LTyp Level1 Level2    Date  Time P1 P2 TU TR NAVE Scale FCnum CT\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      Put2Byte(ISEC2_GME_NI2);
+      Put2Byte(ISEC2_GME_NI3);
+      Put3Byte(ISEC2_GME_ND);
+      Put3Byte(ISEC2_GME_NI);
+      Put1Byte(ISEC2_GME_AFlag);
+      Put3Int(ISEC2_GME_LatPP);
+      Put3Int(ISEC2_GME_LonPP);
+      Put3Int(ISEC2_GME_LonMPL);
+      Put1Byte(ISEC2_GME_BFlag);
+      PutnZero(5);
     }
-
-  is = gribbuffer;
-
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
 
-  switch(GRIB_EDITION(is))
-    {   
-    case 0:
-      year                = GET_UINT1(pds[12]);
-      century             = 1;
-      subcenter           = 0;
-      decimalscale        = 0;
-      break;
-    case 1:
-      year                = PDS_Year;
-      century             = PDS_Century;
-      subcenter           = PDS_Subcenter;
-      decimalscale        = PDS_DecimalScale;
-      break;
-    default:
-      fprintf(stderr, "Grib version %d not supported!", GRIB_EDITION(is));
-      exit(EXIT_FAILURE);
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
+      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
+      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
+      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
+      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
+      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
+      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
+      PutnZero(2);                     /* 34-41 */
     }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      int numlon;
+      if ( ISEC2_Reduced )
+	numlon = 0xFFFF;
+      else
+	numlon = ISEC2_NumLon;
 
-  if ( PDS_Len > 28 )
-    if ( PDS_CenterID    == 98 || PDS_Subcenter == 98 ||
-	(PDS_CenterID    ==  7 && PDS_Subcenter == 98) )
-      if ( pds[40] == 1 )
-	fc_num = GET_UINT1(pds[49]);
+      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
 
-  if ( year < 0 )
-    {
-      date = (-year)*10000+PDS_Month*100+PDS_Day;
-      century = -century;
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_LastLat);
+      Put3Int(ISEC2_LastLon);
+      if ( ISEC2_ResFlag == 0 )
+	{
+	  lonIncr = 0xFFFF;
+	  latIncr = 0xFFFF;
+	}
+      else
+	{
+	  lonIncr = ISEC2_LonIncr;
+	  latIncr = ISEC2_LatIncr;
+	}
+      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
+      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
+	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
+      else
+	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
+
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      PutnZero(4);                     /* 28-31 reserved                 */
+
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  Put3Int(ISEC2_LatSP);
+	  Put3Int(ISEC2_LonSP);
+	  Put1Real((double)(FSEC2_RotAngle));
+	}
     }
   else
     {
-      date =    year*10000+PDS_Month*100+PDS_Day;
+      Error("Unsupported grid type %d", ISEC2_GridType);
     }
-      
-  fprintf(stdout, "%5d :%4d%4d%4d%4d%4d %4d %4d%4d%7d%7d %8d%6d%3d%3d%3d%3d%5d%6d%5d%4d\n", nrec,
-	  PDS_Len,  PDS_CodeTable,   PDS_CenterID, subcenter, PDS_ModelID,
-	  PDS_GridDefinition, PDS_Parameter, PDS_LevelType, PDS_Level1, PDS_Level2,
-	  date, PDS_Time, PDS_TimePeriod1, PDS_TimePeriod2, PDS_TimeUnit, PDS_TimeRange,
-	  PDS_AvgNum, decimalscale, fc_num, century);
-}
 
+#if defined (SX)
+#pragma vdir novector     /* vectorization gives wrong results on NEC */
+#endif
+  for ( i = 0; i < ISEC2_NumVCP; ++i )
+    {
+      Put1Real((double)(fsec2[10+i]));
+    }
 
-void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  if ( ISEC2_Reduced )
+    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  *gribLen = z;
+}
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
-  /*
-  else if ( gribversion == 2 )
-    grib2PrintPDS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
+/* GRIB BLOCK 3 - BIT MAP SECTION */
+static
+void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
+{
+  GRIBPACK *bitmap;
+  long bitmapSize;
+  long imaskSize;
+  long i;
+  long bmsLen, bmsUnusedBits;
+  long fsec4size;
+  long z = *gribLen;
+#if defined (VECTORCODE)
+  unsigned int *imask;
+#endif
+  static int lmissvalinfo = 1;
+  /*  unsigned int c, imask; */
+
+  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
+      lmissvalinfo = 0;
+      Message("Missing value = NaN is unsupported!");
     }
-}
 
+  bitmapSize = ISEC4_NumValues;
+  imaskSize = ((bitmapSize+7)>>3)<<3;
+  bitmap = &lGrib[z+6];
+  fsec4size = 0;
 
-void grib1PrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+#if defined (VECTORCODE)
+  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
+  memset(imask, 0, imaskSize*sizeof(int));
 
-  if ( header )
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      fprintf(stdout, 
-      "  Rec : GDS  NV PVPL Typ : xsize ysize   Lat1   Lon1   Lat2   Lon2    dx    dy\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  imask[i] = 1;
+	}
     }
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < imaskSize/8; i++ )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
+      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
+	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
+	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
+	          (imask[i*8+6] << 1) | (imask[i*8+7]);
     }
 
-  if ( gds )
-    fprintf(stdout, "%5d :%4d%4d%4d %4d :%6d%6d%7d%7d%7d%7d%6d%6d\n", nrec,
-	    GDS_Len,  GDS_NV,   GDS_PVPL, GDS_GridType,
-	    GDS_NumLon,   GDS_NumLat,
-	    GDS_FirstLat, GDS_FirstLon,
-	    GDS_LastLat,  GDS_LastLon,
-	    GDS_LonIncr,  GDS_LatIncr);
-  else
-    fprintf(stdout, "%5d : Grid Description Section not defined\n", nrec);
-}
+  free(imask);
+#else
+  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
+
+  for ( i = 0; i < bitmapSize; i++ )
+    {
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  bitmap[i/8] |= 1<<(7-(i&7));
+	}
+    }
+#endif
 
+  bmsLen = imaskSize/8 + 6;
+  bmsUnusedBits = imaskSize - bitmapSize;
 
-void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
+  Put1Byte(bmsUnusedBits);
+  Put2Byte(0);
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  *gribLen += bmsLen;
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
-  /*
-  else if ( gribversion == 2 )
-    grib2PrintGDS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
-    {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
-    }
+  *datasize = fsec4size;
 }
 
 
-void grib1PrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+/* GRIB BLOCK 4 - BINARY DATA SECTION */
+static
+int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
+			  long *datstart, long *datsize, int code)
 {
-  static int header = 1;
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
+  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
 
-  if ( header )
-    {
-      fprintf(stdout, 
-      "  Rec : Code Level     BMS    Size\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
-    }
+  size_t z = *gribLen;
+  long i, jloop;
+  int numBits;
+  int ival;
+  int blockLength, PackStart = 0, Flag = 0;
+  int binscale = 0;
+  int nbpv;
+  int bds_head = 11;
+  int bds_ext = 0;
+  /* ibits = BitsPerInt; */
+  unsigned int max_nbpv_pow2;
+  int exponent, mantissa;
+  int unused_bits = 0;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int isubset = 0, itemp = 0, itrunc = 0;
+  T factor = 1, fmin, fmax;
+  double zref;
+  double range, rangec;
+  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
+                                /*        of floating point numbers - needed   */
+		                /*        on some platforms (eg vpp700, linux) */
+  extern const double _pow2tab[158];
+  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  if ( isec2 )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+      /* If section 2 is present, it says if data is spherical harmonic */
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+      if ( isec2[0] == 50 || isec2[0] == 60 || 
+	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
 
-  if ( bms )
-    fprintf(stdout, "%5d :%4d%7d %7d %7d\n", nrec,
-	    PDS_Parameter, level,
-	    BMS_Len, BMS_BitmapSize);
+      if ( lspherc )
+	isec4[2] = 128;
+      else
+	isec4[2] = 0;
+    }
   else
-    fprintf(stdout, "%5d :%4d%7d Bit Map Section not defined\n", nrec,
-	    PDS_Parameter, level);
-}
+    {
+      /* Section 4 says if it's spherical harmonic data.. */
 
+      lspherc = ( isec4[2] == 128 );
+    }
 
-void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  /* Complex packing supported for spherical harmonics. */
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+             ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
-  /*
-  else if ( gribversion == 2 )
-    grib2PrintBMS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
+  /* Check input specification is consistent */
+
+  if ( lcomplex && isec2 )
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
+      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+	}
+      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+        }
+      else if ( lcomplex )
+	{
+	  /*
+	    Truncation of full spectrum, which is supposed triangular,
+	    has to be diagnosed. Define also sub-set truncation.
+	  */
+	  isubset = isec4[17];
+	  /* When encoding, use the total number of data. */
+	  itemp   = isec4[0];
+	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
+	}
     }
-}
-
-
-void grib1PrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-  double refval, scale;
 
-  if ( header )
+  if ( decscale )
     {
-      fprintf(stdout, 
-      "  Rec : Code Level     BDS Flag     Scale   RefValue Bits  CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      T scale = (T) pow(10.0, (double) decscale);
+      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
     }
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  if ( lspherc )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
+      if ( lcomplex )
+	{
+	  int jup, ioff;
+	  jup  = isubset;
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	  PackStart = ioff;
+	  Flag = 192;
+	}
+      else
+	{
+	  bds_ext = 4;
+	  PackStart = 1;
+	  Flag = 128;
+	}
     }
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+  *datstart = bds_head + bds_ext;
 
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+  nbpv = numBits = ISEC4_NumBits;
+
+  if ( lspherc && lcomplex )
     {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
+      int pcStart, pcScale;
+      pcStart = isubset;
+      pcScale = isec4[16];
+      TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
+      TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
     }
 
-  refval = BDS_RefValue;
+  fmin = fmax = data[PackStart];
 
-  if ( BDS_BinScale < 0 )
-    scale = 1.0/pow(2.0, (double) -BDS_BinScale);
-  else
-    scale = pow(2.0, (double) BDS_BinScale);
+  TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-  if ( PDS_DecimalScale )
+  zref = (double)fmin;
+
+
+  if ( CGRIBEX_Const && !lspherc )
     {
-      double decscale;
-      decscale = pow(10.0, (double)-PDS_DecimalScale);
-      refval *= decscale;
-      scale  *= decscale;
+      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
     }
 
-  fprintf(stdout, "%5d :%4d%7d %7d %4d %8.5g %11.5g%4d %6.4g\n", nrec,
-	  PDS_Parameter, level,
-	  BDS_Len, BDS_Flag, scale, refval, BDS_NumBits, cr);
-}
 
+  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+  if ( (blockLength%2) == 1 ) blockLength++;
 
-void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+
+  Flag += unused_bits;
 
-  gribversion = gribVersion(gribbuffer, recsize);
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
   /*
-  else if ( gribversion == 2 )
-    grib2PrintBDS(nrec, recpos, recsize, gribbuffer);
+    Adjust number of bits per value if full integer length to
+    avoid hitting most significant bit (sign bit).
   */
-  else
+  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
+  /*
+    Calculate the binary scaling factor to spread the range of
+    values over the number of bits per value.
+    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
+    as a guideline).           
+  */
+  range = fabs(fmax - fmin);
+
+  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  /*
+    Have to allow tolerance in comparisons on some platforms
+    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
+    to avoid clipping ranges which are a power of 2.
+  */
+  if ( range <= jpepsln )
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
+      binscale = 0;
     }
-}
-
-
-void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
+      binscale = 0;
     }
-
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
-
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+  else if ( fabs(range-1.0) <= jpepsln )
     {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
+      binscale = 1 - nbpv;
     }
-
-  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+  else if ( range > 1.0 )
     {
-      fprintf(stdout, "GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+      rangec = range + jpepsln;
+      for ( jloop = 1; jloop < 128; jloop++ )
+	{
+	  if ( _pow2tab[jloop] > rangec ) break;
+	}
+      if ( jloop == 128 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = jloop - nbpv;
+	}
+    }
+  else
+    {
+      rangec = range - jpepsln;
+      for ( jloop = 1; jloop < 127; jloop++ )
+	{
+	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
+	}
+      if ( jloop == 127 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = 1 - jloop - nbpv;
+	}
     }
-}
-
 
-static
-void repair1(unsigned char *gbuf, long gbufsize)
-{
-  long i;
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  /* int recLen; */
-  unsigned char *source;
-  size_t sourceLen;
-  int bds_len, bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress */;
-  int bds_head = 11;
-  int bds_ext = 0, bds_ubits;
-  int datstart = 0;
-  /* int llarge = FALSE; */
+  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
+  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
 
-  nerr = grib1Sections(gbuf, gbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  if ( binscale != 0 )
     {
-      fprintf(stdout, "grib1Sections error\n");
+      if ( binscale < 0 )
+	{
+	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
+	}
+      else
+	{
+	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+	}
+
+      if ( binscale < 0 ) factor =     intpow2(-binscale);
+      else                factor = 1.0/intpow2( binscale);
     }
 
-  /* recLen = gribrec_len(gbuf[4], gbuf[5], gbuf[6]); */
-  /* if ( recLen > JP23SET ) llarge = TRUE; */
+  ref2ibm(&zref, BitsPerInt);
 
-  bds_len   = BDS_Len;
-  bds_nbits = BDS_NumBits;
-  bds_flag  = BDS_Flag;
-  bds_ubits = bds_flag & 15;
-  lspherc   =  bds_flag >> 7;
-  lcomplex  = (bds_flag >> 6)&1;
-  /* lcompress = (bds_flag >> 4)&1; */
+  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
+  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
+  if ( binscale < 0 ) binscale = 32768 - binscale;
+  Put2Byte(binscale);         /*  4-5 Scale factor             */
+  Put1Real(zref);             /*  6-9 Reference value          */
+  Put1Byte(nbpv);             /*   10 Packing size             */
 
   if ( lspherc )
     {
-      if ( lcomplex  )
+      if ( lcomplex )
 	{
-	  int jup, ioff;
-	  jup  = bds[15];
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
+	  int jup = isubset;
+	  int ioff = z + bds_ext;
+	  if ( ioff > 0xFFFF ) ioff = 0;
+	  Put2Byte(ioff);
+	  Put2Int(isec4[16]);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
 	}
       else
 	{
-	  bds_ext = 4;
+	  Put1Real((double)(data[0]));
 	}
     }
 
-  datstart = bds_head + bds_ext;
+  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
 
-  source = bds + datstart;
+#if  defined  (_ARCH_PWR6)
+  TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#else
+  TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#endif
 
-  sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
 
-  if ( bds_nbits == 24 )
-    {
-      long nelem;
-      unsigned char *pbuf;
-      nelem = sourceLen/3;
-      pbuf = (unsigned char*) malloc(sourceLen);
-      for ( i = 0; i < nelem; i++ )
-	{
-	  pbuf[3*i  ] = source[        i];
-	  pbuf[3*i+1] = source[  nelem+i];
-	  pbuf[3*i+2] = source[2*nelem+i];
-	}
-      memcpy(source, pbuf, sourceLen);
-      free(pbuf);
-    }
+  *gribLen = z;
+
+  return (0);
 }
 
 
-void gribRepair1(int nrec, long recsize, unsigned char *gribbuffer)
+void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
+			     int kleng, int *kword, int efunc, int *kret)
 {
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
+  long gribLen = 0; /* Counter of GRIB length for output */
+  long isLen, pdsLen;
+  GRIBPACK *lpds;
+  unsigned char *CGrib;
+  long fsec4size = 0;
+  int numBytes;
+  int bmsIncluded;
+  size_t len;
+  GRIBPACK *lGrib;
+  long datstart, datsize, bdsstart;
+  int status = 0;
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  UNUSED(isec3);
+  UNUSED(efunc);
+
+  grsdef();
+
+  CGrib = (unsigned char *) kgrib;
+
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+
+  /* set max header len */
+  len = 16384;
+
+  /* add data len */
+  numBytes = (ISEC4_NumBits+7)>>3;
+
+  len += numBytes*klenp;
+
+  /* add bitmap len */
+  if ( bmsIncluded ) len += (klenp+7)>>3;
+
+#if defined (VECTORCODE)
+  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
+  if ( lGrib == NULL ) SysError("No Memory!");
+#else
+  lGrib = CGrib;
+#endif
+
+  isLen = 8;
+  encodeIS(lGrib, &gribLen);
+  lpds = &lGrib[isLen];
+  pdsLen = getPdsLen(isec1);
+
+  encodePDS(lpds, pdsLen,  isec1);
+  gribLen += pdsLen;
+  /*
+  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+      static int lwarn_cplx = TRUE;
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+      if ( lwarn_cplx )
+	Message("Complex packing of spectral data unsupported, using simple packing!");
 
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+      isec2[5] = 1;
+      isec4[3] = 0;
+
+      lwarn_cplx = FALSE;
+    }
+  */
+  TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  if ( bmsIncluded )
     {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
+      TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+    }
+  else
+    {
+      fsec4size = ISEC4_NumValues;
     }
 
-  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+  bdsstart = gribLen;
+  status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
+				 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
+  if ( status )
     {
-      fprintf(stdout, "Repair GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
-      repair1(gribbuffer, recsize);
+      *kret = status;
+      return;
     }
-}
-#include <stdio.h>
-#include <string.h>
 
-#if defined (HAVE_CONFIG_H)
-#endif
+  encodeES(lGrib, &gribLen, bdsstart);
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
-#if defined(__cplusplus)
-extern "C" {
-#endif
-#if defined (HAVE_LIBAEC)
-#  include <libaec.h>
-#else
-#  include <szlib.h>
+  if ( (size_t) gribLen > kleng*sizeof(int) )
+    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
+
+#if defined (VECTORCODE)
+  if ( (size_t) gribLen > len )
+    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
+
+  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
+
+  free(lGrib);
 #endif
-#if defined (__cplusplus)
+
+  ISEC0_GRIB_Len     = gribLen;
+  ISEC0_GRIB_Version = 1;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+
+  *kret = status;
 }
-#endif
 
-#if defined (HAVE_LIBAEC)
-#  define AEC_FLAGS           (AEC_DATA_MSB | AEC_DATA_PREPROCESS)
-#else
-#  define OPTIONS_MASK        (SZ_RAW_OPTION_MASK | SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK)
+#endif /* T */
+
+#ifdef T
+#undef T
 #endif
+#define T float
+#ifdef T
 
-#  define PIXELS_PER_BLOCK    (8)
-#  define PIXELS_PER_SCANLINE (PIXELS_PER_BLOCK*128)
+/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
+static
+void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
+{
+  long z = *gribLen;
+  int exponent, mantissa;
+  long i;
+  int ival;
+  int pvoffset = 0xFF;
+  int gdslen = 32;
+  unsigned lonIncr, latIncr;
 
-#  define MIN_COMPRESS        (0.95)
-#  define MIN_SIZE            (256)
-#endif
+  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
 
-#define  Z_SZIP  128
-#define  Z_AEC   130
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
 
+  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
 
-#define SetLen3(var, offset, value) ((var[offset+0] = 0xFF & (value >> 16)), \
-				     (var[offset+1] = 0xFF & (value >>  8)), \
-				     (var[offset+2] = 0xFF & (value      )))
-#define SetLen4(var, offset, value) ((var[offset+0] = 0xFF & (value >> 24)), \
-				     (var[offset+1] = 0xFF & (value >> 16)), \
-				     (var[offset+2] = 0xFF & (value >>  8)), \
-				     (var[offset+3] = 0xFF & (value      )))
+  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
 
+  gdslen += ISEC2_NumVCP * 4;
 
-int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
-{
-  /* urecsize : uncompressed record size  */
-  int compress = 0;
-  int nerr;
-  /* int  bds_len, bds_nbits, lspherc, lcomplex; */
-  int bds_flag, lcompress;
-  long gribsize = 0;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int gribversion;
+  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
+  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
+  Put1Byte(pvoffset);           /*  4    PV */
+  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
+    {
+      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
+      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
+      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
+      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
+      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
+      PutnZero(18);             /* 14-31 reserved                 */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+    {
+      Put2Byte(ISEC2_GME_NI2);
+      Put2Byte(ISEC2_GME_NI3);
+      Put3Byte(ISEC2_GME_ND);
+      Put3Byte(ISEC2_GME_NI);
+      Put1Byte(ISEC2_GME_AFlag);
+      Put3Int(ISEC2_GME_LatPP);
+      Put3Int(ISEC2_GME_LonPP);
+      Put3Int(ISEC2_GME_LonMPL);
+      Put1Byte(ISEC2_GME_BFlag);
+      PutnZero(5);
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+    {
+      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
 
-  if ( gribversion == 2 ) return (compress);
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
+      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
+      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
+      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
+      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
+      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
+      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
+      PutnZero(2);                     /* 34-41 */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      int numlon;
+      if ( ISEC2_Reduced )
+	numlon = 0xFFFF;
+      else
+	numlon = ISEC2_NumLon;
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
+
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_LastLat);
+      Put3Int(ISEC2_LastLon);
+      if ( ISEC2_ResFlag == 0 )
+	{
+	  lonIncr = 0xFFFF;
+	  latIncr = 0xFFFF;
+	}
+      else
+	{
+	  lonIncr = ISEC2_LonIncr;
+	  latIncr = ISEC2_LatIncr;
+	}
+      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
+      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
+	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
+      else
+	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
+
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      PutnZero(4);                     /* 28-31 reserved                 */
+
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  Put3Int(ISEC2_LatSP);
+	  Put3Int(ISEC2_LonSP);
+	  Put1Real((double)(FSEC2_RotAngle));
+	}
+    }
+  else
     {
-      fprintf(stdout, "grib1Sections error\n");
-      return (compress);
+      Error("Unsupported grid type %d", ISEC2_GridType);
     }
 
-  /* bds_len   = BDS_Len; */
-  /* bds_nbits = BDS_NumBits; */
-  bds_flag  = BDS_Flag;
-  /* lspherc   =  bds_flag >> 7; */
-  /* lcomplex  = (bds_flag >> 6)&1; */
-  lcompress = (bds_flag >> 4)&1;
-
-  *urecsize = 0;
-  if ( lcompress )
+#if defined (SX)
+#pragma vdir novector     /* vectorization gives wrong results on NEC */
+#endif
+  for ( i = 0; i < ISEC2_NumVCP; ++i )
     {
-      compress = BDS_Z;
-      if ( compress == Z_SZIP || compress == Z_AEC )
-	{
-	  gribsize = gribrec_len(bds[14], bds[15], bds[16]);
-	}
+      Put1Real((double)(fsec2[10+i]));
     }
 
-  *urecsize = gribsize;
+  if ( ISEC2_Reduced )
+    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
 
-  return (compress);
+  *gribLen = z;
 }
 
-
-int  gribZip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
+/* GRIB BLOCK 3 - BIT MAP SECTION */
+static
+void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
 {
-  int nerr;
-  int gribLen;
-  int rec_len;
-  int llarge = FALSE;
-#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
-  static int libszwarn = 1;
+  GRIBPACK *bitmap;
+  long bitmapSize;
+  long imaskSize;
+  long i;
+  long bmsLen, bmsUnusedBits;
+  long fsec4size;
+  long z = *gribLen;
+#if defined (VECTORCODE)
+  unsigned int *imask;
 #endif
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  static int lmissvalinfo = 1;
+  /*  unsigned int c, imask; */
 
-  gribLen = gribrec_len(dbuf[4], dbuf[5], dbuf[6]);
-  if ( gribLen > JP23SET ) llarge = TRUE;
+  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
+    {
+      lmissvalinfo = 0;
+      Message("Missing value = NaN is unsupported!");
+    }
 
-  rec_len = gribLen;
+  bitmapSize = ISEC4_NumValues;
+  imaskSize = ((bitmapSize+7)>>3)<<3;
+  bitmap = &lGrib[z+6];
+  fsec4size = 0;
 
-  nerr = grib1Sections(dbuf, dbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+#if defined (VECTORCODE)
+  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
+  memset(imask, 0, imaskSize*sizeof(int));
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      fprintf(stdout, "grib1Sections error!\n");
-      return (rec_len);
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  imask[i] = 1;
+	}
     }
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < imaskSize/8; i++ )
+    {
+      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
+	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
+	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
+	          (imask[i*8+6] << 1) | (imask[i*8+7]);
+    }
 
-  {
-    long i;
-    int bdsLen;
-    int gribLenOld = 0;
-    int status;
-    size_t datstart, datsize;
-#if defined (HAVE_LIBAEC)
-    struct aec_stream strm;
+  free(imask);
 #else
-    SZ_com_t sz_param;          /* szip parameter block */
+  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
+
+  for ( i = 0; i < bitmapSize; i++ )
+    {
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  bitmap[i/8] |= 1<<(7-(i&7));
+	}
+    }
 #endif
-    unsigned char *dest, *source;
-    size_t destLen, sourceLen;
-    int bits_per_sample;
-    int bds_len, bds_nbits, bds_flag, lspherc, lcomplex,/* lcompress,*/ bds_ubits;
-    int bds_head = 11;
-    int bds_ext = 0;
-    int bds_zoffset, bds_zstart;
-    unsigned char *pbuf = NULL;
 
-    bds_zstart  = 14;
-    bds_zoffset = 12;
-    if ( llarge ) bds_zoffset += 2;
+  bmsLen = imaskSize/8 + 6;
+  bmsUnusedBits = imaskSize - bitmapSize;
 
-    bds_len   = BDS_Len;
-    bds_len   = correct_bdslen(bds_len, gribLen, bds-dbuf);
-    bds_nbits = BDS_NumBits;
-    bds_flag  = BDS_Flag;
-    bds_ubits = bds_flag & 15;
-    lspherc   =  bds_flag >> 7;
-    lcomplex  = (bds_flag >> 6)&1;
-    /* lcompress = (bds_flag >> 4)&1; */
-    
-    if ( bds_nbits != 8 && bds_nbits != 16 && bds_nbits != 24 && bds_nbits != 32 )
-      {
-	static int linfo = 1;
-	if ( linfo && bds_nbits != 0 )
-	  {
-	    linfo = 0;
-	    fprintf(stderr, "GRIB szip only supports 8, 16, 24 and 32 bit data!\n");
-	  }
-	return (rec_len);
-      }
+  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
+  Put1Byte(bmsUnusedBits);
+  Put2Byte(0);
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      bits_per_sample    = 8;
-    else
-#endif
-      bits_per_sample    = bds_nbits;
+  *gribLen += bmsLen;
 
-#if defined (HAVE_LIBAEC)
-    strm.bits_per_sample = bits_per_sample;
-    strm.block_size      = PIXELS_PER_BLOCK;
-    strm.rsi             = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
-    strm.flags           = AEC_FLAGS;
-    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
-#else
-    sz_param.options_mask        = OPTIONS_MASK;
-    sz_param.bits_per_pixel      = bits_per_sample;
-    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
-    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
-#endif
+  *datasize = fsec4size;
+}
 
-    if ( lspherc )
-      {
-	if ( lcomplex  )
-	  {
-	    int jup, ioff;
-	    jup  = bds[15];
-	    ioff = (jup+1)*(jup+2);
-	    bds_ext = 4 + 3 + 4*ioff;
-	  }
-	else
-	  {
-	    bds_ext = 4;
-	  }
-      }
 
-    datstart = bds_head + bds_ext;
+/* GRIB BLOCK 4 - BINARY DATA SECTION */
+static
+int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
+			  long *datstart, long *datsize, int code)
+{
+  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
+  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
 
-    datsize = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+  size_t z = *gribLen;
+  long i, jloop;
+  int numBits;
+  int ival;
+  int blockLength, PackStart = 0, Flag = 0;
+  int binscale = 0;
+  int nbpv;
+  int bds_head = 11;
+  int bds_ext = 0;
+  /* ibits = BitsPerInt; */
+  unsigned int max_nbpv_pow2;
+  int exponent, mantissa;
+  int unused_bits = 0;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int isubset = 0, itemp = 0, itrunc = 0;
+  T factor = 1, fmin, fmax;
+  double zref;
+  double range, rangec;
+  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
+                                /*        of floating point numbers - needed   */
+		                /*        on some platforms (eg vpp700, linux) */
+  extern const double _pow2tab[158];
+  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
 
-    if ( datsize < MIN_SIZE ) return (rec_len);
-    /*
-    fprintf(stderr, "%d %d %d %d\n", bds_len, datstart, bds_len - datstart, datsize);
-    */
-    sourceLen = datsize;
-    destLen   = sbufsize;
-    
-    source = bds + datstart;
-    dest = sbuf;
+  if ( isec2 )
+    {
+      /* If section 2 is present, it says if data is spherical harmonic */
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      {
-	long nelem;
-	nelem = sourceLen/3;
-	pbuf = (unsigned char*) malloc(sourceLen);
-	for ( i = 0; i < nelem; i++ )
-	  {
-	    pbuf[        i] = source[3*i  ];
-	    pbuf[  nelem+i] = source[3*i+1];
-	    pbuf[2*nelem+i] = source[3*i+2];
-	  }
-	source = pbuf;
-      }
-#endif
+      if ( isec2[0] == 50 || isec2[0] == 60 || 
+	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
 
-#if defined (HAVE_LIBAEC)
-    strm.next_in = source;
-    strm.avail_in = sourceLen;
-    strm.next_out = dest;
-    strm.avail_out = destLen;
+      if ( lspherc )
+	isec4[2] = 128;
+      else
+	isec4[2] = 0;
+    }
+  else
+    {
+      /* Section 4 says if it's spherical harmonic data.. */
 
-    status = aec_buffer_encode(&strm);
-    if ( status != AEC_OK )
-      {
-       	if ( status != AEC_DATA_ERROR )
-	  Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
+      lspherc = ( isec4[2] == 128 );
+    }
 
-    destLen = strm.total_out;
-#else
-    status = SZ_BufftoBuffCompress(dest, &destLen, source, sourceLen, &sz_param);
-    if ( status != SZ_OK )
-      {
-	if ( status == SZ_NO_ENCODER_ERROR )
-	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_PARAM_ERROR )
-	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_MEM_ERROR )
-	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_OUTBUFF_FULL )
-	  /*Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2)*/;
-	else
-	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
-#endif
-    
-    if ( pbuf ) free(pbuf);
-    /*
-    fprintf(stderr, "sourceLen, destLen %d %d\n", sourceLen, destLen);
-    */
-    if ( destLen < MIN_COMPRESS*sourceLen )
-      {
-	source = bds + datstart + bds_zoffset;
-	memcpy(source, dest, destLen);
-	
-	/* ----++++ number of unused bits at end of section) */
+  /* Complex packing supported for spherical harmonics. */
 
-	BDS_Flag -= bds_ubits;
-    
-	gribLenOld = gribLen;
+  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+             ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
-	if ( bds_ext )
-	  for ( i = bds_ext-1; i >= 0; --i )
-	    bds[bds_zoffset+bds_head+i] = bds[bds_head+i];
+  /* Check input specification is consistent */
 
-	/*
-	fprintf(stderr, "destLen, datsize, datstart %d %d %d\n", destLen, datsize, datstart);
-	*/
-	/*	memcpy(bds + datstart + bds_zoffset, source, destLen); */
-	/*
-	  fprintf(stderr, "z>>> %d %d %d %d <<<\n", (int) bds[0+datstart+bds_zoffset],
-	    (int)bds[1+datstart+bds_zoffset], (int)bds[2+datstart+bds_zoffset], (int)bds[3+datstart+bds_zoffset]);
-	*/
-	if ( llarge )
-	  {
-	    if ( gribLenOld%120 )
-	      {
-		fprintf(stderr, "Internal problem, record length not multiple of 120!");
-		while ( gribLenOld%120 ) gribLenOld++;
-	      }
-	    gribLenOld = gribLenOld / (-120);
-	    gribLenOld = JP23SET - gribLenOld + 1;
+  if ( lcomplex && isec2 )
+    {
+      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+	}
+      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+        }
+      else if ( lcomplex )
+	{
+	  /*
+	    Truncation of full spectrum, which is supposed triangular,
+	    has to be diagnosed. Define also sub-set truncation.
+	  */
+	  isubset = isec4[17];
+	  /* When encoding, use the total number of data. */
+	  itemp   = isec4[0];
+	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
+	}
+    }
 
-	    SetLen3(bds, bds_zstart, gribLenOld);
-	    SetLen4(bds, bds_zstart+3, sourceLen);
-	    SetLen4(bds, bds_zstart+7, destLen);
-	  }
-	else
-	  {
-	    SetLen3(bds, bds_zstart, gribLenOld);
-	    SetLen3(bds, bds_zstart+3, sourceLen);
-	    SetLen3(bds, bds_zstart+6, destLen);
-	  }
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double) decscale);
+      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
+    }
 
-	bdsLen = datstart + bds_zoffset + destLen;
+  if ( lspherc )
+    {
+      if ( lcomplex )
+	{
+	  int jup, ioff;
+	  jup  = isubset;
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	  PackStart = ioff;
+	  Flag = 192;
+	}
+      else
+	{
+	  bds_ext = 4;
+	  PackStart = 1;
+	  Flag = 128;
+	}
+    }
 
-	bds[11] = 0;
-	bds[12] = 0;
-#if defined (HAVE_LIBAEC)
-	BDS_Z   = Z_AEC;
-#else
-	BDS_Z   = Z_SZIP;
-#endif
+  *datstart = bds_head + bds_ext;
 
-	BDS_Flag += 16;
-	if ( (bdsLen%2) == 1 )
-	  {
-	    BDS_Flag += 8;
-	    bds[bdsLen++] = 0;
-	  }
+  nbpv = numBits = ISEC4_NumBits;
 
-	SetLen3(bds, 0, bdsLen);
+  if ( lspherc && lcomplex )
+    {
+      int pcStart, pcScale;
+      pcStart = isubset;
+      pcScale = isec4[16];
+      TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
+      TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+    }
 
-	gribLen = (bds - dbuf) + bdsLen;
+  fmin = fmax = data[PackStart];
 
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
+  TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-	if ( llarge )
-	  {
-	    long itemp;
-	    long bdslen = gribLen - 4;
+  zref = (double)fmin;
 
-	    /*
-	      If a very large product, the section 4 length field holds
-	      the number of bytes in the product after section 4 upto
-	      the end of the padding bytes.
-	      This is a fixup to get round the restriction on product lengths
-	      due to the count being only 24 bits. It is only possible because
-	      the (default) rounding for GRIB products is 120 bytes.
-	    */
-	    while ( gribLen%120 ) dbuf[gribLen++] = 0;
 
-	    itemp = gribLen / (-120);
-	    itemp = JP23SET - itemp + 1;
+  if ( CGRIBEX_Const && !lspherc )
+    {
+      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
+    }
 
-	    SetLen3(dbuf, 4, itemp);
 
-	    bdslen = gribLen - bdslen;
+  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+  if ( (blockLength%2) == 1 ) blockLength++;
 
-	    SetLen3(bds, 0, bdslen);
-	  }
-	else
-	  {
-	    SetLen3(dbuf, 4, gribLen);
-	  }
-      }
-    else
-      {
-      }
-    /*
-    fprintf(stderr, "%3d %3d griblen in %6d  out %6d  CR %g   slen %6d dlen %6d  CR %g\n",
-	    PDS_Parameter, PDS_Level1, gribLenOld, gribLen,
-	    ((double)gribLenOld)/gribLen, sourceLen, destLen,
-	    ((double)sourceLen)/destLen);
-    */
-  }
+  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
 
-#else
-  if ( libszwarn )
+  Flag += unused_bits;
+
+
+  /*
+    Adjust number of bits per value if full integer length to
+    avoid hitting most significant bit (sign bit).
+  */
+  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
+  /*
+    Calculate the binary scaling factor to spread the range of
+    values over the number of bits per value.
+    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
+    as a guideline).           
+  */
+  range = fabs(fmax - fmin);
+
+  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  /*
+    Have to allow tolerance in comparisons on some platforms
+    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
+    to avoid clipping ranges which are a power of 2.
+  */
+  if ( range <= jpepsln )
     {
-      Warning("Compression disabled, szlib or libaec not available!");
-      libszwarn = 0;
+      binscale = 0;
+    }
+  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
+    {
+      binscale = 0;
+    }
+  else if ( fabs(range-1.0) <= jpepsln )
+    {
+      binscale = 1 - nbpv;
+    }
+  else if ( range > 1.0 )
+    {
+      rangec = range + jpepsln;
+      for ( jloop = 1; jloop < 128; jloop++ )
+	{
+	  if ( _pow2tab[jloop] > rangec ) break;
+	}
+      if ( jloop == 128 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = jloop - nbpv;
+	}
+    }
+  else
+    {
+      rangec = range - jpepsln;
+      for ( jloop = 1; jloop < 127; jloop++ )
+	{
+	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
+	}
+      if ( jloop == 127 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = 1 - jloop - nbpv;
+	}
     }
-#endif
-
-  if ( llarge )
-    while ( gribLen%120 ) dbuf[gribLen++] = 0;
-  else
-    while ( gribLen & 7 ) dbuf[gribLen++] = 0;
 
-  rec_len = gribLen;
-
-  return (rec_len);
-}
-
-
-int  gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
-{
-#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
-  static int libszwarn = 1;
-#endif
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int bdsLen, recLen, gribLen = 0;
-  unsigned char *dest, *source;
-  size_t destLen, sourceLen;
-  int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
-  int bds_head = 11;
-  int bds_ext = 0;
-  int bds_zoffset, bds_zstart;
-  int datstart = 0;
-  int llarge = FALSE;
+  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
+  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
 
-  nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  if ( binscale != 0 )
     {
-      fprintf(stdout, "grib1Sections error\n");
-      return (0);
-    }
-
-  bds_zstart = 14;
+      if ( binscale < 0 )
+	{
+	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
+	}
+      else
+	{
+	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+	}
 
-  recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
-  if ( recLen > JP23SET ) llarge = TRUE;
+      if ( binscale < 0 ) factor =     intpow2(-binscale);
+      else                factor = 1.0/intpow2( binscale);
+    }
 
-  bds_zoffset = 12;
-  if ( llarge ) bds_zoffset += 2;
+  ref2ibm(&zref, BitsPerInt);
 
-  /* bds_len   = BDS_Len; */
-  bds_nbits = BDS_NumBits;
-  bds_flag  = BDS_Flag;
-  lspherc   =  bds_flag >> 7;
-  lcomplex  = (bds_flag >> 6)&1;
-  /* lcompress = (bds_flag >> 4)&1; */
+  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
+  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
+  if ( binscale < 0 ) binscale = 32768 - binscale;
+  Put2Byte(binscale);         /*  4-5 Scale factor             */
+  Put1Real(zref);             /*  6-9 Reference value          */
+  Put1Byte(nbpv);             /*   10 Packing size             */
 
   if ( lspherc )
     {
-      if ( lcomplex  )
+      if ( lcomplex )
 	{
-	  int jup, ioff;
-	  jup  = bds[bds_zoffset+15];
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
+	  int jup = isubset;
+	  int ioff = z + bds_ext;
+	  if ( ioff > 0xFFFF ) ioff = 0;
+	  Put2Byte(ioff);
+	  Put2Int(isec4[16]);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
 	}
       else
 	{
-	  bds_ext = 4;
+	  Put1Real((double)(data[0]));
 	}
     }
 
-  datstart = bds_head + bds_ext;
+  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
 
-  source = bds + datstart + bds_zoffset;
-  if ( llarge )
-    sourceLen = ((size_t) ((bds[21]<<24)+(bds[22]<<16)+(bds[23]<<8)+bds[24]));
-  else
-    sourceLen = ((size_t) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+#if  defined  (_ARCH_PWR6)
+  TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#else
+  TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#endif
 
-  nerr = grib1Sections(dbuf, sbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "grib1Sections error\n");
-      return (0);
-    }
+  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
 
-  dest = bds + datstart;
-   if ( llarge )
-    destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
-  else
-    destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+  *gribLen = z;
 
-  BDS_Flag -= 16;
+  return (0);
+}
 
-  bdsLen = datstart + destLen;
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
-  {
-    int status;
-    long i;
-    size_t tmpLen;
-    int bds_ubits;
-    int bits_per_sample;
-#if defined (HAVE_LIBAEC)
-    struct aec_stream strm;
-#else
-    SZ_com_t sz_param;          /* szip parameter block */
-#endif
+void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
+			     int kleng, int *kword, int efunc, int *kret)
+{
+  long gribLen = 0; /* Counter of GRIB length for output */
+  long isLen, pdsLen;
+  GRIBPACK *lpds;
+  unsigned char *CGrib;
+  long fsec4size = 0;
+  int numBytes;
+  int bmsIncluded;
+  size_t len;
+  GRIBPACK *lGrib;
+  long datstart, datsize, bdsstart;
+  int status = 0;
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      bits_per_sample    = 8;
-    else
-#endif
-      bits_per_sample    = bds_nbits;
+  UNUSED(isec3);
+  UNUSED(efunc);
 
-#if defined (HAVE_LIBAEC)
-    strm.bits_per_sample         = bits_per_sample;
-    strm.block_size              = PIXELS_PER_BLOCK;
-    strm.rsi                     = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
-    strm.flags                   = AEC_FLAGS;
-    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
-#else
-    sz_param.options_mask        = OPTIONS_MASK;
-    sz_param.bits_per_pixel      = bits_per_sample;
-    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
-    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
-#endif
+  grsdef();
 
-    if ( bds_ext )
-      for ( i = 0; i < bds_ext; ++i )
-	bds[bds_head+i] = bds[bds_zoffset+bds_head+i];
+  CGrib = (unsigned char *) kgrib;
 
-    /*
-    fprintf(stderr, "gribUnzip: sourceLen %ld; destLen %ld\n", (long)sourceLen, (long)destLen);
-    fprintf(stderr, "gribUnzip: sourceOff %d; destOff %d\n", bds[12], bds[11]);
-    fprintf(stderr, "gribUnzip: reclen %d; bdslen %d\n", recLen, bdsLen);
-    */
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
 
-    tmpLen = destLen;
-#if defined (HAVE_LIBAEC)
-    strm.next_in   = source;
-    strm.avail_in  = sourceLen;
-    strm.next_out  = dest;
-    strm.avail_out = tmpLen;
+  /* set max header len */
+  len = 16384;
 
-    status = aec_buffer_decode(&strm);
-    if ( status != AEC_OK )
-      Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+  /* add data len */
+  numBytes = (ISEC4_NumBits+7)>>3;
 
-    tmpLen = strm.total_out;
-#else
-    status = SZ_BufftoBuffDecompress(dest, &tmpLen, source, sourceLen, &sz_param);
-    if ( status != SZ_OK )
-      {
-	if ( status == SZ_NO_ENCODER_ERROR )
-	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_PARAM_ERROR )
-	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_MEM_ERROR )
-	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_OUTBUFF_FULL )
-	  Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else
-	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
-#endif
-    /*
-    fprintf(stderr, "gribUnzip: sl = %ld  dl = %ld   tl = %ld\n",
-	    (long)sourceLen, (long)destLen,(long) tmpLen);
-    */
-    if ( tmpLen != destLen )
-      Warning("unzip size differ: code %3d level %3d  ibuflen %ld ubuflen %ld",
-	      PDS_Parameter, PDS_Level2, (long) destLen, (long) tmpLen);
+  len += numBytes*klenp;
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      {
-	long nelem;
-	unsigned char *pbuf;
-	nelem = tmpLen/3;
-	pbuf = (unsigned char*) malloc(tmpLen);
-	for ( i = 0; i < nelem; i++ )
-	  {
-	    pbuf[3*i  ] = dest[        i];
-	    pbuf[3*i+1] = dest[  nelem+i];
-	    pbuf[3*i+2] = dest[2*nelem+i];
-	  }
-	memcpy(dest, pbuf, tmpLen);
-	free(pbuf);
-      }
-#endif
+  /* add bitmap len */
+  if ( bmsIncluded ) len += (klenp+7)>>3;
 
-    bds_ubits = BDS_Flag & 15;
-    BDS_Flag -= bds_ubits;
+#if defined (VECTORCODE)
+  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
+  if ( lGrib == NULL ) SysError("No Memory!");
+#else
+  lGrib = CGrib;
+#endif
 
-    if ( (bdsLen%2) == 1 )
-      {
-	BDS_Flag += 8;
-	bds[bdsLen++] = 0;
-      }
+  isLen = 8;
+  encodeIS(lGrib, &gribLen);
+  lpds = &lGrib[isLen];
+  pdsLen = getPdsLen(isec1);
 
-    SetLen3(bds, 0, bdsLen);
+  encodePDS(lpds, pdsLen,  isec1);
+  gribLen += pdsLen;
+  /*
+  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
+    {
+      static int lwarn_cplx = TRUE;
 
-    gribLen = (bds - dbuf) + bdsLen;
-    
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
+      if ( lwarn_cplx )
+	Message("Complex packing of spectral data unsupported, using simple packing!");
 
-    if ( llarge )
-      {
-	long itemp;
-        bdsLen = gribLen - 4;
-	/*
-	  If a very large product, the section 4 length field holds
-	  the number of bytes in the product after section 4 upto
-	  the end of the padding bytes.
-	  This is a fixup to get round the restriction on product lengths
-	  due to the count being only 24 bits. It is only possible because
-	  the (default) rounding for GRIB products is 120 bytes.
-	*/
-	while ( gribLen%120 ) dbuf[gribLen++] = 0;
+      isec2[5] = 1;
+      isec4[3] = 0;
 
-	if ( gribLen != recLen )
-	  fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
-	
-	itemp = gribLen / (-120);
-	itemp = JP23SET - itemp + 1;
-	
-	SetLen3(dbuf, 4, itemp);
+      lwarn_cplx = FALSE;
+    }
+  */
+  TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  if ( bmsIncluded )
+    {
+      TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+    }
+  else
+    {
+      fsec4size = ISEC4_NumValues;
+    }
 
-	bdsLen = gribLen - bdsLen;
-	    
-	SetLen3(bds, 0, bdsLen);
-      }
-    else
-      {
-	SetLen3(dbuf, 4, recLen);
-      }
-    /*
-    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
-    */
-    if ( llarge )
-      while ( gribLen%120 ) dbuf[gribLen++] = 0;
-    else
-      while ( gribLen & 7 ) dbuf[gribLen++] = 0;
-    /*
-    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
-    */
-  }
-#else
-  if ( libszwarn )
+  bdsstart = gribLen;
+  status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
+				 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
+  if ( status )
     {
-      Warning("Decompression disabled, szlib or libaec not available!");
-      libszwarn = 0;
+      *kret = status;
+      return;
     }
+
+  encodeES(lGrib, &gribLen, bdsstart);
+
+  if ( (size_t) gribLen > kleng*sizeof(int) )
+    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
+
+#if defined (VECTORCODE)
+  if ( (size_t) gribLen > len )
+    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
+
+  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
+
+  free(lGrib);
 #endif
 
-  return (gribLen);
+  ISEC0_GRIB_Len     = gribLen;
+  ISEC0_GRIB_Version = 1;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+
+  *kret = status;
+}
+
+#endif /* T */
+
+void encode_dummy(void)
+{
+  (void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
+  (void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
 }
-static const char grb_libvers[] = "1.6.4" " of ""Jun 27 2014"" ""14:00:04";
+static const char grb_libvers[] = "1.7.0" " of ""Sep 30 2014"" ""13:27:33";
 const char *
 cgribexLibraryVersion(void)
 {
   return (grb_libvers);
 }
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic pop
+#endif
+
 #if defined (HAVE_CONFIG_H)
 #endif
 
@@ -59816,19 +62606,37 @@ cgribexLibraryVersion(void)
 #define STRING(x)	XSTRING(x)
 
 static char gribapi_libvers[64] = "";
+#if  defined  (HAVE_LIBGRIB_API)
+static int gribapi_libvers_init;
+#endif
 
-const char *gribapiLibraryVersion(void)
+
+void gribapiLibraryVersion(int* major_version, int* minor_version, int* revision_version)
 {
 #if  defined  (HAVE_LIBGRIB_API)
   long version = grib_get_api_version();
-  int major_version, minor_version, revision_version;
+  (*major_version)    = version/10000;
+  (*minor_version)    = (version-(*major_version)*10000)/100;
+  (*revision_version) = (version-(*major_version)*10000-(*minor_version)*100);
+#else
+  (*major_version)    = 0;
+  (*minor_version)    = 0;
+  (*revision_version) = 0;
+#endif
+}
+
+const char *gribapiLibraryVersionString(void)
+{
+#if  defined  (HAVE_LIBGRIB_API)
+  if (!gribapi_libvers_init)
+    {
+      int major_version, minor_version, revision_version;
 
-  major_version    = version/10000;
-  minor_version    = (version-major_version*10000)/100;
-  revision_version = (version-major_version*10000-minor_version*100);
+      gribapiLibraryVersion(&major_version, &minor_version, &revision_version);
 
-  sprintf(gribapi_libvers, "%d.%d.%d",
-	  major_version, minor_version, revision_version);
+      sprintf(gribapi_libvers, "%d.%d.%d", major_version, minor_version, revision_version);
+      gribapi_libvers_init = 1;
+    }
 #endif
 
   return (gribapi_libvers);
@@ -59868,8 +62676,8 @@ void gribContainersNew(stream_t * streamptr)
 
       streamptr->gribContainers = (void **) gribContainers;
 #else
-      gribContainer_t *gribContainers;
-      gribContainers = (gribContainer_t *) malloc(nvars*sizeof(gribContainer_t));
+      gribContainer_t *gribContainers
+        = (gribContainer_t *)xmalloc((size_t)nvars*sizeof(gribContainer_t));
 
       for ( int varID = 0; varID < nvars; ++varID )
         {
@@ -59927,57 +62735,34 @@ void gribContainersDelete(stream_t * streamptr)
 #if defined (HAVE_CONFIG_H)
 #endif
 
+#include <inttypes.h>
 #include <stdio.h>
 
 
 void swap4byte(void *ptr, size_t size)
 {
-  INT32 *ptrtmp;
-  int nval;
+  int32_t *ptrtmp = ptr;
 
-  nval = size;
-  if ( nval < 0 ) nval = 0;
-  ptrtmp = (INT32 *) ptr;
-
-  if ( sizeof(INT32) == 4 )
-    {
-      while ( nval-- )
-	{
-	  *ptrtmp = (((*ptrtmp >> 24) & 0x00ff) | ((*ptrtmp & 0x00ff) << 24) |
-		     ((*ptrtmp >>  8) & 0xff00) | ((*ptrtmp & 0xff00) <<  8));
-	  ptrtmp++;
-	}
-    }
+  if (sizeof (int32_t) == 4)
+    for (size_t i = 0; i < size; ++i)
+      ptrtmp[i] = (((ptrtmp[i] >> 24) & 0x00ff) | ((ptrtmp[i] & 0x00ff) << 24) |
+                   ((ptrtmp[i] >>  8) & 0xff00) | ((ptrtmp[i] & 0xff00) <<  8));
   else
-    {
-      Error("not implemented for %d byte data", sizeof(INT32));
-    }
+    Error("not implemented for %d byte data", sizeof(int32_t));
 }
 
 void swap8byte(void *ptr, size_t size)
 {
-  INT64 *ptrtmp;
-  int nval;
+  int64_t *ptrtmp = ptr;
 
-  nval = size;
-  if ( nval < 0 ) nval = 0;
-  ptrtmp = (INT64 *) ptr;
-
-  if ( sizeof(INT64) == 8 )
-    {
-      while ( nval-- )
-	{
-	  *ptrtmp = (((*ptrtmp >> 56) & 0x000000ff) | ((*ptrtmp & 0x000000ff) << 56) |
-		     ((*ptrtmp >> 40) & 0x0000ff00) | ((*ptrtmp & 0x0000ff00) << 40) |
-		     ((*ptrtmp >> 24) & 0x00ff0000) | ((*ptrtmp & 0x00ff0000) << 24) |
-		     ((*ptrtmp >>  8) & 0xff000000) | ((*ptrtmp & 0xff000000) <<  8));
-	  ptrtmp++;
-	}
-    }
+  if (sizeof (int64_t) == 8)
+    for (size_t i = 0; i < size; ++i)
+      ptrtmp[i] = (((ptrtmp[i] >> 56) & 0x000000ff) | ((ptrtmp[i] & 0x000000ff) << 56) |
+                   ((ptrtmp[i] >> 40) & 0x0000ff00) | ((ptrtmp[i] & 0x0000ff00) << 40) |
+                   ((ptrtmp[i] >> 24) & 0x00ff0000) | ((ptrtmp[i] & 0x00ff0000) << 24) |
+                   ((ptrtmp[i] >>  8) & 0xff000000) | ((ptrtmp[i] & 0xff000000) <<  8));
   else
-    {
-      Error("not implemented for %d byte data", sizeof(INT64));
-    }
+    Error("not implemented for %d byte data", sizeof(int64_t));
 }
 /*
  * Local Variables:
@@ -60310,19 +63095,18 @@ void cdfComment(int ncid)
 {
   static char comment[256] = "Climate Data Interface version ";
   static int init = 0;
-  char *blank;
-  int size = 0;
 
   if ( ! init )
     {
       init = 1;
-      blank = strchr(cdiLibraryVersion(), ' ');
-      if ( blank ) size = blank - cdiLibraryVersion();
+      const char *libvers = cdiLibraryVersion();
+      const char *blank = strchr(libvers, ' ');
+      size_t size = blank ? (size_t)(blank - libvers) : 0;
 
-      if ( size == 0 || ! isdigit((int) *cdiLibraryVersion()) )
+      if ( size == 0 || ! isdigit((int) *libvers) )
 	strcat(comment, "??");
       else
-	strncat(comment, cdiLibraryVersion(), size);
+	strncat(comment, libvers, size);
       strcat(comment, " (http://code.zmaw.de/projects/cdi)");
     }
 
@@ -60674,7 +63458,8 @@ namespaceNew()
   else if (namespacesSize == 1)
     {
       /* make room for additional namespace */
-      struct Namespace *newNameSpaces = (struct Namespace*) xmalloc((namespacesSize + 1) * sizeof (namespaces[0]));
+      struct Namespace *newNameSpaces
+        = (struct Namespace *)xmalloc(((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
       memcpy(newNameSpaces, namespaces, sizeof (namespaces[0]));
       namespaces = newNameSpaces;
       ++namespacesSize;
@@ -60684,7 +63469,8 @@ namespaceNew()
     {
       /* make room for additional namespace */
       newNamespaceID = namespacesSize;
-      namespaces = (struct Namespace*) xrealloc(namespaces, (namespacesSize + 1) * sizeof (namespaces[0]));
+      namespaces
+        = (struct Namespace *)xrealloc(namespaces, ((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
       ++namespacesSize;
     }
   else /* implicit: namespacesSize >= NUM_NAMESPACES */
@@ -60925,6 +63711,26 @@ void serializeUnpackInCore(void *buf, int buf_size, int *position,
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <assert.h>
+
+#if defined (HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+static
+void show_stackframe()
+{
+#if defined (HAVE_EXECINFO_H)
+  void *trace[16];
+  size_t i;
+  size_t trace_size = backtrace(trace, 16);
+  char **messages = backtrace_symbols(trace, trace_size);
+
+  fprintf(stderr, "[bt] Execution path:\n");
+  for ( i = 0; i < trace_size; ++i ) fprintf(stderr, "[bt] %s\n", messages[i]);
+  if ( messages ) free(messages);
+#endif
+}
 
 
 enum { MIN_LIST_SIZE = 128 };
@@ -61037,7 +63843,7 @@ reshListCreate(int namespaceID)
   LIST_LOCK();
   if (resHListSize <= namespaceID)
     {
-      resHList = (struct resHList_t*) xrealloc(resHList, (namespaceID + 1) * sizeof (resHList[0]));
+      resHList = (struct resHList_t *)xrealloc(resHList, (namespaceID + 1) * sizeof (resHList[0]));
       for (int i = resHListSize; i <= namespaceID; ++i)
         reshListClearEntry(i);
       resHListSize = namespaceID + 1;
@@ -61061,10 +63867,11 @@ reshListDestruct(int namespaceID)
       for ( int j = 0; j < resHList[namespaceID].size; j++ )
         {
           listElem_t *listElem = resHList[namespaceID].resources + j;
-          if (listElem->status != RESH_UNUSED)
+          if (listElem->status & RESH_IN_USE_BIT)
             listElem->res.v.ops->valDestroy(listElem->res.v.val);
         }
       free(resHList[namespaceID].resources);
+      resHList[namespaceID].resources = NULL;
       reshListClearEntry(namespaceID);
     }
   if (resHList[callerNamespaceID].resources)
@@ -61079,6 +63886,7 @@ static void listDestroy ( void )
   for (int i = resHListSize; i > 0; --i)
     if (resHList[i-1].resources)
       namespaceDelete(i-1);
+  resHListSize = 0;
   free(resHList);
   resHList = NULL;
   cdiReset();
@@ -61116,26 +63924,25 @@ void listSizeExtend()
 {
   int nsp = namespaceGetActive ();
   int oldSize = resHList[nsp].size;
-  int newListSize = oldSize + MIN_LIST_SIZE;
+  size_t newListSize = (size_t)oldSize + MIN_LIST_SIZE;
 
   resHList[nsp].resources = (listElem_t*) xrealloc(resHList[nsp].resources,
                                                    newListSize * sizeof(listElem_t));
 
   listElem_t *r = resHList[nsp].resources;
-  for (int i = oldSize; i < newListSize; ++i)
+  for (size_t i = (size_t)oldSize; i < newListSize; ++i)
     {
-      r[i].res.free.next = i + 1;
-      r[i].res.free.prev = i - 1;
+      r[i].res.free.next = (int)i + 1;
+      r[i].res.free.prev = (int)i - 1;
       r[i].status = RESH_UNUSED;
     }
 
   if (resHList[nsp].freeHead != -1)
-    r[resHList[nsp].freeHead].res.free.next
-      = newListSize - 1;
+    r[resHList[nsp].freeHead].res.free.prev = (int)newListSize - 1;
   r[newListSize-1].res.free.next = resHList[nsp].freeHead;
   r[oldSize].res.free.prev = -1;
   resHList[nsp].freeHead = oldSize;
-  resHList[nsp].size = newListSize;
+  resHList[nsp].size = (int)newListSize;
 }
 
 /**************************************************************/
@@ -61144,13 +63951,17 @@ static void
 reshPut_(int nsp, int entry, void *p, const resOps *ops)
 {
   listElem_t *newListElem = resHList[nsp].resources + entry;
-  int next = newListElem->res.free.next;
+  int next = newListElem->res.free.next,
+    prev = newListElem->res.free.prev;
   if (next != -1)
-    resHList[nsp].resources[next].res.free.prev = -1;
-  resHList[nsp].freeHead = next;
+    resHList[nsp].resources[next].res.free.prev = prev;
+  if (prev != -1)
+    resHList[nsp].resources[prev].res.free.next = next;
+  else
+    resHList[nsp].freeHead = next;
   newListElem->res.v.val = p;
   newListElem->res.v.ops = ops;
-  newListElem->status = RESH_ASSIGNED;
+  newListElem->status = RESH_DESYNC_IN_USE;
 }
 
 int reshPut ( void *p, const resOps *ops )
@@ -61181,18 +63992,39 @@ reshRemove_(int nsp, int idx)
   int curFree = resHList[nsp].freeHead;
   listElem_t *r = resHList[nsp].resources;
   r[idx].res.free.next = curFree;
+  r[idx].res.free.prev = -1;
   if (curFree != -1)
     r[curFree].res.free.prev = idx;
-  r[idx].status = RESH_UNUSED;
+  r[idx].status = RESH_DESYNC_DELETED;
   resHList[nsp].freeHead = idx;
 }
 
-void reshRemove ( cdiResH resH, const resOps * ops )
+void reshDestroy(cdiResH resH)
 {
   int nsp;
   namespaceTuple_t nspT;
 
-  LIST_INIT(1);
+  LIST_LOCK();
+
+  nsp = namespaceGetActive ();
+
+  nspT = namespaceResHDecode ( resH );
+
+  xassert ( nspT.nsp == nsp
+            && nspT.idx >= 0
+            && nspT.idx < resHList[nsp].size
+            && resHList[nsp].resources[nspT.idx].res.v.ops);
+
+  if (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
+    reshRemove_(nsp, nspT.idx);
+
+  LIST_UNLOCK();
+}
+
+void reshRemove ( cdiResH resH, const resOps * ops )
+{
+  int nsp;
+  namespaceTuple_t nspT;
 
   LIST_LOCK();
 
@@ -61203,7 +64035,7 @@ void reshRemove ( cdiResH resH, const resOps * ops )
   xassert ( nspT.nsp == nsp
             && nspT.idx >= 0
             && nspT.idx < resHList[nsp].size
-            && resHList[nsp].resources[nspT.idx].status != RESH_UNUSED
+            && (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
             && resHList[nsp].resources[nspT.idx].res.v.ops
             && resHList[nsp].resources[nspT.idx].res.v.ops == ops );
 
@@ -61224,7 +64056,7 @@ void reshReplace(cdiResH resH, void *p, const resOps *ops)
   while (resHList[nsp].size <= nspT.idx)
     listSizeExtend();
   listElem_t *q = resHList[nsp].resources + nspT.idx;
-  if (q->status != RESH_UNUSED)
+  if (q->status & RESH_IN_USE_BIT)
     {
       q->res.v.ops->valDestroy(q->res.v.val);
       reshRemove_(nsp, nspT.idx);
@@ -61235,7 +64067,7 @@ void reshReplace(cdiResH resH, void *p, const resOps *ops)
 
 
 static listElem_t *
-reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
+reshGetElem(const char *caller, const char* expressionString, cdiResH resH, const resOps *ops)
 {
   listElem_t *listElem;
   int nsp;
@@ -61249,9 +64081,9 @@ reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
   nsp = namespaceGetActive ();
 
   nspT = namespaceResHDecode ( resH );
+  assert(nspT.idx >= 0);
 
   if (nspT.nsp == nsp &&
-      nspT.idx >= 0 &&
       nspT.idx < resHList[nsp].size)
     {
       listElem = resHList[nsp].resources + nspT.idx;
@@ -61260,20 +64092,32 @@ reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
   else
     {
       LIST_UNLOCK();
-      xabortC(caller, "Invalid namespace %d or index %d for resource handle %d when using namespace %d of size %d!",
-              nspT.nsp, nspT.idx, (int)resH, nsp, resHList[nsp].size);
+      show_stackframe();
+
+      if ( resH == CDI_UNDEFID )
+        {
+          xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is CDI_UNDEFID (= %d).\n\tThis is most likely the result of a failed earlier call. Please check the IDs returned by CDI.", expressionString, caller, resH);
+        }
+      else
+        {
+          xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is garbage (= %d, which resolves to namespace = %d, index = %d).\n\tThis is either the result of using an uninitialized variable,\n\tof using a value as an ID that is not an ID,\n\tor of using an ID after it has been invalidated.", expressionString, caller, resH, nspT.nsp, nspT.idx);
+        }
     }
 
   if ( !(listElem && listElem->res.v.ops == ops) )
-    xabortC(caller, "Invalid resource handle %d, list element not found!",
-            (int)resH);
+    {
+      show_stackframe();
+
+      xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: list element not found. The failed ID is %d", expressionString, caller, (int)resH);
+    }
+
   return listElem;
 }
 
 
-void *reshGetValue(const char * caller, cdiResH resH, const resOps * ops)
+void *reshGetValue(const char * caller, const char* expressionString, cdiResH resH, const resOps * ops)
 {
-  return reshGetElem(caller, resH, ops)->res.v.val;
+  return reshGetElem(caller, expressionString, resH, ops)->res.v.val;
 }
 
 /**************************************************************/
@@ -61291,7 +64135,7 @@ void reshGetResHListOfType ( int c, int * resHs, const resOps * ops )
   nsp = namespaceGetActive ();
 
   for ( i = 0; i < resHList[nsp].size && j < c; i++ )
-    if (resHList[nsp].resources[i].status != RESH_UNUSED
+    if ((resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
         && resHList[nsp].resources[i].res.v.ops == ops)
       resHs[j++] = namespaceIdxEncode2(nsp, i);
 
@@ -61311,7 +64155,7 @@ cdiResHApply(enum cdiApplyRet (*func)(int id, void *res, const resOps *p,
   int nsp = namespaceGetActive ();
   enum cdiApplyRet ret = CDI_APPLY_GO_ON;
   for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
-    if (resHList[nsp].resources[i].status != RESH_UNUSED)
+    if (resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
       ret = func(namespaceIdxEncode2(nsp, i),
                  resHList[nsp].resources[i].res.v.val,
                  resHList[nsp].resources[i].res.v.ops, data);
@@ -61335,7 +64179,7 @@ cdiResHFilterApply(const resOps *p,
   enum cdiApplyRet ret = CDI_APPLY_GO_ON;
   listElem_t *r = resHList[nsp].resources;
   for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
-    if (r[i].status != RESH_UNUSED && r[i].res.v.ops == p)
+    if ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == p)
       ret = func(namespaceIdxEncode2(nsp, i), r[i].res.v.val,
                  data);
   LIST_UNLOCK();
@@ -61361,7 +64205,7 @@ int reshCountType ( const resOps * ops )
 
   listElem_t *r = resHList[nsp].resources;
   for ( i = 0; i < resHList[nsp].size; i++ )
-    countType += (r[i].status != RESH_UNUSED && r[i].res.v.ops == ops);
+    countType += ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == ops);
 
   LIST_UNLOCK();
 
@@ -61371,42 +64215,47 @@ int reshCountType ( const resOps * ops )
 /**************************************************************/
 
 int
-reshResourceGetPackSize(int resH, const resOps *ops, void *context)
+reshResourceGetPackSize_intern(int resH, const resOps *ops, void *context, const char* caller, const char* expressionString)
 {
-  listElem_t *curr = reshGetElem(__func__, resH, ops);
+  listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
   return curr->res.v.ops->valGetPackSize(curr->res.v.val, context);
 }
 
 void
-reshPackResource(int resH, const resOps *ops,
-                 void *buf, int buf_size, int *position, void *context)
+reshPackResource_intern(int resH, const resOps *ops, void *buf, int buf_size, int *position, void *context,
+                        const char* caller, const char* expressionString)
 {
-  listElem_t *curr = reshGetElem(__func__, resH, ops);
+  listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
   curr->res.v.ops->valPack(curr->res.v.val, buf, buf_size, position, context);
 }
 
 
 static int getPackBufferSize(void *context)
 {
-  int nsp, i;
   int intpacksize, packBufferSize = 0;
 
-  nsp = namespaceGetActive ();
+  int nsp = namespaceGetActive ();
 
   /* pack start marker, namespace and sererator marker */
   packBufferSize += 3 * (intpacksize = serializeGetSize(1, DATATYPE_INT, context));
 
   /* pack resources, type marker and seperator marker */
   listElem_t *r = resHList[nsp].resources;
-  for ( i = 0; i < resHList[nsp].size; i++)
-    if (r[i].status == RESH_ASSIGNED)
+  for ( int i = 0; i < resHList[nsp].size; i++)
+    if (r[i].status & RESH_SYNC_BIT)
       {
-        xassert ( r[i].res.v.ops );
-
-        /* message plus frame of 2 ints */
-        packBufferSize +=
-          r[i].res.v.ops->valGetPackSize(r[i].res.v.val, context)
-          + 2 * intpacksize;
+        if (r[i].status == RESH_DESYNC_DELETED)
+          {
+            packBufferSize += 3 * intpacksize;
+          }
+        else if (r[i].status == RESH_DESYNC_IN_USE)
+          {
+            xassert ( r[i].res.v.ops );
+            /* message plus frame of 2 ints */
+            packBufferSize +=
+              r[i].res.v.ops->valGetPackSize(r[i].res.v.val, context)
+              + 2 * intpacksize;
+          }
       }
   /* end marker */
   packBufferSize += intpacksize;
@@ -61435,7 +64284,7 @@ void reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
   int nsp = namespaceGetActive ();
 
   int pBSize = *packBufferSize = getPackBufferSize(context);
-  char *pB = *packBuffer = (char*) xcalloc(1, *packBufferSize);
+  char *pB = *packBuffer = (char *)xcalloc(1, (size_t)pBSize);
 
   {
     int header[3] = { start, nsp, sep };
@@ -61444,24 +64293,29 @@ void reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
 
   listElem_t *r = resHList[nsp].resources;
   for ( i = 0; i < resHList[nsp].size; i++ )
-    if ( r[i].status == RESH_ASSIGNED)
+    if (r[i].status & RESH_SYNC_BIT)
       {
-        listElem_t * curr = r + i;
-        xassert ( curr->res.v.ops );
-
-        type = curr->res.v.ops->valTxCode ();
-
-        if ( ! type ) continue;
-
-        serializePack( &type, 1, DATATYPE_INT, * packBuffer,
-                       * packBufferSize, &packBufferPos, context);
-
-        curr->res.v.ops->valPack(curr->res.v.val,
-                                 pB, pBSize, &packBufferPos, context);
-
-        serializePack(&sep, 1, DATATYPE_INT, pB, pBSize, &packBufferPos, context);
-
-        curr->status = RESH_CLOSED;
+        if (r[i].status == RESH_DESYNC_DELETED)
+          {
+            enum { del_ints = 3 };
+            int temp[del_ints] = { RESH_DELETE, namespaceIdxEncode2(nsp, i), SEPARATOR };
+            serializePack(temp, del_ints, DATATYPE_INT,
+                          pB, pBSize, &packBufferPos, context);
+          }
+        else
+          {
+            listElem_t * curr = r + i;
+            xassert ( curr->res.v.ops );
+            type = curr->res.v.ops->valTxCode ();
+            if ( ! type ) continue;
+            serializePack(&type, 1, DATATYPE_INT, pB,
+                          pBSize, &packBufferPos, context);
+            curr->res.v.ops->valPack(curr->res.v.val,
+                                     pB, pBSize, &packBufferPos, context);
+            serializePack(&sep, 1, DATATYPE_INT,
+                          pB, pBSize, &packBufferPos, context);
+          }
+        r[i].status &= ~RESH_SYNC_BIT;
       }
 
   LIST_UNLOCK();
@@ -61479,7 +64333,7 @@ void reshSetStatus ( cdiResH resH, const resOps * ops, int status )
   namespaceTuple_t nspT;
   listElem_t * listElem;
 
-  xassert(ops && status != RESH_UNUSED);
+  xassert(ops && (status & RESH_IN_USE_BIT));
 
   LIST_INIT(1);
 
@@ -61566,8 +64420,8 @@ int reshListCompare ( int nsp0, int nsp1 )
     *resources1 = resHList[nsp1].resources;
   for (i = 0; i < listSizeMin; i++)
     {
-      int occupied0 = resources0[i].status != RESH_UNUSED,
-        occupied1 = resources1[i].status != RESH_UNUSED;
+      int occupied0 = (resources0[i].status & RESH_IN_USE_BIT) != 0,
+        occupied1 = (resources1[i].status & RESH_IN_USE_BIT) != 0;
       /* occupation mismatch ? */
       int diff = occupied0 ^ occupied1;
       valCompare |= (diff << cdiResHListOccupationMismatch);
@@ -61589,11 +64443,11 @@ int reshListCompare ( int nsp0, int nsp1 )
     }
   /* find resources in nsp 0 beyond end of nsp 1 */
   for (int j = listSizeMin; j < resHList[nsp0].size; ++j)
-    valCompare |= ((resources0[j].status != RESH_UNUSED)
+    valCompare |= (((resources0[j].status & RESH_IN_USE_BIT) != 0)
                    << cdiResHListOccupationMismatch);
   /* find resources in nsp 1 beyond end of nsp 0 */
   for (; i < resHList[nsp1].size; ++i)
-    valCompare |= ((resources1[i].status != RESH_UNUSED)
+    valCompare |= (((resources1[i].status & RESH_IN_USE_BIT) != 0)
                    << cdiResHListOccupationMismatch);
 
   LIST_UNLOCK();
@@ -61632,7 +64486,7 @@ void reshListPrint(FILE *fp)
       for ( j = 0; j < resHList[i].size; j++ )
         {
           curr = resHList[i].resources + j;
-          if (curr->status != RESH_UNUSED)
+          if (!(curr->status & RESH_IN_USE_BIT))
             {
               curr->res.v.ops->valPrint(curr->res.v.val, fp);
               fprintf ( fp, "\n" );
@@ -61655,8 +64509,8 @@ void reshListPrint(FILE *fp)
  * require-trailing-newline: t
  * End:
  */
-   static char cdi_libvers[] = "1.6.4" " of ""Jun 27 2014"" ""14:11:36";
-char *cdiLibraryVersion(void)
+   static const char cdi_libvers[] = "1.6.5.1" " of ""Oct 31 2014"" ""21:33:19";
+const char *cdiLibraryVersion(void)
 {
   return (cdi_libvers);
 }
@@ -64192,20 +67046,20 @@ FCALLSCSUB1 (streamClose, STREAMCLOSE, streamclose, INT)
 FCALLSCSUB1 (streamSync, STREAMSYNC, streamsync, INT)
 FCALLSCSUB2 (streamDefVlist, STREAMDEFVLIST, streamdefvlist, INT, INT)
 FCALLSCFUN1 (INT, streamInqVlist, STREAMINQVLIST, streaminqvlist, INT)
+
+/*  PIO:  */
+
 FCALLSCFUN1 (INT, streamInqVlistIDorig, STREAMINQVLISTIDORIG, streaminqvlistidorig, INT)
 FCALLSCFUN1 (INT, streamInqFiletype, STREAMINQFILETYPE, streaminqfiletype, INT)
 FCALLSCSUB2 (streamDefByteorder, STREAMDEFBYTEORDER, streamdefbyteorder, INT, INT)
 FCALLSCFUN1 (INT, streamInqByteorder, STREAMINQBYTEORDER, streaminqbyteorder, INT)
 FCALLSCSUB2 (streamDefCompType, STREAMDEFCOMPTYPE, streamdefcomptype, INT, INT)
-FCALLSCSUB2 (streamDefCompLevel, STREAMDEFCOMPLEVEL, streamdefcomplevel, INT, INT)
 FCALLSCFUN1 (INT, streamInqCompType, STREAMINQCOMPTYPE, streaminqcomptype, INT)
+FCALLSCSUB2 (streamDefCompLevel, STREAMDEFCOMPLEVEL, streamdefcomplevel, INT, INT)
 FCALLSCFUN1 (INT, streamInqCompLevel, STREAMINQCOMPLEVEL, streaminqcomplevel, INT)
 FCALLSCFUN2 (INT, streamDefTimestep, STREAMDEFTIMESTEP, streamdeftimestep, INT, INT)
-
-/*  query currently set timestep id  */
-
-FCALLSCFUN1 (INT, streamInqCurTimestepID, STREAMINQCURTIMESTEPID, streaminqcurtimestepid, INT)
 FCALLSCFUN2 (INT, streamInqTimestep, STREAMINQTIMESTEP, streaminqtimestep, INT, INT)
+FCALLSCFUN1 (INT, streamInqCurTimestepID, STREAMINQCURTIMESTEPID, streaminqcurtimestepid, INT)
 FCALLSCFUN1 (STRING, streamFilename, STREAMFILENAME, streamfilename, INT)
 FCALLSCFUN1 (STRING, streamFilesuffix, STREAMFILESUFFIX, streamfilesuffix, INT)
 FCALLSCFUN1 (INT, streamNtsteps, STREAMNTSTEPS, streamntsteps, INT)
@@ -64213,21 +67067,23 @@ FCALLSCFUN1 (INT, streamInqNvars, STREAMINQNVARS, streaminqnvars, INT)
 
 /*  STREAM var I/O routines  */
 
-FCALLSCSUB4 (streamReadVar, STREAMREADVAR, streamreadvar, INT, INT, PDOUBLE, PINT)
 FCALLSCSUB4 (streamWriteVar, STREAMWRITEVAR, streamwritevar, INT, INT, PDOUBLE, INT)
 FCALLSCSUB4 (streamWriteVarF, STREAMWRITEVARF, streamwritevarf, INT, INT, PFLOAT, INT)
-FCALLSCSUB5 (streamReadVarSlice, STREAMREADVARSLICE, streamreadvarslice, INT, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB4 (streamReadVar, STREAMREADVAR, streamreadvar, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB4 (streamReadVarF, STREAMREADVARF, streamreadvarf, INT, INT, PFLOAT, PINT)
 FCALLSCSUB5 (streamWriteVarSlice, STREAMWRITEVARSLICE, streamwritevarslice, INT, INT, INT, PDOUBLE, INT)
 FCALLSCSUB5 (streamWriteVarSliceF, STREAMWRITEVARSLICEF, streamwritevarslicef, INT, INT, INT, PFLOAT, INT)
+FCALLSCSUB5 (streamReadVarSlice, STREAMREADVARSLICE, streamreadvarslice, INT, INT, INT, PDOUBLE, PINT)
+FCALLSCSUB5 (streamReadVarSliceF, STREAMREADVARSLICEF, streamreadvarslicef, INT, INT, INT, PFLOAT, PINT)
 FCALLSCSUB5 (streamWriteVarChunk, STREAMWRITEVARCHUNK, streamwritevarchunk, INT, INT, INTVV, PDOUBLE, INT)
 
 /*  STREAM record I/O routines  */
 
-FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
 FCALLSCSUB3 (streamDefRecord, STREAMDEFRECORD, streamdefrecord, INT, INT, INT)
-FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, PDOUBLE, PINT)
+FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
 FCALLSCSUB3 (streamWriteRecord, STREAMWRITERECORD, streamwriterecord, INT, PDOUBLE, INT)
 FCALLSCSUB3 (streamWriteRecordF, STREAMWRITERECORDF, streamwriterecordf, INT, PFLOAT, INT)
+FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, PDOUBLE, PINT)
 FCALLSCSUB2 (streamCopyRecord, STREAMCOPYRECORD, streamcopyrecord, INT, INT)
 
 /*  VLIST routines  */
@@ -64278,8 +67134,8 @@ FCALLSCFUN2 (INT, vlistInqVarZaxis, VLISTINQVARZAXIS, vlistinqvarzaxis, INT, INT
 /*  used in MPIOM  */
 
 FCALLSCFUN2 (INT, vlistInqVarID, VLISTINQVARID, vlistinqvarid, INT, INT)
-FCALLSCFUN2 (INT, vlistInqVarTsteptype, VLISTINQVARTSTEPTYPE, vlistinqvartsteptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarTsteptype, VLISTDEFVARTSTEPTYPE, vlistdefvartsteptype, INT, INT, INT)
+FCALLSCFUN2 (INT, vlistInqVarTsteptype, VLISTINQVARTSTEPTYPE, vlistinqvartsteptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarCompType, VLISTDEFVARCOMPTYPE, vlistdefvarcomptype, INT, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarCompType, VLISTINQVARCOMPTYPE, vlistinqvarcomptype, INT, INT)
 FCALLSCSUB3 (vlistDefVarCompLevel, VLISTDEFVARCOMPLEVEL, vlistdefvarcomplevel, INT, INT, INT)
@@ -64323,6 +67179,8 @@ FCALLSCSUB3 (vlistDefVarTimaccu, VLISTDEFVARTIMACCU, vlistdefvartimaccu, INT, IN
 FCALLSCFUN2 (INT, vlistInqVarTimaccu, VLISTINQVARTIMACCU, vlistinqvartimaccu, INT, INT)
 FCALLSCSUB3 (vlistDefVarTypeOfGeneratingProcess, VLISTDEFVARTYPEOFGENERATINGPROCESS, vlistdefvartypeofgeneratingprocess, INT, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarTypeOfGeneratingProcess, VLISTINQVARTYPEOFGENERATINGPROCESS, vlistinqvartypeofgeneratingprocess, INT, INT)
+FCALLSCSUB3 (vlistDefVarProductDefinitionTemplate, VLISTDEFVARPRODUCTDEFINITIONTEMPLATE, vlistdefvarproductdefinitiontemplate, INT, INT, INT)
+FCALLSCFUN2 (INT, vlistInqVarProductDefinitionTemplate, VLISTINQVARPRODUCTDEFINITIONTEMPLATE, vlistinqvarproductdefinitiontemplate, INT, INT)
 FCALLSCFUN2 (INT, vlistInqVarSize, VLISTINQVARSIZE, vlistinqvarsize, INT, INT)
 FCALLSCSUB4 (vlistDefIndex, VLISTDEFINDEX, vlistdefindex, INT, INT, INT, INT)
 FCALLSCFUN3 (INT, vlistInqIndex, VLISTINQINDEX, vlistinqindex, INT, INT, INT)
@@ -64383,19 +67241,19 @@ FCALLSCFUN2 (INT, gridInqXvals, GRIDINQXVALS, gridinqxvals, INT, PDOUBLE)
 FCALLSCSUB2 (gridDefYvals, GRIDDEFYVALS, griddefyvals, INT, PDOUBLE)
 FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, PDOUBLE)
 FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING)
+FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING)
+FCALLSCSUB2 (gridInqXlongname, GRIDINQXLONGNAME, gridinqxlongname, INT, PSTRING)
 FCALLSCSUB2 (gridDefXunits, GRIDDEFXUNITS, griddefxunits, INT, STRING)
+FCALLSCSUB2 (gridInqXunits, GRIDINQXUNITS, gridinqxunits, INT, PSTRING)
 FCALLSCSUB2 (gridDefYname, GRIDDEFYNAME, griddefyname, INT, STRING)
+FCALLSCSUB2 (gridInqYname, GRIDINQYNAME, gridinqyname, INT, PSTRING)
 FCALLSCSUB2 (gridDefYlongname, GRIDDEFYLONGNAME, griddefylongname, INT, STRING)
+FCALLSCSUB2 (gridInqYlongname, GRIDINQYLONGNAME, gridinqylongname, INT, PSTRING)
 FCALLSCSUB2 (gridDefYunits, GRIDDEFYUNITS, griddefyunits, INT, STRING)
-FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING)
-FCALLSCSUB2 (gridInqXlongname, GRIDINQXLONGNAME, gridinqxlongname, INT, PSTRING)
+FCALLSCSUB2 (gridInqYunits, GRIDINQYUNITS, gridinqyunits, INT, PSTRING)
 FCALLSCSUB2 (gridInqXstdname, GRIDINQXSTDNAME, gridinqxstdname, INT, PSTRING)
-FCALLSCSUB2 (gridInqXunits, GRIDINQXUNITS, gridinqxunits, INT, PSTRING)
-FCALLSCSUB2 (gridInqYname, GRIDINQYNAME, gridinqyname, INT, PSTRING)
-FCALLSCSUB2 (gridInqYlongname, GRIDINQYLONGNAME, gridinqylongname, INT, PSTRING)
 FCALLSCSUB2 (gridInqYstdname, GRIDINQYSTDNAME, gridinqystdname, INT, PSTRING)
-FCALLSCSUB2 (gridInqYunits, GRIDINQYUNITS, gridinqyunits, INT, PSTRING)
 FCALLSCSUB2 (gridDefPrec, GRIDDEFPREC, griddefprec, INT, INT)
 FCALLSCFUN1 (INT, gridInqPrec, GRIDINQPREC, gridinqprec, INT)
 FCALLSCFUN2 (DOUBLE, gridInqXval, GRIDINQXVAL, gridinqxval, INT, INT)
@@ -64404,25 +67262,25 @@ FCALLSCFUN1 (DOUBLE, gridInqXinc, GRIDINQXINC, gridinqxinc, INT)
 FCALLSCFUN1 (DOUBLE, gridInqYinc, GRIDINQYINC, gridinqyinc, INT)
 FCALLSCFUN1 (INT, gridIsCircular, GRIDISCIRCULAR, gridiscircular, INT)
 FCALLSCFUN1 (INT, gridIsRotated, GRIDISROTATED, gridisrotated, INT)
-FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT)
 FCALLSCSUB2 (gridDefXpole, GRIDDEFXPOLE, griddefxpole, INT, DOUBLE)
-FCALLSCFUN1 (DOUBLE, gridInqYpole, GRIDINQYPOLE, gridinqypole, INT)
+FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT)
 FCALLSCSUB2 (gridDefYpole, GRIDDEFYPOLE, griddefypole, INT, DOUBLE)
-FCALLSCFUN1 (DOUBLE, gridInqAngle, GRIDINQANGLE, gridinqangle, INT)
+FCALLSCFUN1 (DOUBLE, gridInqYpole, GRIDINQYPOLE, gridinqypole, INT)
 FCALLSCSUB2 (gridDefAngle, GRIDDEFANGLE, griddefangle, INT, DOUBLE)
-FCALLSCSUB2 (gridDefTrunc, GRIDDEFTRUNC, griddeftrunc, INT, INT)
+FCALLSCFUN1 (DOUBLE, gridInqAngle, GRIDINQANGLE, gridinqangle, INT)
 FCALLSCFUN1 (INT, gridInqTrunc, GRIDINQTRUNC, gridinqtrunc, INT)
+FCALLSCSUB2 (gridDefTrunc, GRIDDEFTRUNC, griddeftrunc, INT, INT)
 
 /*  Hexagonal GME grid  */
 
-FCALLSCFUN1 (INT, gridInqGMEnd, GRIDINQGMEND, gridinqgmend, INT)
 FCALLSCSUB2 (gridDefGMEnd, GRIDDEFGMEND, griddefgmend, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni, GRIDINQGMENI, gridinqgmeni, INT)
+FCALLSCFUN1 (INT, gridInqGMEnd, GRIDINQGMEND, gridinqgmend, INT)
 FCALLSCSUB2 (gridDefGMEni, GRIDDEFGMENI, griddefgmeni, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni2, GRIDINQGMENI2, gridinqgmeni2, INT)
+FCALLSCFUN1 (INT, gridInqGMEni, GRIDINQGMENI, gridinqgmeni, INT)
 FCALLSCSUB2 (gridDefGMEni2, GRIDDEFGMENI2, griddefgmeni2, INT, INT)
-FCALLSCFUN1 (INT, gridInqGMEni3, GRIDINQGMENI3, gridinqgmeni3, INT)
+FCALLSCFUN1 (INT, gridInqGMEni2, GRIDINQGMENI2, gridinqgmeni2, INT)
 FCALLSCSUB2 (gridDefGMEni3, GRIDDEFGMENI3, griddefgmeni3, INT, INT)
+FCALLSCFUN1 (INT, gridInqGMEni3, GRIDINQGMENI3, gridinqgmeni3, INT)
 
 /*  Reference of an unstructured grid  */
 
@@ -64485,12 +67343,12 @@ FCALLSCFUN1 (INT, zaxisInqNumber, ZAXISINQNUMBER, zaxisinqnumber, INT)
 FCALLSCSUB2 (zaxisDefUUID, ZAXISDEFUUID, zaxisdefuuid, INT, PPSTRING)
 FCALLSCSUB2 (zaxisInqUUID, ZAXISINQUUID, zaxisinquuid, INT, PPSTRING)
 FCALLSCSUB2 (zaxisDefName, ZAXISDEFNAME, zaxisdefname, INT, STRING)
-FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
-FCALLSCSUB2 (zaxisDefUnits, ZAXISDEFUNITS, zaxisdefunits, INT, STRING)
 FCALLSCSUB2 (zaxisInqName, ZAXISINQNAME, zaxisinqname, INT, PSTRING)
+FCALLSCSUB2 (zaxisDefLongname, ZAXISDEFLONGNAME, zaxisdeflongname, INT, STRING)
 FCALLSCSUB2 (zaxisInqLongname, ZAXISINQLONGNAME, zaxisinqlongname, INT, PSTRING)
-FCALLSCSUB2 (zaxisInqStdname, ZAXISINQSTDNAME, zaxisinqstdname, INT, PSTRING)
+FCALLSCSUB2 (zaxisDefUnits, ZAXISDEFUNITS, zaxisdefunits, INT, STRING)
 FCALLSCSUB2 (zaxisInqUnits, ZAXISINQUNITS, zaxisinqunits, INT, PSTRING)
+FCALLSCSUB2 (zaxisInqStdname, ZAXISINQSTDNAME, zaxisinqstdname, INT, PSTRING)
 FCALLSCSUB2 (zaxisDefPrec, ZAXISDEFPREC, zaxisdefprec, INT, INT)
 FCALLSCFUN1 (INT, zaxisInqPrec, ZAXISINQPREC, zaxisinqprec, INT)
 FCALLSCSUB2 (zaxisDefPositive, ZAXISDEFPOSITIVE, zaxisdefpositive, INT, INT)
@@ -64500,14 +67358,14 @@ FCALLSCFUN1 (INT, zaxisInqLtype, ZAXISINQLTYPE, zaxisinqltype, INT)
 FCALLSCSUB3 (zaxisDefVct, ZAXISDEFVCT, zaxisdefvct, INT, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisInqVct, ZAXISINQVCT, zaxisinqvct, INT, PDOUBLE)
 FCALLSCFUN1 (INT, zaxisInqVctSize, ZAXISINQVCTSIZE, zaxisinqvctsize, INT)
+FCALLSCSUB2 (zaxisDefLbounds, ZAXISDEFLBOUNDS, zaxisdeflbounds, INT, PDOUBLE)
 FCALLSCFUN2 (INT, zaxisInqLbounds, ZAXISINQLBOUNDS, zaxisinqlbounds, INT, PDOUBLE)
-FCALLSCFUN2 (INT, zaxisInqUbounds, ZAXISINQUBOUNDS, zaxisinqubounds, INT, PDOUBLE)
-FCALLSCFUN2 (INT, zaxisInqWeights, ZAXISINQWEIGHTS, zaxisinqweights, INT, PDOUBLE)
 FCALLSCFUN2 (DOUBLE, zaxisInqLbound, ZAXISINQLBOUND, zaxisinqlbound, INT, INT)
-FCALLSCFUN2 (DOUBLE, zaxisInqUbound, ZAXISINQUBOUND, zaxisinqubound, INT, INT)
-FCALLSCSUB2 (zaxisDefLbounds, ZAXISDEFLBOUNDS, zaxisdeflbounds, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisDefUbounds, ZAXISDEFUBOUNDS, zaxisdefubounds, INT, PDOUBLE)
+FCALLSCFUN2 (INT, zaxisInqUbounds, ZAXISINQUBOUNDS, zaxisinqubounds, INT, PDOUBLE)
+FCALLSCFUN2 (DOUBLE, zaxisInqUbound, ZAXISINQUBOUND, zaxisinqubound, INT, INT)
 FCALLSCSUB2 (zaxisDefWeights, ZAXISDEFWEIGHTS, zaxisdefweights, INT, PDOUBLE)
+FCALLSCFUN2 (INT, zaxisInqWeights, ZAXISINQWEIGHTS, zaxisinqweights, INT, PDOUBLE)
 FCALLSCSUB2 (zaxisChangeType, ZAXISCHANGETYPE, zaxischangetype, INT, INT)
 
 /*  TAXIS routines  */
@@ -64519,10 +67377,16 @@ FCALLSCSUB2 (taxisCopyTimestep, TAXISCOPYTIMESTEP, taxiscopytimestep, INT, INT)
 FCALLSCSUB2 (taxisDefType, TAXISDEFTYPE, taxisdeftype, INT, INT)
 FCALLSCSUB2 (taxisDefVdate, TAXISDEFVDATE, taxisdefvdate, INT, INT)
 FCALLSCSUB2 (taxisDefVtime, TAXISDEFVTIME, taxisdefvtime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqVdate, TAXISINQVDATE, taxisinqvdate, INT)
+FCALLSCFUN1 (INT, taxisInqVtime, TAXISINQVTIME, taxisinqvtime, INT)
 FCALLSCSUB2 (taxisDefRdate, TAXISDEFRDATE, taxisdefrdate, INT, INT)
 FCALLSCSUB2 (taxisDefRtime, TAXISDEFRTIME, taxisdefrtime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqRdate, TAXISINQRDATE, taxisinqrdate, INT)
+FCALLSCFUN1 (INT, taxisInqRtime, TAXISINQRTIME, taxisinqrtime, INT)
 FCALLSCSUB2 (taxisDefFdate, TAXISDEFFDATE, taxisdeffdate, INT, INT)
 FCALLSCSUB2 (taxisDefFtime, TAXISDEFFTIME, taxisdefftime, INT, INT)
+FCALLSCFUN1 (INT, taxisInqFdate, TAXISINQFDATE, taxisinqfdate, INT)
+FCALLSCFUN1 (INT, taxisInqFtime, TAXISINQFTIME, taxisinqftime, INT)
 FCALLSCFUN1 (INT, taxisHasBounds, TAXISHASBOUNDS, taxishasbounds, INT)
 FCALLSCSUB1 (taxisDeleteBounds, TAXISDELETEBOUNDS, taxisdeletebounds, INT)
 FCALLSCSUB3 (taxisDefVdateBounds, TAXISDEFVDATEBOUNDS, taxisdefvdatebounds, INT, INT, INT)
@@ -64530,17 +67394,15 @@ FCALLSCSUB3 (taxisDefVtimeBounds, TAXISDEFVTIMEBOUNDS, taxisdefvtimebounds, INT,
 FCALLSCSUB3 (taxisInqVdateBounds, TAXISINQVDATEBOUNDS, taxisinqvdatebounds, INT, PINT, PINT)
 FCALLSCSUB3 (taxisInqVtimeBounds, TAXISINQVTIMEBOUNDS, taxisinqvtimebounds, INT, PINT, PINT)
 FCALLSCSUB2 (taxisDefCalendar, TAXISDEFCALENDAR, taxisdefcalendar, INT, INT)
+FCALLSCFUN1 (INT, taxisInqCalendar, TAXISINQCALENDAR, taxisinqcalendar, INT)
 FCALLSCSUB2 (taxisDefTunit, TAXISDEFTUNIT, taxisdeftunit, INT, INT)
+FCALLSCFUN1 (INT, taxisInqTunit, TAXISINQTUNIT, taxisinqtunit, INT)
+FCALLSCSUB2 (taxisDefForecastTunit, TAXISDEFFORECASTTUNIT, taxisdefforecasttunit, INT, INT)
+FCALLSCFUN1 (INT, taxisInqForecastTunit, TAXISINQFORECASTTUNIT, taxisinqforecasttunit, INT)
+FCALLSCSUB2 (taxisDefForecastPeriod, TAXISDEFFORECASTPERIOD, taxisdefforecastperiod, INT, DOUBLE)
+FCALLSCFUN1 (DOUBLE, taxisInqForecastPeriod, TAXISINQFORECASTPERIOD, taxisinqforecastperiod, INT)
 FCALLSCSUB2 (taxisDefNumavg, TAXISDEFNUMAVG, taxisdefnumavg, INT, INT)
 FCALLSCFUN1 (INT, taxisInqType, TAXISINQTYPE, taxisinqtype, INT)
-FCALLSCFUN1 (INT, taxisInqVdate, TAXISINQVDATE, taxisinqvdate, INT)
-FCALLSCFUN1 (INT, taxisInqVtime, TAXISINQVTIME, taxisinqvtime, INT)
-FCALLSCFUN1 (INT, taxisInqRdate, TAXISINQRDATE, taxisinqrdate, INT)
-FCALLSCFUN1 (INT, taxisInqRtime, TAXISINQRTIME, taxisinqrtime, INT)
-FCALLSCFUN1 (INT, taxisInqFdate, TAXISINQFDATE, taxisinqfdate, INT)
-FCALLSCFUN1 (INT, taxisInqFtime, TAXISINQFTIME, taxisinqftime, INT)
-FCALLSCFUN1 (INT, taxisInqCalendar, TAXISINQCALENDAR, taxisinqcalendar, INT)
-FCALLSCFUN1 (INT, taxisInqTunit, TAXISINQTUNIT, taxisinqtunit, INT)
 FCALLSCFUN1 (INT, taxisInqNumavg, TAXISINQNUMAVG, taxisinqnumavg, INT)
 FCALLSCFUN1 (STRING, tunitNamePtr, TUNITNAMEPTR, tunitnameptr, INT)
 
@@ -64588,5 +67450,6 @@ FCALLSCFUN2 (STRING, tableInqParUnitsPtr, TABLEINQPARUNITSPTR, tableinqparunitsp
 FCALLSCSUB3 (streamDefHistory, STREAMDEFHISTORY, streamdefhistory, INT, INT, STRING)
 FCALLSCFUN1 (INT, streamInqHistorySize, STREAMINQHISTORYSIZE, streaminqhistorysize, INT)
 FCALLSCSUB2 (streamInqHistoryString, STREAMINQHISTORYSTRING, streaminqhistorystring, INT, PSTRING)
+FCALLSCSUB3 (gribapiLibraryVersion, GRIBAPILIBRARYVERSION, gribapilibraryversion, PINT, PINT, PINT)
 
 #endif
diff --git a/libcdi/src/cgribex.h b/libcdi/src/cgribex.h
index 145b92a..43385aa 100644
--- a/libcdi/src/cgribex.h
+++ b/libcdi/src/cgribex.h
@@ -57,13 +57,14 @@
 /*
  *  Macros for the product definition section ( Section 1 )
  */
-#define  ISEC1_TABLE4_MINUTE    0
-#define  ISEC1_TABLE4_HOUR      1
-#define  ISEC1_TABLE4_DAY       2
-#define  ISEC1_TABLE4_3HOURS   10
-#define  ISEC1_TABLE4_6HOURS   11
-#define  ISEC1_TABLE4_12HOURS  12
-#define  ISEC1_TABLE4_QUARTER  13
+#define  ISEC1_TABLE4_MINUTE      0
+#define  ISEC1_TABLE4_HOUR        1
+#define  ISEC1_TABLE4_DAY         2
+#define  ISEC1_TABLE4_3HOURS     10
+#define  ISEC1_TABLE4_6HOURS     11
+#define  ISEC1_TABLE4_12HOURS    12
+#define  ISEC1_TABLE4_QUARTER    13
+#define  ISEC1_TABLE4_30MINUTES  14
 
 
 #define  ISEC1_CodeTable            (isec1[ 0])  /*  Version number of code table                 */
@@ -222,12 +223,6 @@ void  gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffe
 void  gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer);
 void  gribRepair1(int nrec, long recsize, unsigned char *gribbuffer);
 
-int grib1Sections(unsigned char *gribbuffer, long recsize, unsigned char **pdsp,
-		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp);
-int grib2Sections(unsigned char *gribbuffer, long recsize, unsigned char **idsp,
-		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
-		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
-
 int   gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize);
 
 int   gribBzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize);
@@ -246,7 +241,7 @@ int   gribFileSeek(int fileID, long *offset);
 int   gribReadSize(int fileID);
 int   gribVersion(unsigned char *buffer, size_t buffersize);
 
-int   gribGinfo(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
+int   grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
 
 double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation);
 
diff --git a/libcdi/src/cgribexlib.c b/libcdi/src/cgribexlib.c
index 6e968f8..629b130 100644
--- a/libcdi/src/cgribexlib.c
+++ b/libcdi/src/cgribexlib.c
@@ -1,7 +1,17 @@
 
-/* Automatically generated by m214003 at 2014-06-27, do not edit */
+/* Automatically generated by m214003 at 2014-09-30, do not edit */
 
-/* CGRIBEXLIB_VERSION="1.6.4" */
+/* CGRIBEXLIB_VERSION="1.7.0" */
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic warning "-Wstrict-overflow"
+#endif
 
 #ifdef _ARCH_PWR6
 #pragma options nostrict
@@ -24,6 +34,13 @@
 #include "calendar.h"
 #include "timebase.h"
 
+#ifndef _TEMPLATES_H
+#define _TEMPLATES_H
+
+#define CAT(X,Y)      X##_##Y
+#define TEMPLATE(X,Y) CAT(X,Y)
+
+#endif 
 #ifndef _GRIB_INT_H
 #define _GRIB_INT_H
 
@@ -108,6 +125,8 @@
 #  define IS_EQUAL(x,y)     (!IS_NOT_EQUAL(x,y))
 #endif
 
+/* dummy use of unused parameters to silence compiler warnings */
+#define  UNUSED(x) (void)x
 
 #define  JP23SET    0x7FFFFF  /* 2**23 - 1 (---> 8388607)  */
 
@@ -156,19 +175,20 @@ void   confp3(double pval, int *kexp, int *kmant, int kbits, int kround);
 double decfp2(int kexp, int kmant);
 void   ref2ibm(double *pref, int kbits);
 
-void   scaleComplex(double *fpdata, int pcStart, int pcScale, int trunc, int inv);
-void   scatterComplex(double *fpdata, int pcStart, int trunc, int nsp);
-void   gatherComplex(double *fpdata, int pcStart, int trunc, int nsp);
+void   scale_complex_double(double *fpdata, int pcStart, int pcScale, int trunc, int inv);
+void   scale_complex_float(float *fpdata, int pcStart, int pcScale, int trunc, int inv);
+void   scatter_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
+void   scatter_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
+void   gather_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
+void   gather_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
 
-void   scm0(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
-int    rowina2(double *p, int ko, int ki, double *pw,
-	       int kcode, double msval, int *kret);
-int    rowina3(double *p, int ko, int ki, double *pw,
-	       int kcode, double msval, int *kret, int omisng, int operio, int oveggy);
+void   scm0_double(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
 int    qu2reg2(double *pfield, int *kpoint, int klat, int klon,
 	       double *ztemp, double msval, int *kret);
-int    qu2reg3(double *pfield, int *kpoint, int klat, int klon,
-	       double msval, int *kret, int omisng, int operio, int oveggy);
+int    qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
+		      double msval, int *kret, int omisng, int operio, int oveggy);
+int    qu2reg3_float(float *pfield, int *kpoint, int klat, int klon,
+		     float msval, int *kret, int omisng, int operio, int oveggy);
 
 #if  defined  (INT32)
 long   packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc);
@@ -179,13 +199,26 @@ long   unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc
 #endif
 long   unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc);
 
-void  gribEncode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		 int kleng, int *kword, int efunc, int *kret);
+void  grib_encode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
+			 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
+			 int kleng, int *kword, int efunc, int *kret);
+void  grib_encode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+			float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
+			int kleng, int *kword, int efunc, int *kret);
+
+void  grib_decode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
+			 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
+			 int kleng, int *kword, int dfunc, int *kret);
+void  grib_decode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+			float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
+			int kleng, int *kword, int dfunc, int *kret);
 
-void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		 int kleng, int *kword, int dfunc, int *kret);
+
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
+		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize);
+int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
+		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
+		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
 
 #endif  /* _GRIB_INT_H */
 #ifndef _GRIBDECODE_H
@@ -329,8 +362,8 @@ void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
 #define  GRIB2_SECNUM(section)   (GET_UINT1(section[4]))
 
 #endif  /* _GRIBDECODE_H */
-#ifndef _GRIBENCODE_H
-#define _GRIBENCODE_H
+#ifndef _GRIB_ENCODE_H
+#define _GRIB_ENCODE_H
 
 
 #define PutnZero(n) \
@@ -362,7 +395,7 @@ void  gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
   Put3Byte(mantissa);            \
 }
 
-#endif  /* _GRIBENCODE_H */
+#endif  /* _GRIB_ENCODE_H */
 #include <stdio.h>
 #include <math.h>
 
@@ -636,14 +669,14 @@ double intpow2(int x)
 }
 /* 
 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
- result on bailung (gcc 4.7):
-  orig    : fmin: -500000  fmax: 499999  time:   4.84s
-  sse2    : fmin: -500000  fmax: 499999  time:   4.82s
+ result on bailung (gcc 4.8.2):
+  orig    : fmin: -500000  fmax: 499999  time:   4.82s
+  sse2    : fmin: -500000  fmax: 499999  time:   4.83s
 
 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD minmax_val.c
- result on thunder5 (gcc 4.7.2):
+ result on thunder5 (gcc 4.8.2):
   orig    : fmin: -500000  fmax: 499999  time:   3.10s
-  simd    : fmin: -500000  fmax: 499999  time:   3.23s # omp simd in gcc 4.9
+  simd    : fmin: -500000  fmax: 499999  time:   3.10s # omp simd in gcc 4.9
   avx     : fmin: -500000  fmax: 499999  time:   2.84s
 
 icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
@@ -725,7 +758,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax
 #if defined(_ENABLE_AVX)
 
 static
-void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, double *max)
+void avx_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
 {
   double fmin[4], fmax[4];
   __m256d current_max, current_min, work;
@@ -747,7 +780,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
 
   while (nframes >= 16) {
 
-    (void) _mm_prefetch(buf+8, _MM_HINT_NTA);
+    (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
 
     work = _mm256_load_pd(buf);
     current_min = _mm256_min_pd(current_min, work);
@@ -759,7 +792,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
     current_max = _mm256_max_pd(current_max, work);
     buf += 4;
 
-    (void) _mm_prefetch(buf+8, _MM_HINT_NTA);
+    (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
 
     work = _mm256_load_pd(buf);
     current_min = _mm256_min_pd(current_min, work);
@@ -819,7 +852,7 @@ void avx_minmax_val(const double *restrict buf, size_t nframes, double *min, dou
 #elif defined(_ENABLE_SSE2)
 
 static
-void sse2_minmax_val(const double *restrict buf, size_t nframes, double *min, double *max)
+void sse2_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
 {
   __m128d current_max, current_min, work;
   
@@ -897,7 +930,7 @@ void sse2_minmax_val(const double *restrict buf, size_t nframes, double *min, do
 
 #if defined(_ARCH_PWR6)
 static
-void pwr6_minmax_val_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
 #define __UNROLL_DEPTH_1 6
   size_t datasize = idatasize;
@@ -944,7 +977,7 @@ void pwr6_minmax_val_unrolled6(const double *restrict data, long idatasize, doub
 
 #if defined(TEST_MINMAXVAL) && defined(__GNUC__)
 static
-void minmax_val_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
 #endif
 
 #if defined(GNUC_PUSH_POP)
@@ -952,7 +985,7 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma GCC optimize ("O3", "fast-math")
 #endif
 static
-void minmax_val_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
   size_t i;
   size_t datasize = idatasize;
@@ -964,13 +997,39 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma vdir nodep
 #elif defined(__uxp__)
 #pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; ++i )
+    {
+      dmin = dmin < data[i] ? dmin : data[i];
+      dmax = dmax > data[i] ? dmax : data[i];
+    }
+
+  *fmin = dmin;
+  *fmax = dmax;
+}
+
+static
+void minmax_val_float(const float *restrict data, long idatasize, float *fmin, float *fmax)
+{
+  size_t i;
+  size_t datasize = idatasize;
+  float dmin = *fmin, dmax = *fmax;
+
+#if   defined(CRAY)
+#pragma _CRI ivdep
+#elif defined(SX)
+#pragma vdir nodep
+#elif defined(__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
 #endif
   for ( i = 0; i < datasize; ++i )
     {
       dmin = dmin < data[i] ? dmin : data[i];
       dmax = dmax > data[i] ? dmax : data[i];
-      //      if ( dmin > data[i] ) dmin = data[i];
-      //      if ( dmax < data[i] ) dmax = data[i];
     }
 
   *fmin = dmin;
@@ -993,7 +1052,7 @@ void minmax_val_orig(const double *restrict data, long idatasize, double *fmin,
 #pragma GCC optimize ("O3", "fast-math")
 #endif
 static
-void minmax_val_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
   size_t i;
   size_t datasize = idatasize;
@@ -1018,7 +1077,7 @@ void minmax_val_simd(const double *restrict data, long idatasize, double *fmin,
 #endif
 
 static
-void minmax_val(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double(const double *restrict data, long idatasize, double *fmin, double *fmax)
 {
 #if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER) 
   uint64_t start_minmax, end_minmax;
@@ -1036,11 +1095,11 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
 
 #if defined(_ENABLE_AVX)
 
-  avx_minmax_val(data, datasize, fmin, fmax);
+  avx_minmax_val_double(data, datasize, fmin, fmax);
 
 #elif defined(_ENABLE_SSE2)
 
-  sse2_minmax_val(data, datasize, fmin, fmax);
+  sse2_minmax_val_double(data, datasize, fmin, fmax);
 
 #else
 
@@ -1053,7 +1112,7 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
   hpmStart(1, "minmax fsel");
 #endif
 
-  pwr6_minmax_val_unrolled6(data, datasize, fmin, fmax);
+  pwr6_minmax_val_double_unrolled6(data, datasize, fmin, fmax);
 
 #if defined(_GET_IBM_COUNTER) 
   hpmStop(1);
@@ -1067,7 +1126,7 @@ void minmax_val(const double *restrict data, long idatasize, double *fmin, doubl
   hpmStart(1, "minmax base");
 #endif
 
-  minmax_val_orig(data, datasize, fmin, fmax);
+  minmax_val_double_orig(data, datasize, fmin, fmax);
 
 #if defined(_GET_IBM_COUNTER) 
   hpmStop(1);
@@ -1118,8 +1177,6 @@ double dtime()
 int main(void)
 {
   long datasize = 1000000;
-  double *data = NULL;
-  double fmin, fmax;
   double t_begin, t_end;
 
 #if   defined(_OPENMP)
@@ -1134,71 +1191,96 @@ int main(void)
   printf("gcc\n");
 #endif
 
-  data = (double*) malloc(datasize*sizeof(double));
+  {
+    float fmin, fmax;
+    float *data_sp = (float*) malloc(datasize*sizeof(float));
 
-  // for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
-  for ( long i = 0; i < datasize/2; i++ )        data[i] = (double) (i);
-  for ( long i = datasize/2; i < datasize; i++ ) data[i] = (double) (-datasize + i);
-  // for ( long i = 0; i < datasize; i++ )    printf("%d %g\n", i, data[i]);
+    for ( long i = 0; i < datasize/2; i++ )        data_sp[i] = (float) (i);
+    for ( long i = datasize/2; i < datasize; i++ ) data_sp[i] = (float) (-datasize + i);
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    printf("float:\n");
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val_orig(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("orig      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_sp[0];
+	minmax_val_float(data_sp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    free(data_sp);
+  }
+
+  {
+    double fmin, fmax;
+    double *data_dp = (double*) malloc(datasize*sizeof(double));
+
+    // for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
+    for ( long i = 0; i < datasize/2; i++ )        data_dp[i] = (double) (i);
+    for ( long i = datasize/2; i < datasize; i++ ) data_dp[i] = (double) (-datasize + i);
+
+    printf("double:\n");
+
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("minmax_val: fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double_orig(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("orig      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 
 #if defined(OMP_SIMD)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      minmax_val_simd(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("simd      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	minmax_val_double_simd(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("simd      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
 
 #if defined(_ENABLE_AVX)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      avx_minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("avx       : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	avx_minmax_double_val(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("avx       : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #elif defined(_ENABLE_SSE2)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      sse2_minmax_val(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("sse2      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	sse2_minmax_val_double(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("sse2      : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
 #if defined(_ARCH_PWR6)
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      fmin = fmax = data[0];
-      pwr6_minmax_val_unrolled6(data, datasize, &fmin, &fmax);
-    }
-  t_end = dtime();
-  printf("pwr6u6  : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
+    t_begin = dtime();
+    for ( int i = 0; i < NRUN; ++i )
+      {
+	fmin = fmax = data_dp[0];
+	pwr6_minmax_val_double_unrolled6(data_dp, datasize, &fmin, &fmax);
+      }
+    t_end = dtime();
+    printf("pwr6u6  : fmin: %ld  fmax: %ld  time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
 #endif
+    free(data_dp);
+  }
 
   return (0);
 }
@@ -1209,22 +1291,27 @@ int main(void)
 #undef _ENABLE_SSE2
 #undef GNUC_PUSH_POP
 /* 
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL encode_double_array.c
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama (gcc 4.8.2):
+  orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 16.0471s
+  sse41   : val1: 1  val2: 1  val3: 2  valn: 66  time: 15.4391s
+
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
  result on bailung (gcc 4.7):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 8.4166s
   sse41   : val1: 1  val2: 1  val3: 2  valn: 66  time: 7.1522s
 
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL encode_double_array.c
+gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
  result on thunder5 (gcc 4.7):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 6.21976s
   avx     : val1: 1  val2: 1  val3: 2  valn: 66  time: 4.54485s
 
-icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_MINMAXVAL encode_double_array.c
+icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_ENCODE encode_array.c
  result on thunder5 (icc 13.2):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 14.6279s
   avx     : val1: 1  val2: 1  val3: 2  valn: 66  time:  4.9776s
 
-xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode_double_array.c
+xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_array.c
  result on blizzard (xlc 12):
   orig    : val1: 1  val2: 1  val3: 2  valn: 66  time: 132.25s
   unrolled: val1: 1  val2: 1  val3: 2  valn: 66  time:  27.202s
@@ -1235,7 +1322,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode
 #pragma options nostrict
 #endif
 
-#ifdef TEST_MINMAXVAL
+#ifdef TEST_ENCODE
 #include <stdio.h>
 #include <stdlib.h>
 #define  GRIBPACK     unsigned char
@@ -1295,7 +1382,7 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL encode
 #if defined _ENABLE_AVX
 
 static
-void avx_encode_double_array_2byte(size_t datasize, 
+void avx_encode_array_2byte_double(size_t datasize, 
 				   unsigned char * restrict lGrib,
 				   const double * restrict data, 
 				   double zref, double factor, size_t *gz) 
@@ -1396,7 +1483,7 @@ void avx_encode_double_array_2byte(size_t datasize,
 #elif defined _ENABLE_SSE4_1
 
 static
-void sse41_encode_double_array_2byte(size_t datasize, 
+void sse41_encode_array_2byte_double(size_t datasize, 
 				     unsigned char * restrict lGrib,
 				     const double * restrict data, 
 				     double zref, double factor, size_t *gz) 
@@ -1524,1062 +1611,664 @@ void sse41_encode_double_array_2byte(size_t datasize,
 
 #endif // SIMD variants
 
-static
-void encode_double_array_common(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
-				const double *data, double zref, double factor, size_t *gz)
-{
-  size_t i, z = *gz;
-  unsigned int ival;
-  int cbits, jbits;
-  unsigned int c;
-  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-    
-  /* code from gribw routine flist2bitstream */
 
-  cbits = 8;
-  c = 0;
-  for ( i = packStart; i < datasize; i++ )
-    {
-      /* note float -> unsigned int .. truncate */
-      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
-      /*
-	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
-	if ( ival < 0 ) ival = 0;
-      */
-      jbits = numBits;
-      while ( cbits <= jbits ) 
-	{
-	  if ( cbits == 8 )
-	    {
-	      jbits -= 8;
-	      lGrib[z++] = (ival >> jbits) & 0xFF;
-	    }
-	  else
-	    {
-	      jbits -= cbits;
-	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
-	      cbits = 8;
-	      c = 0;
-	    }
-	}
-      /* now jbits < cbits */
-      if ( jbits )
-	{
-	  c = (c << jbits) + (ival & mask[jbits]);
-	  cbits -= jbits;
-	}
-    }
-  if ( cbits != 8 ) lGrib[z++] = c << cbits;
+#ifdef TEST_ENCODE
 
-  *gz = z;
-}
+#define CAT(X,Y)      X##_##Y
+#define TEMPLATE(X,Y) CAT(X,Y)
 
-static
-void encode_double_array_2byte(size_t datasize, GRIBPACK *restrict lGrib,
-			       const double *restrict data, double zref, double factor, size_t *gz)
-{
-  size_t i, z = *gz;
-  uint16_t ui16;
-  double tmp;
+#ifdef T
+#undef T
+#endif
+#define T double
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
+#ifdef T
+#undef T
 #endif
-  for ( i = 0; i < datasize; i++ )
-    {
-      tmp = ((data[i] - zref) * factor + 0.5);
-      ui16 = (uint16_t) tmp;
-      lGrib[z  ] = ui16 >>  8;
-      lGrib[z+1] = ui16;
-      z += 2;
-    }
+#define T float
 
-  *gz = z;
+
+#include <sys/time.h>
+
+static
+double dtime()
+{
+  double tseconds = 0.0;
+  struct timeval mytime;
+  gettimeofday(&mytime, NULL);
+  tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
+  return (tseconds);
 }
 
+#define NRUN 10000
+
 static
-void encode_double_array_byte(int numBits, size_t packStart, size_t datasize, 
-			      GRIBPACK *restrict lGrib,
-			      const double *restrict data, 
-			      double zref, double factor, size_t *gz)
+void pout(char *name, int s, unsigned char *lgrib, long datasize, double tt)
 {
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
-  uint64_t start_minmax, end_minmax;
-#endif
+  printf("%8s: val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", name, (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], tt);
+}
 
-  uint32_t ui32;
-  size_t i, z = *gz;
-  double tmp;
+int main(void)
+{
+  long datasize = 1000000;
+  float *dataf = NULL;
+  double *data = NULL;
+  double t_begin, t_end;
+  unsigned char *lgrib;
 
-  data += packStart;
-  datasize -= packStart;
+  dataf = (float*) malloc(datasize*sizeof(float));
+  data  = (double*) malloc(datasize*sizeof(double));
+  lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
 
-  if      ( numBits ==  8 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(2, "pack 8 bit base");
-#endif
+  for ( long i = 0; i < datasize; ++i ) dataf[i] = (float) (-datasize/2 + i);
+  for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
 
-#if defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
-#endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-	  lGrib[z  ] = (uint16_t) tmp;
-          z++;
-	}
+  int PackStart = 0;
+  int nbpv = 16;
+  double zref = data[0];
+  size_t z;
+  double factor = 0.00390625;
+  int s = 256;
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(2);
-#endif
-    }
-  else if ( numBits == 16 )
+  if ( 0 )
     {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(3, "pack 16 bit base");
-#elif defined _GET_X86_COUNTER 
-  start_minmax = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-  start_minmax = mach_absolute_time();
-#endif
+      encode_array_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
+      encode_array_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
+    }
 
-#if defined _ENABLE_AVX
 
-      avx_encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+#if   defined(__ICC)
+  printf("icc\n");
+#elif defined(__clang__)
+  printf("clang\n");
+#elif defined(__GNUC__)
+  printf("gcc\n");
+#endif
 
-#elif defined _ENABLE_SSE4_1
+  printf("float:\n");
 
-      sse41_encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_2byte_float(datasize, lgrib, dataf, (float)zref, (float)factor, &z);
+    }
+  t_end = dtime();
+  pout("orig", s, lgrib, datasize, t_end-t_begin);
 
-#else
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_unrolled_float(nbpv, PackStart, datasize, lgrib, dataf, (float)zref, (float)factor, &z);
+    }
+  t_end = dtime();
+  pout("unrolled", s, lgrib, datasize, t_end-t_begin);
 
-      encode_double_array_2byte(datasize, lGrib, data, zref, factor, &z);
+  printf("double:\n");
 
-#endif
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("orig", s, lgrib, datasize, t_end-t_begin);
 
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER 
-      end_minmax = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      end_minmax = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
-      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
-#elif defined _ENABLE_SSE4_1
-      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
-#else
-      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
-#endif  
-#endif
-      
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(3);
-#endif
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      encode_array_unrolled_double(nbpv, PackStart, datasize, lgrib, data, zref, factor, &z);
     }
-  else if ( numBits == 24 )
+  t_end = dtime();
+  pout("unrolled", s, lgrib, datasize, t_end-t_begin);
+
+#if defined _ENABLE_AVX
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
     {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(4, "pack 24 bit base");
+      z = 0;
+      avx_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("avx", s, lgrib, datasize, t_end-t_begin);
+#elif defined _ENABLE_SSE4_1
+  t_begin = dtime();
+  for ( int i = 0; i < NRUN; ++i )
+    {
+      z = 0;
+      sse41_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
+    }
+  t_end = dtime();
+  pout("sse41", s, lgrib, datasize, t_end-t_begin);
 #endif
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
+  return 0;
+}
+#endif // TEST_ENCODE
+
+#undef DISABLE_SIMD
+#undef _ENABLE_AVX
+#undef _ENABLE_SSE4_1
+//#undef _GET_X86_COUNTER
+//#undef _GET_MACH_COUNTER
+//#undef _GET_IBM_COUNTER
+//#undef _ARCH_PWR6
+
+#if defined _GET_IBM_COUNTER
+#include <libhpc.h>
+#elif defined _GET_X86_COUNTER
+#include <x86intrin.h>
+#elif defined _GET_MACH_COUNTER
+#include <mach/mach_time.h>
 #endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-          ui32 = (uint32_t) tmp;
-          lGrib[z  ] =  ui32 >> 16;
-          lGrib[z+1] =  ui32 >>  8;
-          lGrib[z+2] =  ui32;
-          z += 3;
-	}
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(4);
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#if   defined(__GNUC__) && (__GNUC__ >= 4)
+#elif defined(__ICC)    && (__ICC >= 1100)
+#elif defined(__clang__)
+#else
+#define DISABLE_SIMD
 #endif
-    }
-  else if ( numBits == 32 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(5, "pack 32 bit base");
+
+#define DISABLE_SIMD
+
+#ifdef DISABLE_SIMD
+# ifdef ENABLE_AVX
+#  define _ENABLE_AVX
+# endif
+# ifdef ENABLE_SSE4_1
+#  define _ENABLE_SSE4_1
+# endif
 #endif
 
-#if   defined (CRAY)
-#pragma _CRI ivdep
-#elif defined (SX)
-#pragma vdir nodep
-#elif defined (__uxp__)
-#pragma loop novrec
+#ifndef DISABLE_SIMD
+# ifdef __AVX__
+#  define _ENABLE_AVX
+# endif
+# ifdef __SSE4_1__
+#  define _ENABLE_SSE4_1
+# endif
 #endif
-      for ( i = 0; i < datasize; i++ )
-	{
-	  tmp = ((data[i] - zref) * factor + 0.5);
-          ui32 = (uint32_t) tmp;
-          lGrib[z  ] =  ui32 >> 24;
-          lGrib[z+1] =  ui32 >> 16;
-          lGrib[z+2] =  ui32 >>  8;
-          lGrib[z+3] =  ui32;
-          z += 4;
-	}
 
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(5);
+#if defined _ENABLE_AVX
+#include <immintrin.h>
+#elif defined _ENABLE_SSE4_1
+#include <smmintrin.h>
 #endif
-    }
-  else if ( numBits > 0 && numBits <= 32 )
+
+#if defined _ENABLE_AVX
+
+static
+void avx_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
+				     double * restrict fpdata, double fmin, double zscale)
+{
+  size_t i, j;
+  size_t nframes = datasize;
+  size_t residual;
+  size_t ofs;
+
+  double dval;
+
+  double *data = fpdata;
+  __m128i *sgrib;
+  
+  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
+
+  __m256d ymm0 = _mm256_set1_pd(fmin);
+  __m256d ymm1 = _mm256_set1_pd(zscale);
+  
+  __m128i xmm0, xmm1, xmm2, xmm3;
+  __m256d ymm2, ymm3;
+
+  i = -1;
+  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
     {
-      encode_double_array_common(numBits, 0, datasize, lGrib, 
-				 data, zref, factor, &z);
+      i++;
+      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
+      fpdata[i] = fmin + zscale * dval;
+      data++;
+      nframes--;
     }
-  else if ( numBits == 0 )
-    {
+  
+  if (i == -1) i = 0;
+  sgrib = (__m128i *) (igrib+i);
+
+  while (nframes >= 16)
+    { 
+      xmm0 = _mm_loadu_si128((__m128i *) sgrib);
+      xmm0 = _mm_shuffle_epi8(xmm0, mask);
+      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
+      xmm2 = _mm_cvtepu16_epi32(xmm0);
+      xmm3 = _mm_cvtepu16_epi32(xmm1);
+
+      ymm2 = _mm256_cvtepi32_pd(xmm2);
+      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
+      (void) _mm256_stream_pd(data, ymm2);
+      ymm3 = _mm256_cvtepi32_pd(xmm3);
+      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+4, ymm3);  
+      
+      xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
+      xmm0 = _mm_shuffle_epi8(xmm0, mask);
+      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
+      xmm2 = _mm_cvtepu16_epi32(xmm0);
+      xmm3 = _mm_cvtepu16_epi32(xmm1);
+      
+      ymm2 = _mm256_cvtepi32_pd(xmm2);
+      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+8, ymm2);
+      ymm3 = _mm256_cvtepi32_pd(xmm3);
+      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
+      (void) _mm256_stream_pd(data+12, ymm3);  
+      
+      data += 16;
+      sgrib += 2;
+      nframes -= 16;
     }
-  else
+
+  residual = nframes;
+  ofs = datasize - residual;
+  for ( j = 0; j < residual; j++ )
     {
-      Error("Unimplemented packing factor %d!", numBits);
+      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
+      fpdata[ofs+j] = fmin + zscale * dval;
     }
 
-  *gz = z;
+  return;
 }
 
+#elif defined _ENABLE_SSE4_1
+
 static
-void encode_double_array_unrolled(int numBits, size_t packStart, size_t datasize, 
-				  GRIBPACK *restrict lGrib,
-				  const double *restrict data, 
-				  double zref, double factor, size_t *gz)
+void sse41_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
+				     double * restrict fpdata, double fmin, double zscale)
 {
-  U_BYTEORDER;
-  size_t i, j, z = *gz;
-#ifdef _ARCH_PWR6
-#define __UNROLL_DEPTH_2 8
-#else
-#define __UNROLL_DEPTH_2 8
-#endif
+  size_t i, j;
+  size_t nframes = datasize;
   size_t residual;
   size_t ofs;
-  double dval[__UNROLL_DEPTH_2];
-  unsigned long ival;
 
-  data += packStart;
-  datasize -= packStart;
-  residual =  datasize % __UNROLL_DEPTH_2;
-  ofs = datasize - residual;
+  double dval;
 
-  // reducing FP operations to single FMA is slowing down on pwr6 ...
+  double *data = fpdata;
+  __m128i *sgrib;
+  
+  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
+  __m128d dmm8 = _mm_set1_pd(fmin);
+  __m128d dmm9 = _mm_set1_pd(zscale);
+  
+  __m128i xmm4, xmm5;
+  __m128i xmm6, xmm7;
+  
+  __m128d dmm0, dmm1, dmm2, dmm3;
+  __m128d dmm4, dmm5, dmm6, dmm7;
 
-  if      ( numBits ==  8 )
+  i = -1;
+  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
     {
-      unsigned char *cgrib = (unsigned char *) (lGrib + z);
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(2, "pack 8 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      *cgrib++ =  (unsigned long) dval[j];
-	    }
-	  z += __UNROLL_DEPTH_2;
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  *cgrib++ = (unsigned long) dval[j];
-	}
-      z += residual;
-
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(2);
-#endif
-    }
-  else if ( numBits == 16 )
-    {
-      unsigned short *sgrib = (unsigned short *) (lGrib + z);
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(3, "pack 16 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  if ( IS_BIGENDIAN() )
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  *sgrib++ = (unsigned long) dval[j];
-		}
-	      z += 2*__UNROLL_DEPTH_2;
-	    }
-	  else
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  ival = (unsigned long) dval[j];
-		  lGrib[z  ] = ival >>  8;
-		  lGrib[z+1] = ival;
-		  z += 2;
-		}
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      if ( IS_BIGENDIAN() )
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      *sgrib++ = (unsigned long) dval[j];
-	    }
-	  z += 2*residual;
-	}
-      else
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] = ival >>  8;
-	      lGrib[z+1] = ival;
-	      z += 2;
-	    }
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(3);
-#endif
-    }
-  else if ( numBits == 24 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(4, "pack 24 bit unrolled");
-#endif
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] =  ival >> 16;
-	      lGrib[z+1] =  ival >>  8;
-	      lGrib[z+2] =  ival;
-	      z += 3;
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  ival = (unsigned long) dval[j];
-	  lGrib[z  ] =  ival >> 16;
-	  lGrib[z+1] =  ival >>  8;
-	  lGrib[z+2] =  ival;
-	  z += 3;
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(4);
-#endif
-    }
-  else if ( numBits == 32 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(5, "pack 32 bit unrolled");
-#endif
-      unsigned int *igrib = (unsigned int *) (lGrib + z);
-      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
-	{
-	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-	    {
-	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
-	    }
-	  if ( IS_BIGENDIAN() )
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  *igrib = (unsigned long) dval[j];
-		  igrib++;
-		  z += 4;
-		}
-	    }
-	  else
-	    {
-	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
-		{
-		  ival = (unsigned long) dval[j];
-		  lGrib[z  ] =  ival >> 24;
-		  lGrib[z+1] =  ival >> 16;
-		  lGrib[z+2] =  ival >>  8;
-		  lGrib[z+3] =  ival;
-		  z += 4;
-		}
-	    }
-	}
-      for (j = 0; j < residual; j++) 
-	{
-	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
-	}
-      if ( IS_BIGENDIAN() )
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      *igrib = (unsigned long) dval[j];
-	      igrib++;
-	      z += 4;
-	    }
-	}
-      else
-	{
-	  for (j = 0; j < residual; j++) 
-	    {
-	      ival = (unsigned long) dval[j];
-	      lGrib[z  ] =  ival >> 24;
-	      lGrib[z+1] =  ival >> 16;
-	      lGrib[z+2] =  ival >>  8;
-	      lGrib[z+3] =  ival;
-	      z += 4;
-	    }
-	}
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(5);
-#endif
-    }
-  else if ( numBits > 0 && numBits <= 32 )
-    {
-      encode_double_array_common(numBits, 0, datasize, lGrib, data, zref, factor, &z);
+      i++;
+      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
+      fpdata[i] = fmin + zscale * dval;
+      data++;
+      nframes--;
     }
-  else if ( numBits == 0 )
+  
+  if (i == -1) i = 0;
+  sgrib = (__m128i *) (igrib+i);
+  
+  while (nframes >= 16)
     {
+      xmm5 = _mm_loadu_si128((__m128i *) sgrib);
+      xmm5 = _mm_shuffle_epi8(xmm5, mask);
+      xmm4 = _mm_srli_si128(xmm5, 8);
+      xmm6 = _mm_cvtepu16_epi32(xmm5);
+      dmm0 = _mm_cvtepi32_pd(xmm6);
+      dmm0 = _mm_add_pd(_mm_mul_pd(dmm0, dmm9), dmm8);
+      (void) _mm_stream_pd(data, dmm0);
+      xmm7 = _mm_srli_si128(xmm6, 8);
+      dmm1 = _mm_cvtepi32_pd(xmm7);
+      dmm1 = _mm_add_pd(_mm_mul_pd(dmm1, dmm9), dmm8);
+      (void) _mm_stream_pd(data+2, dmm1);
+      xmm6 = _mm_cvtepu16_epi32(xmm4);
+      dmm2 = _mm_cvtepi32_pd(xmm6);
+      dmm2 = _mm_add_pd(_mm_mul_pd(dmm2, dmm9), dmm8);
+      (void) _mm_stream_pd(data+4, dmm2);
+      xmm7 = _mm_srli_si128(xmm6, 8);
+      dmm3 = _mm_cvtepi32_pd(xmm7);
+      dmm3 = _mm_add_pd(_mm_mul_pd(dmm3, dmm9), dmm8);
+      (void) _mm_stream_pd(data+6, dmm3);
+      
+      xmm5 = _mm_loadu_si128((__m128i *) sgrib+1);
+      xmm5 = _mm_shuffle_epi8(xmm5, mask);
+      xmm4 = _mm_srli_si128(xmm5, 8);
+      xmm6 = _mm_cvtepu16_epi32(xmm5);
+      dmm4 = _mm_cvtepi32_pd(xmm6);
+      dmm4 = _mm_add_pd(_mm_mul_pd(dmm4, dmm9), dmm8);
+      (void) _mm_stream_pd(data+8, dmm4);
+      xmm7 = _mm_srli_si128(xmm6, 8);
+      dmm5 = _mm_cvtepi32_pd(xmm7);
+      dmm5 = _mm_add_pd(_mm_mul_pd(dmm5, dmm9), dmm8);
+      (void) _mm_stream_pd(data+10, dmm5);
+      xmm6 = _mm_cvtepu16_epi32(xmm4);
+      dmm6 = _mm_cvtepi32_pd(xmm6);
+      dmm6 = _mm_add_pd(_mm_mul_pd(dmm6, dmm9), dmm8);
+      (void) _mm_stream_pd(data+12, dmm6);
+      xmm7 = _mm_srli_si128(xmm6, 8);
+      dmm7 = _mm_cvtepi32_pd(xmm7);
+      dmm7 = _mm_add_pd(_mm_mul_pd(dmm7, dmm9), dmm8);
+      (void) _mm_stream_pd(data+14, dmm7);
+
+      data += 16;
+      sgrib += 2;
+      nframes -= 16;
     }
-  else
+
+  residual = nframes;
+  ofs = datasize - residual;
+  for ( j = 0; j < residual; j++ )
     {
-      Error("Unimplemented packing factor %d!", numBits);
+      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
+      fpdata[ofs+j] = fmin + zscale * dval;
     }
 
-  *gz = z;
-#undef __UNROLL_DEPTH_2
+  return;
 }
 
-#ifdef TEST_MINMAXVAL
-
-#include <sys/time.h>
+#endif
 
-static
-double dtime()
-{
-  double tseconds = 0.0;
-  struct timeval mytime;
-  gettimeofday(&mytime, NULL);
-  tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
-  return (tseconds);
-}
+#undef DISABLE_SIMD
+#undef _ENABLE_AVX
+#undef _ENABLE_SSE4_1
 
-#define NRUN 10000
 
-int main(void)
+void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
 {
-  long datasize = 1000000;
-  double *data = NULL;
-  double t_begin, t_end;
-  unsigned char *lgrib;
+  /*
 
-  data  = (double*) malloc(datasize*sizeof(double));
-  lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
+    Purpose:
+    --------
 
-  for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
+    Convert floating point number from machine
+    representation to GRIB representation.
 
-  int PackStart = 0;
-  int nbpv = 16;
-  double zref = data[0];
-  size_t z;
-  double factor = 0.00390625;
-  int s = 256;
+    Input Parameters:
+    -----------------
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("orig    : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
+       pval    - Floating point number to be converted.
+       kbits   - Number of bits in computer word.
+       kround  - Conversion type.
+                 0 , Closest number in GRIB format less than
+                     original number.
+                 1 , Closest number in GRIB format to the
+                     original number (equal to, greater than or
+                     less than original number).
 
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      encode_double_array_unrolled (nbpv, PackStart, datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("unrolled: val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
+    Output Parameters:
+    ------------------
 
-#if defined _ENABLE_AVX
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      avx_encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("avx     : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-#elif defined _ENABLE_SSE4_1
-  t_begin = dtime();
-  for ( int i = 0; i < NRUN; ++i )
-    {
-      z = 0;
-      sse41_encode_double_array_2byte   (datasize, lgrib, data, zref, factor, &z);
-    }
-  t_end = dtime();
-  printf("sse41   : val1: %d  val2: %d  val3: %d  valn: %d  time: %gs\n", (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], t_end-t_begin);
-#endif
+       kexp    - 8 Bit signed exponent.
+       kmant   - 24 Bit mantissa.
 
-  return 0;
-}
-#endif // TEST_MINMAXVAL
+    Method:
+    -------
 
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
-//#undef _GET_X86_COUNTER
-//#undef _GET_MACH_COUNTER
-//#undef _GET_IBM_COUNTER
-//#undef _ARCH_PWR6
+    Floating point number represented as 8 bit signed
+    exponent and 24 bit mantissa in integer values.
 
-#if defined _GET_IBM_COUNTER
-#include <libhpc.h>
-#elif defined _GET_X86_COUNTER
-#include <x86intrin.h>
-#elif defined _GET_MACH_COUNTER
-#include <mach/mach_time.h>
-#endif
+    Externals.
+    ----------
 
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
+    decfp2    - Decode from IBM floating point format.
 
-#if   defined(__GNUC__) && (__GNUC__ >= 4)
-#elif defined(__ICC)    && (__ICC >= 1100)
-#elif defined(__clang__)
-#else
-#define DISABLE_SIMD
-#endif
+    Reference:
+    ----------
 
-#define DISABLE_SIMD
+    WMO Manual on Codes re GRIB representation.
 
-#ifdef DISABLE_SIMD
-# ifdef ENABLE_AVX
-#  define _ENABLE_AVX
-# endif
-# ifdef ENABLE_SSE4_1
-#  define _ENABLE_SSE4_1
-# endif
-#endif
+    Comments:
+    ---------
 
-#ifndef DISABLE_SIMD
-# ifdef __AVX__
-#  define _ENABLE_AVX
-# endif
-# ifdef __SSE4_1__
-#  define _ENABLE_SSE4_1
-# endif
-#endif
+    Routine aborts if an invalid conversion type parameter
+    is used or if a 24 bit mantissa is not produced.
 
-#if defined _ENABLE_AVX
-#include <immintrin.h>
-#elif defined _ENABLE_SSE4_1
-#include <smmintrin.h>
-#endif
+    Author:
+    -------
+     
+    John Hennessy   ECMWF   18.06.91
 
-#if defined _ENABLE_AVX
+    Modifications:
+    --------------
 
-static
-void avx_decode_double_array_2byte(size_t datasize, const unsigned char * restrict igrib,
-				     double * restrict fpdata, double fmin, double zscale)
-{
-  size_t i, j;
-  size_t nframes = datasize;
-  size_t residual;
-  size_t ofs;
+    Uwe Schulzweida   MPIfM   01/04/2001
 
-  double dval;
+    Convert to C from EMOS library version 130
 
-  double *data = fpdata;
-  __m128i *sgrib;
-  
-  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
+    Uwe Schulzweida   MPIfM   02/08/2002
 
-  __m256d ymm0 = _mm256_set1_pd(fmin);
-  __m256d ymm1 = _mm256_set1_pd(zscale);
-  
-  __m128i xmm0, xmm1, xmm2, xmm3;
-  __m256d ymm2, ymm3;
+     - speed up by factor 1.6 on NEC SX6
+        - replace 1.0 / pow(16.0, (double)(iexp - 70)) by rpow16m70tab[iexp]
+  */
 
-  i = -1;
-  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
+  double rpowref;
+  double zref, zeps;
+  int iexp, isign;
+  int iround;
+  // extern int CGRIBEX_Debug;
+  extern const double _pow16tab[71];
+
+  /* ----------------------------------------------------------------- */
+  /*   Section 1 . Initialise                                          */
+  /* ----------------------------------------------------------------- */
+
+  /*  Check conversion type parameter. */
+
+  iround = kround;
+  if ( iround != 0 && iround != 1 )
     {
-      i++;
-      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
-      fpdata[i] = fmin + zscale * dval;
-      data++;
-      nframes--;
+      Error("Invalid conversion type = %d", iround);
+
+      /*  If not aborting, arbitrarily set rounding to 'up'. */
+     iround = 1;
     }
-  
-  if (i == -1) i = 0;
-  sgrib = (__m128i *) (igrib+i);
 
-  while (nframes >= 16)
-    { 
-      xmm0 = _mm_loadu_si128((__m128i *) sgrib);
-      xmm0 = _mm_shuffle_epi8(xmm0, mask);
-      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
-      xmm2 = _mm_cvtepu16_epi32(xmm0);
-      xmm3 = _mm_cvtepu16_epi32(xmm1);
+  /* ----------------------------------------------------------------- */
+  /*   Section 2 . Convert value of zero.                              */
+  /* ----------------------------------------------------------------- */
 
-      ymm2 = _mm256_cvtepi32_pd(xmm2);
-      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
-      (void) _mm256_stream_pd(data, ymm2);
-      ymm3 = _mm256_cvtepi32_pd(xmm3);
-      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+4, ymm3);  
-      
-      xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
-      xmm0 = _mm_shuffle_epi8(xmm0, mask);
-      xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
-      xmm2 = _mm_cvtepu16_epi32(xmm0);
-      xmm3 = _mm_cvtepu16_epi32(xmm1);
-      
-      ymm2 = _mm256_cvtepi32_pd(xmm2);
-      ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+8, ymm2);
-      ymm3 = _mm256_cvtepi32_pd(xmm3);
-      ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
-      (void) _mm256_stream_pd(data+12, ymm3);  
-      
-      data += 16;
-      sgrib += 2;
-      nframes -= 16;
+  if ( ! (fabs(pval) > 0))
+    {
+      *kexp  = 0;
+      *kmant = 0;
+      iexp   = 0;
+      isign  = 0;
+      goto LABEL900;
     }
 
-  residual = nframes;
-  ofs = datasize - residual;
-  for ( j = 0; j < residual; j++ )
+  /* ----------------------------------------------------------------- */
+  /*   Section 3 . Convert other values.                               */
+  /* ----------------------------------------------------------------- */
+
+  zeps = 1.0e-12;
+  if ( kbits == 32 ) zeps = 1.0e-8;
+  zref = pval;
+
+  /*  Sign of value. */
+
+  isign = 0;
+  if ( zref < 0.0 )
     {
-      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
-      fpdata[ofs+j] = fmin + zscale * dval;
+      isign = 128;
+      zref  = - zref;
     }
 
-  return;
-}
+  /*  Exponent. */
 
-#elif defined _ENABLE_SSE4_1
+  iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
 
-static
-void sse41_decode_double_array_2byte(size_t datasize, const unsigned char * restrict igrib,
-				     double * restrict fpdata, double fmin, double zscale)
-{
-  size_t i, j;
-  size_t nframes = datasize;
-  size_t residual;
-  size_t ofs;
+  /* only ANSI C99 has log2 */
+  /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
 
-  double dval;
+  if ( iexp < 0   ) iexp = 0;
+  if ( iexp > 127 ) iexp = 127;
 
-  double *data = fpdata;
-  __m128i *sgrib;
-  
-  __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
-  __m128d dmm8 = _mm_set1_pd(fmin);
-  __m128d dmm9 = _mm_set1_pd(zscale);
-  
-  __m128i xmm4, xmm5;
-  __m128i xmm6, xmm7;
-  
-  __m128d dmm0, dmm1, dmm2, dmm3;
-  __m128d dmm4, dmm5, dmm6, dmm7;
+  /*
+  rpowref = zref / pow(16.0, (double)(iexp - 70));
+  */
 
-  i = -1;
-  while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
+  if ( (iexp - 70) < 0 )
+    rpowref = zref * _pow16tab[-(iexp - 70)];
+  else
+    rpowref = zref / _pow16tab[(iexp - 70)];
+
+  /*  Mantissa. */
+
+  if ( iround == 0 )
     {
-      i++;
-      dval = (((int)igrib[2*i] <<  8) | (int)igrib[2*i+1]);
-      fpdata[i] = fmin + zscale * dval;
-      data++;
-      nframes--;
+      /*  Closest number in GRIB format less than original number. */
+      /*  Truncate for positive numbers. */
+      /*  Round up for negative numbers. */
+
+      if ( isign == 0 )
+	*kmant = (int) rpowref;
+      else
+	*kmant = lround(rpowref + 0.5);
     }
-  
-  if (i == -1) i = 0;
-  sgrib = (__m128i *) (igrib+i);
-  
-  while (nframes >= 16)
+  else
     {
-      xmm5 = _mm_loadu_si128((__m128i *) sgrib);
-      xmm5 = _mm_shuffle_epi8(xmm5, mask);
-      xmm4 = _mm_srli_si128(xmm5, 8);
-      xmm6 = _mm_cvtepu16_epi32(xmm5);
-      dmm0 = _mm_cvtepi32_pd(xmm6);
-      dmm0 = _mm_add_pd(_mm_mul_pd(dmm0, dmm9), dmm8);
-      (void) _mm_stream_pd(data, dmm0);
-      xmm7 = _mm_srli_si128(xmm6, 8);
-      dmm1 = _mm_cvtepi32_pd(xmm7);
-      dmm1 = _mm_add_pd(_mm_mul_pd(dmm1, dmm9), dmm8);
-      (void) _mm_stream_pd(data+2, dmm1);
-      xmm6 = _mm_cvtepu16_epi32(xmm4);
-      dmm2 = _mm_cvtepi32_pd(xmm6);
-      dmm2 = _mm_add_pd(_mm_mul_pd(dmm2, dmm9), dmm8);
-      (void) _mm_stream_pd(data+4, dmm2);
-      xmm7 = _mm_srli_si128(xmm6, 8);
-      dmm3 = _mm_cvtepi32_pd(xmm7);
-      dmm3 = _mm_add_pd(_mm_mul_pd(dmm3, dmm9), dmm8);
-      (void) _mm_stream_pd(data+6, dmm3);
-      
-      xmm5 = _mm_loadu_si128((__m128i *) sgrib+1);
-      xmm5 = _mm_shuffle_epi8(xmm5, mask);
-      xmm4 = _mm_srli_si128(xmm5, 8);
-      xmm6 = _mm_cvtepu16_epi32(xmm5);
-      dmm4 = _mm_cvtepi32_pd(xmm6);
-      dmm4 = _mm_add_pd(_mm_mul_pd(dmm4, dmm9), dmm8);
-      (void) _mm_stream_pd(data+8, dmm4);
-      xmm7 = _mm_srli_si128(xmm6, 8);
-      dmm5 = _mm_cvtepi32_pd(xmm7);
-      dmm5 = _mm_add_pd(_mm_mul_pd(dmm5, dmm9), dmm8);
-      (void) _mm_stream_pd(data+10, dmm5);
-      xmm6 = _mm_cvtepu16_epi32(xmm4);
-      dmm6 = _mm_cvtepi32_pd(xmm6);
-      dmm6 = _mm_add_pd(_mm_mul_pd(dmm6, dmm9), dmm8);
-      (void) _mm_stream_pd(data+12, dmm6);
-      xmm7 = _mm_srli_si128(xmm6, 8);
-      dmm7 = _mm_cvtepi32_pd(xmm7);
-      dmm7 = _mm_add_pd(_mm_mul_pd(dmm7, dmm9), dmm8);
-      (void) _mm_stream_pd(data+14, dmm7);
+      /*  Closest number in GRIB format to the original number   */
+      /*  (equal to, greater than or less than original number). */
 
-      data += 16;
-      sgrib += 2;
-      nframes -= 16;
+      *kmant = lround(rpowref);
     }
 
-  residual = nframes;
-  ofs = datasize - residual;
-  for ( j = 0; j < residual; j++ )
+  /*  Check that mantissa value does not exceed 24 bits. */
+  /*  If it does, adjust the exponent upwards and recalculate */
+  /*  the mantissa. */
+  /*  16777215 = 2**24 - 1 */
+
+  if ( *kmant > 16777215 )
     {
-      dval = (((int)igrib[2*(ofs+j)] <<  8) | (int)igrib[2*(ofs+j)+1]);
-      fpdata[ofs+j] = fmin + zscale * dval;
-    }
 
-  return;
-}
+    LABEL350:
 
-#endif
+      ++iexp;
 
-static 
-void decode_double_array_common(const unsigned char * restrict igrib, long jlend, int NumBits, 
-				double fmin, double zscale, double * restrict fpdata)
-{
-  /* code from wgrib routine BDS_unpack */
-  const unsigned char *bits = igrib;
-  unsigned int jmask;
-  long i;
-  unsigned int tbits = 0;
-  int n_bits = NumBits;
-  int t_bits = 0;
-      
-  jmask = (1 << n_bits) - 1;
-  for ( i = 0; i < jlend; i++ )
-    {
-      if (n_bits - t_bits > 8)
-	{
-	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
-	  bits += 2;
-	  t_bits += 16;
-	}
+      /*  Check for exponent overflow during adjustment  */
 
-      while ( t_bits < n_bits )
+      if ( iexp > 127 )
 	{
-	  tbits = (tbits * 256) + *bits++;
-	  t_bits += 8;
-	}
-      t_bits -= n_bits;
-      fpdata[i] = (tbits >> t_bits) & jmask;
-    }
-  /* at least this vectorizes :) */
-  for ( i = 0; i < jlend; i++ )
-    fpdata[i] = fmin + zscale*fpdata[i];
-}
+          Message("Exponent overflow");
+          Message("Original number = %30.20f", pval);
+          Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
+		  isign, iexp, *kmant);
 
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+	  Error("Exponent overflow");
 
-static 
-void decode_double_array_common2(const unsigned char * restrict igrib, long jlend, int NumBits, 
-				 double fmin, double zscale, double * restrict fpdata)
-{
-  /* code from wgrib routine BDS_unpack */
-  const unsigned char *bits = igrib;
-  long i;
-  int n_bits = NumBits;
-  int c_bits, j_bits;
-  double jj;
+	  /*  If not aborting, arbitrarily set value to zero  */
 
-  /* older unoptimized code, not often used */
-  c_bits = 8;
-  for ( i = 0; i < jlend; i++ )
-    {
-      jj = 0.0;
-      j_bits = n_bits;
-      while (c_bits <= j_bits)
+          Message("Value arbitrarily set to zero.");
+          *kexp  = 0;
+          *kmant = 0;
+          iexp  = 0;
+          isign = 0;
+          goto LABEL900;
+	}
+
+      if ( (iexp - 70) < 0 )
+	rpowref = zref * _pow16tab[-(iexp - 70)];
+      else
+	rpowref = zref / _pow16tab[(iexp - 70)];
+
+      if ( iround == 0 )
 	{
-	  if (c_bits == 8)
-	    {
-	      jj = jj * 256.0  + (double) (*bits++);
-	      j_bits -= 8;
-	    }
+	  /*  Closest number in GRIB format less than original number. */
+	  /*  Truncate for positive numbers. */
+	  /*  Round up for negative numbers. */
+
+	  if ( isign == 0 )
+	    *kmant = (int) rpowref;
 	  else
-	    {
-	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
-	      bits++;
-	      j_bits -= c_bits;
-	      c_bits = 8;
-	    }
+	    *kmant = lround(rpowref + 0.5);
 	}
-
-      if (j_bits)
+      else
 	{
-	  c_bits -= j_bits;
-	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+	  /*  Closest number in GRIB format to the original number */
+	  /*  (equal to, greater or less than original number). */
+
+	  *kmant = lround(rpowref);
 	}
-      
-      fpdata[i] = fmin + zscale*jj;
+
+      /*  Repeat calculation (with modified exponent) if still have */
+      /*  mantissa overflow. */
+
+      if ( *kmant > 16777215 ) goto LABEL350;
     }
-} 
 
-static 
-void decode_double_array_byte(const unsigned char *restrict igrib, long jlend, int numBits, 
-			      double fmin, double zscale, double *restrict fpdata)
-{
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
-  uint64_t start_decode, end_decode;
-#endif
+  /*  Add sign bit to exponent. */
 
-  long i;
-  double dval;
-#if defined (VECTORCODE)
-  GRIBPACK *lgrib = NULL;
+  *kexp = iexp + isign;
 
-  if ( numBits%8 == 0 )
+  /* ----------------------------------------------------------------- */
+  /*   Section 9. Return                                               */
+  /* ----------------------------------------------------------------- */
+
+LABEL900:
+  /*
+  if ( CGRIBEX_Debug )
     {
-      long jlenc = jlend * numBits / 8;
-      if ( jlenc > 0 ) 
-	{
-	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
-	  if ( lgrib == NULL ) SysError("No Memory!");
+      double zval;
 
-	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
-	}
-    }
+      Message("Conversion type parameter = %4d", kround);
+      Message("Original number = %30.20f", pval);
 
-  if ( numBits ==  0 )
-    {
-      for ( i = 0; i < jlend; i++ )
-	fpdata[i] = fmin;
+      zval = decfp2(*kexp, *kmant);
+
+      Message("Converted to      %30.20f", zval);
+      Message("Sign = %3d, Exponent = %3d, Mantissa = %12d", isign, iexp, *kmant);
     }
-  else if ( numBits ==  8 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (int)lgrib[i];
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 16 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 24 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
-	  	 (int)lgrib[3*i+2]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 32 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
-		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits <= 25 )
-    {
-      decode_double_array_common(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else if ( numBits > 25 && numBits < 32 )
-    {
-      decode_double_array_common2(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else
-    {
-      Error("Unimplemented packing factor %d!", numBits);
-    }
-
-  if ( lgrib ) free(lgrib);
-
-#else
-  if ( numBits ==  0 )
-    {
-      for ( i = 0; i < jlend; i++ )
-	fpdata[i] = fmin;
-    }
-  else if ( numBits ==  8 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (int)igrib[i];
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 16 )
-    {
-#ifdef _GET_IBM_COUNTER 
-      hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER 
-      start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      start_decode = mach_absolute_time();
-#endif
-      
-#if defined _ENABLE_AVX
-      printf("AVX selected ...\n");
-      avx_decode_double_array_2byte((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
-      printf("SSE4 selected ...\n");
-      sse41_decode_double_array_2byte((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
-      for ( i = 0; i < jlend; i++ )
-	{
-	  dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
-	  fpdata[i] = fmin + zscale * dval;
-	}
-#endif
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER 
-      end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER 
-      end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
-      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
-      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
-      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif  
-#endif
-      
-#ifdef _GET_IBM_COUNTER 
-      hpmStop(6);
-#endif
-    }
-  else if ( numBits == 24 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
-		 (int)igrib[3*i+2]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits == 32 )
-    for ( i = 0; i < jlend; i++ )
-      {
-	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
-		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
-	fpdata[i] = fmin + zscale * dval;
-      }
-  else if ( numBits <= 25 )
-    {
-      decode_double_array_common(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else if ( numBits > 25 && numBits < 32 )
-    {
-      decode_double_array_common2(igrib, jlend, numBits, fmin, zscale, fpdata);
-    }
-  else
-    {
-      Error("Unimplemented packing factor %d!", numBits);
-    }
-#endif
-}
-
-static 
-void decode_double_array_unrolled(const unsigned char * restrict igrib, long jlend, int numBits, 
-				  double fmin, double zscale, double * restrict fpdata)
-{
-  decode_double_array_byte(igrib, jlend, numBits, fmin, zscale, fpdata);
-}
-
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
+  */
+  return;
+} /* confp3 */
 
 
-void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
+double decfp2(int kexp, int kmant)
 {
   /*
 
     Purpose:
     --------
 
-    Convert floating point number from machine
-    representation to GRIB representation.
+    Convert GRIB representation of a floating point
+    number to machine representation.
 
     Input Parameters:
     -----------------
 
-       pval    - Floating point number to be converted.
-       kbits   - Number of bits in computer word.
-       kround  - Conversion type.
-                 0 , Closest number in GRIB format less than
-                     original number.
-                 1 , Closest number in GRIB format to the
-                     original number (equal to, greater than or
-                     less than original number).
+    kexp    - 8 Bit signed exponent.
+    kmant   - 24 Bit mantissa.
 
     Output Parameters:
     ------------------
 
-       kexp    - 8 Bit signed exponent.
-       kmant   - 24 Bit mantissa.
+    Return value   - Floating point number represented
+                     by kexp and kmant.
 
     Method:
     -------
 
-    Floating point number represented as 8 bit signed
-    exponent and 24 bit mantissa in integer values.
+    Floating point number represented as 8 bit exponent
+    and 24 bit mantissa in integer values converted to
+    machine floating point format.
 
-    Externals.
+    Externals:
     ----------
 
-    decfp2    - Decode from IBM floating point format.
+    None.
 
     Reference:
     ----------
@@ -2589,12 +2278,15 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
     Comments:
     ---------
 
-    Routine aborts if an invalid conversion type parameter
-    is used or if a 24 bit mantissa is not produced.
+    Rewritten from DECFP, to conform to programming standards.
+    Sign bit on 0 value now ignored, if present.
+    If using 32 bit reals, check power of 16 is not so small as to
+    cause overflows (underflows!); this causes warning to be given
+    on Fujitsus.
 
     Author:
     -------
-     
+
     John Hennessy   ECMWF   18.06.91
 
     Modifications:
@@ -2602,324 +2294,76 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
 
     Uwe Schulzweida   MPIfM   01/04/2001
 
-    Convert to C from EMOS library version 130
-
+     - Convert to C from EMOS library version 130
+     
     Uwe Schulzweida   MPIfM   02/08/2002
 
-     - speed up by factor 1.6 on NEC SX6
-        - replace 1.0 / pow(16.0, (double)(iexp - 70)) by rpow16m70tab[iexp]
+     - speed up by factor 2 on NEC SX6
+        - replace pow(2.0, -24.0) by constant POW_2_M24
+        - replace pow(16.0, (double)(iexp - 64)) by pow16m64tab[iexp]
   */
 
-  double rpowref;
-  double zref, zeps;
+  double pval;
   int iexp, isign;
-  int iround;
-  // extern int CGRIBEX_Debug;
+  //extern int CGRIBEX_Debug;
   extern const double _pow16tab[71];
-
-  /* ----------------------------------------------------------------- */
-  /*   Section 1 . Initialise                                          */
-  /* ----------------------------------------------------------------- */
-
-  /*  Check conversion type parameter. */
-
-  iround = kround;
-  if ( iround != 0 && iround != 1 )
-    {
-      Error("Invalid conversion type = %d", iround);
-
-      /*  If not aborting, arbitrarily set rounding to 'up'. */
-     iround = 1;
-    }
-
+  
   /* ----------------------------------------------------------------- */
-  /*   Section 2 . Convert value of zero.                              */
+  /*   Section 1 . Convert value of 0.0. Ignore sign bit.              */
   /* ----------------------------------------------------------------- */
 
-  if ( ! (fabs(pval) > 0))
+  //if ( CGRIBEX_Debug ) Message("KEXP = %d  KMANT = %d", kexp, kmant);
+  /*
+  if ( (kexp == 128 || kexp == 0) && kmant == 0 )
+  */
+  if ( (kexp == 128) || (kexp == 0) || (kexp == 255) )
     {
-      *kexp  = 0;
-      *kmant = 0;
-      iexp   = 0;
-      isign  = 0;
+      pval = 0.0;
       goto LABEL900;
     }
 
   /* ----------------------------------------------------------------- */
-  /*   Section 3 . Convert other values.                               */
+  /*   Section 2 . Convert other values.                               */
   /* ----------------------------------------------------------------- */
 
-  zeps = 1.0e-12;
-  if ( kbits == 32 ) zeps = 1.0e-8;
-  zref = pval;
-
   /*  Sign of value. */
 
-  isign = 0;
-  if ( zref < 0.0 )
+  iexp  = kexp;
+  isign = 1;
+
+  if ( iexp >= 128 )
     {
-      isign = 128;
-      zref  = - zref;
+      iexp -= 128;
+      isign = -1;
     }
 
-  /*  Exponent. */
+  /*  Decode value. */
 
-  iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
+  /* pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); */
 
-  /* only ANSI C99 has log2 */
-  /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
+  iexp -= 64;
 
-  if ( iexp < 0   ) iexp = 0;
-  if ( iexp > 127 ) iexp = 127;
+  if ( iexp < 0 )
+    pval = 1./_pow16tab[-iexp];
+  else
+    pval = _pow16tab[iexp];
 
-  /*
-  rpowref = zref / pow(16.0, (double)(iexp - 70));
-  */
+  pval *= isign * POW_2_M24 * kmant;
 
-  if ( (iexp - 70) < 0 )
-    rpowref = zref * _pow16tab[-(iexp - 70)];
-  else
-    rpowref = zref / _pow16tab[(iexp - 70)];
+  /* ----------------------------------------------------------------- */
+  /*   Section 9. Return to calling routine.                           */
+  /* ----------------------------------------------------------------- */
 
-  /*  Mantissa. */
+LABEL900:
 
-  if ( iround == 0 )
-    {
-      /*  Closest number in GRIB format less than original number. */
-      /*  Truncate for positive numbers. */
-      /*  Round up for negative numbers. */
+  //if ( CGRIBEX_Debug ) Message("Returned value = %f", pval);
 
-      if ( isign == 0 )
-	*kmant = (int) rpowref;
-      else
-	*kmant = lround(rpowref + 0.5);
-    }
-  else
-    {
-      /*  Closest number in GRIB format to the original number   */
-      /*  (equal to, greater than or less than original number). */
-
-      *kmant = lround(rpowref);
-    }
-
-  /*  Check that mantissa value does not exceed 24 bits. */
-  /*  If it does, adjust the exponent upwards and recalculate */
-  /*  the mantissa. */
-  /*  16777215 = 2**24 - 1 */
-
-  if ( *kmant > 16777215 )
-    {
-
-    LABEL350:
-
-      ++iexp;
-
-      /*  Check for exponent overflow during adjustment  */
-
-      if ( iexp > 127 )
-	{
-          Message("Exponent overflow");
-          Message("Original number = %30.20f", pval);
-          Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
-		  isign, iexp, *kmant);
-
-	  Error("Exponent overflow");
-
-	  /*  If not aborting, arbitrarily set value to zero  */
-
-          Message("Value arbitrarily set to zero.");
-          *kexp  = 0;
-          *kmant = 0;
-          iexp  = 0;
-          isign = 0;
-          goto LABEL900;
-	}
-
-      if ( (iexp - 70) < 0 )
-	rpowref = zref * _pow16tab[-(iexp - 70)];
-      else
-	rpowref = zref / _pow16tab[(iexp - 70)];
-
-      if ( iround == 0 )
-	{
-	  /*  Closest number in GRIB format less than original number. */
-	  /*  Truncate for positive numbers. */
-	  /*  Round up for negative numbers. */
-
-	  if ( isign == 0 )
-	    *kmant = (int) rpowref;
-	  else
-	    *kmant = lround(rpowref + 0.5);
-	}
-      else
-	{
-	  /*  Closest number in GRIB format to the original number */
-	  /*  (equal to, greater or less than original number). */
-
-	  *kmant = lround(rpowref);
-	}
-
-      /*  Repeat calculation (with modified exponent) if still have */
-      /*  mantissa overflow. */
-
-      if ( *kmant > 16777215 ) goto LABEL350;
-    }
-
-  /*  Add sign bit to exponent. */
-
-  *kexp = iexp + isign;
-
-  /* ----------------------------------------------------------------- */
-  /*   Section 9. Return                                               */
-  /* ----------------------------------------------------------------- */
-
-LABEL900:
-  /*
-  if ( CGRIBEX_Debug )
-    {
-      double zval;
-
-      Message("Conversion type parameter = %4d", kround);
-      Message("Original number = %30.20f", pval);
-
-      zval = decfp2(*kexp, *kmant);
-
-      Message("Converted to      %30.20f", zval);
-      Message("Sign = %3d, Exponent = %3d, Mantissa = %12d", isign, iexp, *kmant);
-    }
-  */
-  return;
-} /* confp3 */
-
-
-double decfp2(int kexp, int kmant)
-{
-  /*
-
-    Purpose:
-    --------
-
-    Convert GRIB representation of a floating point
-    number to machine representation.
-
-    Input Parameters:
-    -----------------
-
-    kexp    - 8 Bit signed exponent.
-    kmant   - 24 Bit mantissa.
-
-    Output Parameters:
-    ------------------
-
-    Return value   - Floating point number represented
-                     by kexp and kmant.
-
-    Method:
-    -------
-
-    Floating point number represented as 8 bit exponent
-    and 24 bit mantissa in integer values converted to
-    machine floating point format.
-
-    Externals:
-    ----------
-
-    None.
-
-    Reference:
-    ----------
-
-    WMO Manual on Codes re GRIB representation.
-
-    Comments:
-    ---------
-
-    Rewritten from DECFP, to conform to programming standards.
-    Sign bit on 0 value now ignored, if present.
-    If using 32 bit reals, check power of 16 is not so small as to
-    cause overflows (underflows!); this causes warning to be given
-    on Fujitsus.
-
-    Author:
-    -------
-
-    John Hennessy   ECMWF   18.06.91
-
-    Modifications:
-    --------------
-
-    Uwe Schulzweida   MPIfM   01/04/2001
-
-     - Convert to C from EMOS library version 130
-     
-    Uwe Schulzweida   MPIfM   02/08/2002
-
-     - speed up by factor 2 on NEC SX6
-        - replace pow(2.0, -24.0) by constant POW_2_M24
-        - replace pow(16.0, (double)(iexp - 64)) by pow16m64tab[iexp]
-  */
-
-  double pval;
-  int iexp, isign;
-  //extern int CGRIBEX_Debug;
-  extern const double _pow16tab[71];
-  
-  /* ----------------------------------------------------------------- */
-  /*   Section 1 . Convert value of 0.0. Ignore sign bit.              */
-  /* ----------------------------------------------------------------- */
-
-  //if ( CGRIBEX_Debug ) Message("KEXP = %d  KMANT = %d", kexp, kmant);
-  /*
-  if ( (kexp == 128 || kexp == 0) && kmant == 0 )
-  */
-  if ( (kexp == 128) || (kexp == 0) || (kexp == 255) )
-    {
-      pval = 0.0;
-      goto LABEL900;
-    }
-
-  /* ----------------------------------------------------------------- */
-  /*   Section 2 . Convert other values.                               */
-  /* ----------------------------------------------------------------- */
-
-  /*  Sign of value. */
-
-  iexp  = kexp;
-  isign = 1;
-
-  if ( iexp >= 128 )
-    {
-      iexp -= 128;
-      isign = -1;
-    }
-
-  /*  Decode value. */
-
-  /* pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); */
-
-  iexp -= 64;
-
-  if ( iexp < 0 )
-    pval = 1./_pow16tab[-iexp];
-  else
-    pval = _pow16tab[iexp];
-
-  pval *= isign * POW_2_M24 * kmant;
-
-  /* ----------------------------------------------------------------- */
-  /*   Section 9. Return to calling routine.                           */
-  /* ----------------------------------------------------------------- */
-
-LABEL900:
-
-  //if ( CGRIBEX_Debug ) Message("Returned value = %f", pval);
-
-  return (pval);
-} /* decfp2 */
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdarg.h>
+  return (pval);
+} /* decfp2 */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
 
 
 
@@ -3048,13 +2492,14 @@ void gribDateTime(int *isec1, int *date, int *time)
       addsec = 0;
       switch ( ISEC1_TimeUnit )
 	{
-	case ISEC1_TABLE4_MINUTE:  addsec =    60 * time_period; break;
-	case ISEC1_TABLE4_QUARTER: addsec =   900 * time_period; break;
-	case ISEC1_TABLE4_HOUR:    addsec =  3600 * time_period; break;
-	case ISEC1_TABLE4_3HOURS:  addsec = 10800 * time_period; break;
-	case ISEC1_TABLE4_6HOURS:  addsec = 21600 * time_period; break;
-	case ISEC1_TABLE4_12HOURS: addsec = 43200 * time_period; break;
-	case ISEC1_TABLE4_DAY:     addsec = 86400 * time_period; break;
+	case ISEC1_TABLE4_MINUTE:    addsec =    60 * time_period; break;
+	case ISEC1_TABLE4_QUARTER:   addsec =   900 * time_period; break;
+	case ISEC1_TABLE4_30MINUTES: addsec =  1800 * time_period; break;
+	case ISEC1_TABLE4_HOUR:      addsec =  3600 * time_period; break;
+	case ISEC1_TABLE4_3HOURS:    addsec = 10800 * time_period; break;
+	case ISEC1_TABLE4_6HOURS:    addsec = 21600 * time_period; break;
+	case ISEC1_TABLE4_12HOURS:   addsec = 43200 * time_period; break;
+	case ISEC1_TABLE4_DAY:       addsec = 86400 * time_period; break;
 	default:
 	  if ( lprint )
 	    {
@@ -3102,15 +2547,21 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
   int yfunc = *hoper;
 
   if ( yfunc == 'C' )
-    gribEncode(isec0, isec1, isec2, fsec2, isec3,
-	       fsec3, isec4, fsec4, klenp, kgrib,
-	       kleng, kword, yfunc, kret);
+    {
+      grib_encode_double(isec0, isec1, isec2, fsec2, isec3,
+			 fsec3, isec4, fsec4, klenp, kgrib,
+			 kleng, kword, yfunc, kret);
+    }
   else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
-    gribDecode(isec0, isec1, isec2, fsec2, isec3,
-	       fsec3, isec4, fsec4, klenp, kgrib,
-	       kleng, kword, yfunc, kret);
+    {
+      grib_decode_double(isec0, isec1, isec2, fsec2, isec3,
+			 fsec3, isec4, fsec4, klenp, kgrib,
+			 kleng, kword, yfunc, kret);
+    }
   else if ( yfunc == 'V' )
-    fprintf(stderr, "  cgribex: Version is %s\n", cgribexLibraryVersion());
+    {
+      fprintf(stderr, "  cgribex: Version is %s\n", cgribexLibraryVersion());
+    }
   else
     {
       Error("oper %c unsupported!", yfunc);
@@ -3120,10 +2571,41 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
 
 
 void
-gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
-	 float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
+gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
+	 float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
 	 int kleng, int *kword, char *hoper, int *kret)
 {
+  int yfunc = *hoper;
+
+  if ( yfunc == 'C' )
+    {
+      grib_encode_float(isec0, isec1, isec2, fsec2, isec3,
+			fsec3, isec4, fsec4, klenp, kgrib,
+			kleng, kword, yfunc, kret);
+    }
+  else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
+    {
+      grib_decode_float(isec0, isec1, isec2, fsec2, isec3,
+			fsec3, isec4, fsec4, klenp, kgrib,
+			kleng, kword, yfunc, kret);
+    }
+  else if ( yfunc == 'V' )
+    {
+      fprintf(stderr, " cgribex: Version is %s\n", cgribexLibraryVersion());
+    }
+  else
+    {
+      Error("oper %c unsupported!", yfunc);
+      *kret=-9;
+    }
+}
+
+
+void
+gribExSP_old(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
+	     float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
+	     int kleng, int *kword, char *hoper, int *kret)
+{
   int inum, j;
   double fsec2dp[1024];
   double fsec3dp[2];
@@ -3231,11 +2713,13 @@ void gribSetConst(int flag)
 
 void gribSetRound(int round)
 {
+  UNUSED(round);
 }
 
 
 void gribSetRefDP(double refval)
 {
+  UNUSED(refval);
 }
 
 
@@ -3247,6 +2731,7 @@ void gribSetRefSP(float refval)
 
 void gribSetValueCheck(int vcheck)
 {
+  UNUSED(vcheck);
 }
 #include <string.h>
 #include <math.h>
@@ -3306,7 +2791,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 
   */
 
-  int iprev, icurr, icount, ioffset;
+  int iprev, icurr, ioffset;
   int ibit, ierr, iout, iyear;
   int jloop, jiloop;
   float value;
@@ -3400,7 +2885,7 @@ void gribPrintSec1(int *isec0, int *isec1)
     fprintf(grprsm, " Century of reference time of data.   %9d\n", isec1[20]);
 
   /*   Print sub-centre  */
-  fprintf(grprsm, " Sub-centre identifier.               %9d\n", isec1[21]);
+  fprintf(grprsm, " Sub-centre identifier.               %9d\n", ISEC1_SubCenterID);
 
   /*   Decimal scale factor  */
   fprintf(grprsm, " Units decimal scaling factor.        %9d\n", isec1[22]);
@@ -3858,7 +3343,7 @@ void gribPrintSec1(int *isec0, int *isec1)
           fprintf(grprsm, " List of different time intervals used:\n");
           iprev  = isec1[49];
           icurr  = 0;
-          icount = 0;
+          unsigned icount = 0;
           for (jloop = 1; jloop <= isec1[48]; jloop++)
 	    {
 	      icurr = isec1[48+jloop];
@@ -3869,7 +3354,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 		  if ( icount == 2 )
 		    fprintf(grprsm, "  - interval %5.4d used       twice\n", iprev);
 		  if ( icount > 2 )
-		    fprintf(grprsm, "  - interval %5.4d used %5d times\n",  iprev, icount);
+		    fprintf(grprsm, "  - interval %5.4d used %5u times\n",  iprev, icount);
 		  iprev  = icurr;
 		  icount = 1;
 		}
@@ -3881,7 +3366,7 @@ void gribPrintSec1(int *isec0, int *isec1)
 	  if ( icount == 2 )
 	    fprintf(grprsm, "  - interval %5.4d used       twice\n", iprev);
 	  if ( icount > 2 )
-	    fprintf(grprsm, "  - interval %5.4d used %5d times\n",  iprev, icount);
+	    fprintf(grprsm, "  - interval %5.4d used %5u times\n",  iprev, icount);
 	}
       /*
 	ECMWF Local definition 13.
@@ -4012,7 +3497,7 @@ void gribPrintSec1(int *isec0, int *isec1)
     Washington EPS products (but not reformatted Washington EPS
     products.
   */
-  if ( (isec1[1] == 7 && isec1[23] == 1) && (! isec1[21] == 98) )
+  if ( (isec1[1] == 7 && isec1[23] == 1) && (! (ISEC1_SubCenterID == 98)) )
     {
       /*   CALL KWPRS1 (iSEC0,iSEC1)*/
     }
@@ -4054,7 +3539,7 @@ void printQuasi(int *isec2)
   */
 
   char yout[64];
-  int nextlat, nrepeat, latcnt;
+  int nextlat, latcnt;
   int j;
   int ntos;
 
@@ -4095,7 +3580,7 @@ void printQuasi(int *isec2)
       /*
 	Look for neighbouring latitudes with same number of points
       */
-      nrepeat = 0;
+      unsigned nrepeat = 0;
 
     LABEL110:
       /*
@@ -4366,7 +3851,7 @@ void gribPrintSec2DP(int *isec0, int *isec2, double *fsec2)
     -----------------------------------------------------------------
   */
   /*
-  if ( isec2[0] == 192 && isec1[1] == 98 )
+  if ( isec2[0] == 192 && ISEC1_CenterID == 98 )
     {
       fprintf(grprsm, " Data represent type = ECMWF ocean  (Table 6) %9d\n", isec2[0]);
       if ( isec2[1] ==  32767 )
@@ -4390,7 +3875,7 @@ void gribPrintSec2DP(int *isec0, int *isec2, double *fsec2)
     Section 7.6 . Print triangular data
     -----------------------------------------------------------------
   */
-  if ( isec2[0] == 192 /* && isec1[1] == 78 */ )
+  if ( isec2[0] == 192 /* && ISEC1_CenterID == 78 */ )
     {
       fprintf(grprsm, " Data represent type = triangular   (Table 6) %9d\n", isec2[0]);
       fprintf(grprsm, " Number of factor 2 in factorisation of Ni.   %9d\n", isec2[1]);
@@ -4509,6 +3994,8 @@ void gribPrintSec3DP(int *isec0, int *isec3, double *fsec3)
 
   */
 
+  UNUSED(isec0);
+
   grsdef();
 
   fprintf(grprsm, " \n");
@@ -4559,6 +4046,8 @@ void gribPrintSec4DP(int *isec0, int *isec4, double *fsec4)
   int inum;
   int j;
 
+  UNUSED(isec0);
+
   grsdef();
 
   /*
@@ -4737,6171 +4226,10013 @@ void gribPrintSec4Wave(int *isec4)
       fprintf(grprsm, "%20.10f\n", *ptemp);
     }
 }
-#include <string.h>
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
 
-int  BitsPerInt = (int) (sizeof(int) * 8);
+#include <string.h>
+#include <ctype.h>
 
 
 
-/* GRIB block 0 - indicator block */
-static
-void encodeIS(GRIBPACK *lGrib, long *gribLen)
+int gribOpen(const char *filename, const char *mode)
 {
-  long z = *gribLen;
-
-  lGrib[0] = 'G';
-  lGrib[1] = 'R';
-  lGrib[2] = 'I';
-  lGrib[3] = 'B';
+  int fileID;
 
-  /* 
-   * lGrib[4]-lGrib[6] contains full length of grib record. 
-   * included before finished CODEGB
-   */
+  fileID = fileOpen(filename, mode);
 
-  z = 7;   
-  Put1Byte(1); /* grib version */
-  z = 8;
+#if defined (__sun)
+  if ( fileID != FILE_UNDEFID && tolower(*mode) == 'r' )
+    {
+      fileSetBufferType(fileID, FILE_BUFTYPE_MMAP);
+    }
+#endif
 
-  *gribLen = z;
+  return (fileID);  
 }
 
-/* GRIB block 5 - end block */
-static
-void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
+
+void gribClose(int fileID)
 {
-  long z = *gribLen;
+  fileClose(fileID);
+}
 
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
-  lGrib[z++] = '7';
 
-  if ( z > JP23SET )
-    {
-      long itemp;
-      long bdslen = z - 4;
-      /*
-      fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET);
-      exit(1);
-      */
-      /*
-	If a very large product, the section 4 length field holds
-	the number of bytes in the product after section 4 upto
-	the end of the padding bytes.
-	This is a fixup to get round the restriction on product lengths
-	due to the count being only 24 bits. It is only possible because
-	the (default) rounding for GRIB products is 120 bytes.
-      */
-      while ( z%120 ) lGrib[z++] = 0;
+off_t gribGetPos(int fileID)
+{
+  return (fileGetPos(fileID));
+}
 
-      if ( z > JP23SET*120 )
-	{
-	  fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET*120);
-	  exit(1);
-	}
 
-      itemp = z / (-120);
-      itemp = JP23SET - itemp + 1;
+int gribCheckFiletype(int fileID)
+{
+  int ierr;
+  int found = 0;
+  char buffer[4];
 
-      lGrib[4] = itemp >> 16;
-      lGrib[5] = itemp >>  8;
-      lGrib[6] = itemp;
+  if ( fileRead(fileID, buffer, 4) != 4 ) return(found);
 
-      bdslen = z - bdslen;
-      lGrib[bdsstart  ] = bdslen >> 16;
-      lGrib[bdsstart+1] = bdslen >>  8;
-      lGrib[bdsstart+2] = bdslen;
+  if ( memcmp(buffer, "GRIB", 4) == 0 )
+    {
+      found = 1;
+      if ( CGRIBEX_Debug ) Message("found GRIB file = %s", fileInqName(fileID));
     }
   else
     {
-      lGrib[4] = z >> 16;
-      lGrib[5] = z >>  8;
-      lGrib[6] = z;
+      long offset;
 
-      while ( z%8 ) lGrib[z++] = 0;
+      ierr = gribFileSeek(fileID, &offset);
+      fileRewind(fileID);
+      if ( !ierr )
+	{
+	  found = 1;
+	  if ( CGRIBEX_Debug ) Message("found seek GRIB file = %s", fileInqName(fileID));
+	}
     }
 
-  *gribLen = z;
+  return (found);
 }
 
-/* GRIB block 1 - product definition block. */
-
-#define DWD_extension_253_len 38
-#define DWD_extension_254_len 26
-#define ECMWF_extension_1_len 24
-#define MPIM_extension_1_len  18
 
-static
-long getLocalExtLen(int *isec1)
+int gribCheckSeek(int fileID, long *offset, int *version)
 {
-  long extlen = 0;
+  int ierr;
+  char buffer[4];
 
-  if ( ISEC1_LocalFLag )
+  ierr = gribFileSeek(fileID, offset);
+
+  *version = -1;
+  if ( !ierr )
     {
-      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	{
-	  if      ( isec1[36] == 254 ) extlen = DWD_extension_254_len;
-	  else if ( isec1[36] == 253 ) extlen = DWD_extension_253_len;
-	}
-      else if ( ISEC1_CenterID == 98 )
-        {
-	  if ( isec1[36] == 1 )   extlen = ECMWF_extension_1_len;
-        }
-      else if ( ISEC1_CenterID == 252 )
-        {
-	  if ( isec1[36] == 1 ) extlen = MPIM_extension_1_len;
-        }
+      if ( fileRead(fileID, buffer, 4) == 4 )
+	*version = buffer[3];
     }
 
-  return (extlen);
+  return (ierr);
 }
 
-static
-long getPdsLen(int *isec1)
+
+int gribFileSeekOld(int fileID, long *offset)
 {
-  long pdslen = 28;
+  /* position file pointer after GRIB */
+  int ch;
+  int buffersize = 4096;
+  unsigned char buffer[4096];
+  int retry = 4096;
+  int i;
+  void *fileptr;
 
-  pdslen += getLocalExtLen(isec1);
+  *offset = 0;
 
-  return (pdslen);
-}
+  fileptr = filePtr(fileID);
 
-static
-void encodePDS_DWD_local_Extension_254(GRIBPACK *lGrib, long *zs, int *isec1)
-{
-  int isvn;
-  long localextlen, i;
-  long z = *zs;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
+  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
+  /*
+  fileRead(fileID, buffer, 4);
+  */
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-2; i++ )
+  while ( retry-- )
     {
-      Put1Byte(isec1[24+i]);
+      for ( i = 0; i < buffersize-4; ++i )
+	{
+	  if (buffer[i  ] == 'G' && 
+	      buffer[i+1] == 'R' &&
+	      buffer[i+2] == 'I' &&
+	      buffer[i+3] == 'B')
+	    {
+	      if ( CGRIBEX_Debug )
+		Message("record offset = %d", (int) *offset);
+	      return (0);
+	    }
+	  else
+	    {
+	      ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
+	      (*offset)++;
+	    }
+	}
+      buffer[0] = buffer[i  ];
+      buffer[1] = buffer[i+1];
+      buffer[2] = buffer[i+2];
+      buffer[3] = buffer[i+3];
     }
 
-  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
-  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
 
-  *zs = z;
+  return (1);
 }
 
-static
-void encodePDS_DWD_local_Extension_253(GRIBPACK *lGrib, long *zs, int *isec1)
+
+int gribFileSeek(int fileID, long *offset)
 {
-  int isvn;
-  long localextlen, i;
-  long z = *zs;
+  /* position file pointer after GRIB */
+  const long GRIB = 0x47524942;
+  long code = 0;
+  int ch;
+  int retry = 4096*4096;
+  void *fileptr;
 
-  localextlen = DWD_extension_254_len;
-  for ( i = 0; i < localextlen-2; i++ )
+  *offset = 0;
+
+  fileptr = filePtr(fileID);
+
+  while ( retry-- )
     {
-      Put1Byte(isec1[24+i]);
+      ch = filePtrGetc(fileptr);
+      if ( ch == EOF ) return (-1);
+    
+      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+
+      if ( code == GRIB )
+	{
+	  if ( CGRIBEX_Debug )
+	    Message("record offset = %d", (int) *offset);
+	  return (0);
+	}
+
+      (*offset)++;
     }
 
-  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
-  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
-  Put1Byte(isec1[50]);        /* 55 User id, specified by table       */
-  Put2Byte(isec1[51]);        /* 56 Experiment identifier             */
-  Put2Byte(isec1[52]);        /* 58 Ensemble identification by table  */
-  Put2Byte(isec1[53]);        /* 60 Number of ensemble members        */
-  Put2Byte(isec1[54]);        /* 62 Actual number of ensemble member  */
-  Put1Byte(isec1[55]);        /* 64 Model major version number        */ 
-  Put1Byte(isec1[56]);        /* 65 Model minor version number        */ 
-  Put1Byte(0);                /* 66 Blank for even buffer length      */
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
 
-  *zs = z;
+  return (1);
 }
 
-static
-void encodePDS_ECMWF_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
-{
-  // int isvn;
-  long localextlen, i;
-  long z = *zs;
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-12; i++ )
-    {
-      Put1Byte(isec1[24+i]);
-    }
-                              /* 12 bytes explicitly encoded below:         */
-  Put1Byte(isec1[36]);        /* ECMWF local GRIB use definition identifier */
-                              /*    1=MARS labelling or ensemble fcst. data */
-  Put1Byte(isec1[37]);        /* Class                                      */
-  Put1Byte(isec1[38]);        /* Type                                       */
-  Put2Byte(isec1[39]);        /* Stream                                     */
+int gribFileSeekTest(int fileID, long *offset)
+{
+  /* position file pointer after GRIB */
+  const long GRIB = 0x47524942;
+  long code = 0;
+  int ch;
+  int i = 0;
+  const int buffersize = 8;
+  unsigned char buffer[8];
+  int retry = 4096*4096;
+  void *fileptr;
+  int nread = 0;
 
-  /* Version number or experiment identifier    */
-  Put1Byte(((unsigned char*) &isec1[40])[0]);
-  Put1Byte(((unsigned char*) &isec1[40])[1]);
-  Put1Byte(((unsigned char*) &isec1[40])[2]);
-  Put1Byte(((unsigned char*) &isec1[40])[3]);
+  *offset = 0;
 
-  Put1Byte(isec1[41]);        /* Ensemble forecast number                   */
-  Put1Byte(isec1[42]);        /* Total number of forecasts in ensemble      */
-  Put1Byte(0);                /* (Spare)                                    */
+  fileptr = filePtr(fileID);
 
-  *zs = z;
-}
+  while ( retry-- )
+    {
+      if ( i >= nread )
+	{
+	  nread = (int) filePtrRead(fileptr, buffer, buffersize);
+	  if ( nread == 0 ) return (-1);
+	  i = 0;
+	}
 
-static
-void encodePDS_MPIM_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
-{
-  // int isvn;
-  long localextlen, i;
-  long z = *zs;
+      ch = buffer[i++];
+      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
 
-  localextlen = getLocalExtLen(isec1);
-  for ( i = 0; i < localextlen-6; i++ )
-    {
-      Put1Byte(isec1[24+i]);
+      if ( code == GRIB )
+	{
+	  /* printf("end: %d %d\n", nread, i); */
+	  if ( CGRIBEX_Debug )
+	    Message("record offset = %d", (int) *offset);
+
+	  if ( i != nread ) fileSetPos(fileID, (off_t) i-nread, SEEK_CUR);
+
+	  return (0);
+	}
+
+      (*offset)++;
     }
-                              /* 6 bytes explicitly encoded below:          */
-  Put1Byte(isec1[36]);        /* MPIM local GRIB use definition identifier  */
-                              /*    (extension identifier)                  */
-  Put1Byte(isec1[37]);        /* type of ensemble forecast                  */
-  Put2Byte(isec1[38]);        /* individual ensemble member                 */
-  Put2Byte(isec1[39]);        /* number of forecasts in ensemble            */
 
-  *zs = z;
+  if ( CGRIBEX_Debug )
+    Message("record offset = %d", (int) *offset);
+
+  return (1);
 }
 
-/* GRIB BLOCK 1 - PRODUCT DESCRIPTION SECTION */
-static
-void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
+
+int gribReadSize(int fileID)
 {
-  GRIBPACK *lGrib = lpds;
-  long z = 0;
-  int ival, century, year;
+  int gribversion, gribsize;
+  int b1, b2, b3;
+  off_t pos;
+  void *fileptr;
+  /*
+  const int buffersize = 4;
+  unsigned char buffer[4];
+  */
+  fileptr = filePtr(fileID);
 
-  century = ISEC1_Century;
-  year    = ISEC1_Year;
+  pos = fileGetPos(fileID); 
+  /* bug: order of functions calls!
+     gribsize = (filePtrGetc(fileptr) << 16) + (filePtrGetc(fileptr) << 8) + filePtrGetc(fileptr);
+  */
+  b1 = filePtrGetc(fileptr);
+  b2 = filePtrGetc(fileptr);
+  b3 = filePtrGetc(fileptr);
+  // gribsize = (b1 << 16) + (b2 << 8) + b3;
+  gribsize = gribrec_len(b1, b2, b3);
 
-  if ( century < 0 )
-    {
-      century = -century;
-      year    = -year;
-    }
+  gribversion = filePtrGetc(fileptr);
+  /*
+  filePtrRead(fileptr, buffer, buffersize);
 
-  Put3Byte(pdsLen);               /*  0 Length of Block 1        */
-  Put1Byte(ISEC1_CodeTable);      /*  3 Local table number       */
-  Put1Byte(ISEC1_CenterID);       /*  4 Identification of centre */
-  Put1Byte(ISEC1_ModelID);        /*  5 Identification of model  */
-  Put1Byte(ISEC1_GridDefinition); /*  6 Grid definition          */
-  Put1Byte(ISEC1_Sec2Or3Flag);    /*  7 Block 2 included         */
-  Put1Byte(ISEC1_Parameter);      /*  8 Parameter Code           */
-  Put1Byte(ISEC1_LevelType);      /*  9 Type of level            */
-  if ( (ISEC1_LevelType !=  20) &&
-       (ISEC1_LevelType != GRIB1_LTYPE_99)         &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)   &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)   &&
-       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)     &&
-       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)      &&
-       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)     &&
-       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH)  &&
-       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
-       (ISEC1_LevelType != 115) &&
-       (ISEC1_LevelType != 117) &&
-       (ISEC1_LevelType != 125) &&
-       (ISEC1_LevelType != 127) &&
-       (ISEC1_LevelType != 160) &&
-       (ISEC1_LevelType != 210) )
-    {
-      Put1Byte(ISEC1_Level1);
-      Put1Byte(ISEC1_Level2);
-    }
-  else
+  gribsize = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
+
+  gribversion = buffer[3];
+  */
+  if ( gribsize == 24 )
     {
-      Put2Byte(ISEC1_Level1);     /* 10 Level                    */    
+      if ( gribversion != 1 && gribversion != 2 ) gribversion = 0;
     }
 
-  Put1Int(year);                  /* 12 Year of Century          */
-  Put1Byte(ISEC1_Month);          /* 13 Month                    */
-  Put1Byte(ISEC1_Day);            /* 14 Day                      */
-  Put1Byte(ISEC1_Hour);           /* 15 Hour                     */
-  Put1Byte(ISEC1_Minute);         /* 16 Minute                   */
+  if ( CGRIBEX_Debug )
+    Message("gribversion = %d", gribversion);
 
-  Put1Byte(ISEC1_TimeUnit);       /* 17 Time unit                */
-  if ( ISEC1_TimeRange == 10 )
-    {
-      Put1Byte(ISEC1_TimePeriod1);
-      Put1Byte(ISEC1_TimePeriod2);
-    }
-  else if ( ISEC1_TimeRange == 113 || ISEC1_TimeRange ==   0 )
-    {
-      Put1Byte(ISEC1_TimePeriod1);
-      Put1Byte(0);
-    }
-  else if ( ISEC1_TimeRange ==   5 || ISEC1_TimeRange ==   4 || 
-	    ISEC1_TimeRange ==   3 || ISEC1_TimeRange ==   2 )
-    {
-      Put1Byte(0);
-      Put1Byte(ISEC1_TimePeriod2);
-    }
-  else
+  if ( gribversion == 0 )
     {
-      Put1Byte(0);
-      Put1Byte(0); 
-    }
-  Put1Byte(ISEC1_TimeRange);      /* 20 Timerange flag           */
-  Put2Byte(ISEC1_AvgNum);         /* 21 Average                  */
+      int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
+      int issize = 4, essize = 4;
+      int flag;
 
-  Put1Byte(ISEC1_AvgMiss);        /* 23 Missing from averages    */
-  Put1Byte(century);              /* 24 Century                  */
-  Put1Byte(ISEC1_SubCenterID);    /* 25 Subcenter                */
-  Put2Byte(ISEC1_DecScaleFactor); /* 26 Decimal scale factor     */
+      pdssize = gribsize;
+      fileSetPos(fileID, (off_t) 3, SEEK_CUR);
+      if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
+      flag = filePtrGetc(fileptr);
+      if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
+  
+      fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
 
-  if ( ISEC1_LocalFLag )
-    {
-      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	{
-	  if      ( isec1[36] == 254 ) encodePDS_DWD_local_Extension_254(lGrib, &z, isec1);
-	  else if ( isec1[36] == 253 ) encodePDS_DWD_local_Extension_253(lGrib, &z, isec1);
-	}
-      else if ( ISEC1_CenterID == 98 )
-	{
-	  if ( isec1[36] == 1 ) encodePDS_ECMWF_local_Extension_1(lGrib, &z, isec1);
-	}
-      else if ( ISEC1_CenterID == 252 )
+      if ( flag & 128 )
 	{
-	  if ( isec1[36] == 1 ) encodePDS_MPIM_local_Extension_1(lGrib, &z, isec1);
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  gdssize = (b1 << 16) + (b2 << 8) + b3;
+	  fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
+	  if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
 	}
-      else
+
+      if ( flag & 64 )
 	{
-	  long i, localextlen;
-	  localextlen = getLocalExtLen(isec1);
-	  for ( i = 0; i < localextlen; i++ )
-	    {
-	      Put1Byte(isec1[24+i]);
-	    }
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  bmssize = (b1 << 16) + (b2 << 8) + b3;
+	  fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
+	  if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
 	}
-    }
-}
-
-/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
-static
-void encodeGDS(GRIBPACK *lGrib, long *gribLen, int *isec2, double *fsec2)
-{
-  long z = *gribLen;
-  int exponent, mantissa;
-  long i;
-  int ival;
-  int pvoffset = 0xFF;
-  int gdslen = 32;
-  unsigned lonIncr, latIncr;
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
-
-  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
+      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+      bdssize = (b1 << 16) + (b2 << 8) + b3;
+      if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
 
-  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
+      gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
+    }
+  else if ( gribversion == 1 )
+    {
+      if ( gribsize > JP23SET ) /* Large GRIB record */
+	{
+	  int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
+	  int issize = 4, essize = 4;
+	  int flag;
 
-  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  pdssize = (b1 << 16) + (b2 << 8) + b3;
+	  if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
 
-  gdslen += ISEC2_NumVCP * 4;
+	  for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
+	  if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
+  
+	  fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
 
-  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
-  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
-  Put1Byte(pvoffset);           /*  4    PV */
-  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
+	  if ( flag & 128 )
+	    {
+	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	      gdssize = (b1 << 16) + (b2 << 8) + b3;
+	      fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
+	      if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
+	    }
+	  
+	  if ( flag & 64 )
+	    {
+	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	      bmssize = (b1 << 16) + (b2 << 8) + b3;
+	      fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
+	      if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
+	    }
 
-  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
-    {
-      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
-      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
-      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
-      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
-      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
-      PutnZero(18);             /* 14-31 reserved                 */
+	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
+	  bdssize = (b1 << 16) + (b2 << 8) + b3;
+	  bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
+	  if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
+
+	  gribsize = issize+pdssize+gdssize+bmssize+bdssize+essize;
+	}
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+  else if ( gribversion == 2 )
     {
-      Put2Byte(ISEC2_GME_NI2);
-      Put2Byte(ISEC2_GME_NI3);
-      Put3Byte(ISEC2_GME_ND);
-      Put3Byte(ISEC2_GME_NI);
-      Put1Byte(ISEC2_GME_AFlag);
-      Put3Int(ISEC2_GME_LatPP);
-      Put3Int(ISEC2_GME_LonPP);
-      Put3Int(ISEC2_GME_LonMPL);
-      Put1Byte(ISEC2_GME_BFlag);
-      PutnZero(5);
+      int i;
+      /* we set gribsize the following way because it doesn't matter then
+	 whether int is 4 or 8 bytes long - we don't have to care if the size
+	 really fits: if it does not, the record can not be read at all */
+      gribsize = 0;
+      for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | filePtrGetc(fileptr);
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+  else
     {
-      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
-
-      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
-      Put3Int(ISEC2_FirstLat);
-      Put3Int(ISEC2_FirstLon);
-      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
-      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
-      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
-      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
-      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
-      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
-      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
-      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
-      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
-      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
-      PutnZero(2);                     /* 34-41 */
+      gribsize = 0;
+      Warning("GRIB version %d unsupported!", gribversion);
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-    {
-      int numlon;
-      if ( ISEC2_Reduced )
-	numlon = 0xFFFF;
-      else
-	numlon = ISEC2_NumLon;
 
-      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
+  if ( filePtrEOF(fileptr) ) gribsize = 0;
 
-      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
-      Put3Int(ISEC2_FirstLat);
-      Put3Int(ISEC2_FirstLon);
-      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
-      Put3Int(ISEC2_LastLat);
-      Put3Int(ISEC2_LastLon);
-      if ( ISEC2_ResFlag == 0 )
-	{
-	  lonIncr = 0xFFFF;
-	  latIncr = 0xFFFF;
-	}
-      else
-	{
-	  lonIncr = ISEC2_LonIncr;
-	  latIncr = ISEC2_LatIncr;
-	}
-      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
-      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
-	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
-      else
-	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
+  if ( CGRIBEX_Debug )
+    Message("gribsize    = %d", gribsize);
 
-      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
-      PutnZero(4);                     /* 28-31 reserved                 */
+  fileSetPos(fileID, pos, SEEK_SET);
 
-      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-	{
-	  Put3Int(ISEC2_LatSP);
-	  Put3Int(ISEC2_LonSP);
-	  Put1Real(FSEC2_RotAngle);
-	}
-    }
-  else
-    {
-      Error("Unsupported grid type %d", ISEC2_GridType);
-    }
+  return (gribsize);
+}
 
-#if defined (SX)
-#pragma vdir novector     /* vectorization gives wrong results on NEC */
-#endif
-  for ( i = 0; i < ISEC2_NumVCP; ++i )
+
+int gribGetSize(int fileID)
+{
+  int recsize;
+  long offset;
+  int ierr;
+
+  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
+  if ( ierr > 0 )
     {
-      Put1Real(fsec2[10+i]);
+      Warning("GRIB record not found!");
+      return (0);
     }
 
-  if ( ISEC2_Reduced )
-    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
+  if ( ierr == -1 )
+    return (0);
+  else if ( ierr == 1 )
+    return (0);
 
-  *gribLen = z;
+  recsize = gribReadSize(fileID);
+
+  if ( CGRIBEX_Debug ) Message("recsize = %d", recsize);
+
+  fileSetPos(fileID, (off_t) -4, SEEK_CUR);
+
+  return (recsize);
 }
 
-/* GRIB BLOCK 3 - BIT MAP SECTION */
-static
-void encodeBMS(GRIBPACK *lGrib, long *gribLen, double *fsec3, int *isec4, double *data, long *datasize)
+
+int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
 {
-  GRIBPACK *bitmap;
-  long bitmapSize;
-  long imaskSize;
-  long i;
-  long bmsLen, bmsUnusedBits;
-  long fsec4size;
-  long z = *gribLen;
-#if defined (VECTORCODE)
-  unsigned int *imask;
-#endif
-  static int lmissvalinfo = 1;
-  /*  unsigned int c, imask; */
+  long offset;
+  int ierr = 0;
+  size_t nread, recsize, recsize0;
 
-  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
+  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
+  if ( ierr > 0 )
     {
-      lmissvalinfo = 0;
-      Message("Missing value = NaN is unsupported!");
+      Warning("GRIB record not found!");
+      return (-2);
     }
 
-  bitmapSize = ISEC4_NumValues;
-  imaskSize = ((bitmapSize+7)>>3)<<3;
-  bitmap = &lGrib[z+6];
-  fsec4size = 0;
-
-#if defined (VECTORCODE)
-  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
-  memset(imask, 0, imaskSize*sizeof(int));
-
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-  for ( i = 0; i < bitmapSize; i++ )
+  if ( ierr == -1 )
     {
-      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
-	{
-	  data[fsec4size++] = data[i];
-	  imask[i] = 1;
-	}
+      *buffersize = 0;
+      return (-1);
     }
-
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-  for ( i = 0; i < imaskSize/8; i++ )
+  else if ( ierr == 1 )
     {
-      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
-	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
-	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
-	          (imask[i*8+6] << 1) | (imask[i*8+7]);
+      *buffersize = 0;
+      return (-2);
     }
 
-  free(imask);
-#else
-  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
+  recsize = gribReadSize(fileID);
 
-  for ( i = 0; i < bitmapSize; i++ )
+  buffer[0] = 'G';
+  buffer[1] = 'R';
+  buffer[2] = 'I';
+  buffer[3] = 'B';
+
+  recsize0 = recsize;
+
+  if ( recsize > *buffersize )
     {
-      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
-	{
-	  data[fsec4size++] = data[i];
-	  bitmap[i/8] |= 1<<(7-(i&7));
-	}
+      recsize = *buffersize;
+      ierr = -3;
     }
-#endif
 
-  bmsLen = imaskSize/8 + 6;
-  bmsUnusedBits = imaskSize - bitmapSize;
+  *buffersize = recsize0;
 
-  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
-  Put1Byte(bmsUnusedBits);
-  Put2Byte(0);
+  nread = fileRead(fileID, &buffer[4], recsize-4);
 
-  *gribLen += bmsLen;
+  if ( nread != recsize-4 ) ierr = 1;
 
-  *datasize = fsec4size;
+  return (ierr);
 }
 
 
-/* GRIB BLOCK 4 - BINARY DATA SECTION */
-static
-int encodeBDS(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, double *data,
-	      long *datstart, long *datsize, int code)
+int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
 {
-  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
-  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
+  int  nwrite = 0;
 
-  size_t z = *gribLen;
-  long i, jloop;
-  int numBits;
-  int ival;
-  int blockLength, PackStart = 0, Flag = 0;
-  int binscale = 0;
-  int nbpv;
-  int bds_head = 11;
-  int bds_ext = 0;
-  /* ibits = BitsPerInt; */
-  unsigned int max_nbpv_pow2;
-  int exponent, mantissa;
-  int unused_bits = 0;
-  int lspherc = FALSE, lcomplex = FALSE;
-  int isubset = 0, itemp = 0, itrunc = 0;
-  double factor = 1, fmin, fmax, zref;
-  double range, rangec;
-  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
-                                /*        of floating point numbers - needed   */
-		                /*        on some platforms (eg vpp700, linux) */
-  extern const double _pow2tab[158];
-  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
-
-  if ( isec2 )
-    {
-      /* If section 2 is present, it says if data is spherical harmonic */
-
-      if ( isec2[0] == 50 || isec2[0] == 60 || 
-	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
-
-      if ( lspherc )
-	isec4[2] = 128;
-      else
-	isec4[2] = 0;
-    }
-  else
-    {
-      /* Section 4 says if it's spherical harmonic data.. */
-
-      lspherc = ( isec4[2] == 128 );
-    }
-
-  /* Complex packing supported for spherical harmonics. */
-
-  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
-             ( lspherc && isec2 && ( isec2[5] == 2 ) );
-
-  /* Check input specification is consistent */
-
-  if ( lcomplex && isec2 )
-    {
-      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
-	{
-	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
-	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
-	  return (807);
-	}
-      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
-	{
-	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
-	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
-	  return (807);
-        }
-      else if ( lcomplex )
-	{
-	  /*
-	    Truncation of full spectrum, which is supposed triangular,
-	    has to be diagnosed. Define also sub-set truncation.
-	  */
-	  isubset = isec4[17];
-	  /* When encoding, use the total number of data. */
-	  itemp   = isec4[0];
-	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
-	}
-    }
-
-  if ( decscale )
-    {
-      double scale = pow(10.0, (double) decscale);
-      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
-    }
-
-  if ( lspherc )
+  if( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
     {
-      if ( lcomplex )
-	{
-	  int jup, ioff;
-	  jup  = isubset;
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
-	  PackStart = ioff;
-	  Flag = 192;
-	}
-      else
-	{
-	  bds_ext = 4;
-	  PackStart = 1;
-	  Flag = 128;
-	}
+      perror(__func__);
+      nwrite = -1;
     }
 
-  *datstart = bds_head + bds_ext;
+  return ((int) nwrite);
+}
 
-  nbpv = numBits = ISEC4_NumBits;
 
-  if ( lspherc && lcomplex )
-    {
-      int pcStart, pcScale;
-      pcStart = isubset;
-      pcScale = isec4[16];
-      scaleComplex(data, pcStart, pcScale, itrunc, 0);
-      gatherComplex(data, pcStart, itrunc, datasize);
-    }
+int gribrec_len(int b1, int b2, int b3)
+{
+  int gribsize;
 
-  fmin = fmax = data[PackStart];
+  gribsize = (1-(int) ((unsigned) (b1&128) >> 6)) * (int) (((b1&127) << 16)+(b2<<8) + b3);
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( gribsize < 0 ) gribsize *= (-120);
 
-  minmax_val(data+PackStart, datasize-PackStart, &fmin, &fmax);
+  return (gribsize);
+}
 
-  zref = fmin;
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 
 
-  if ( CGRIBEX_Const && !lspherc )
-    {
-      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
-    }
+FILE *grprsm = NULL;
+double fref;
+double fmaxval;
+int nfref;
+int nfmaxval;
+int nrnd;
+int ndbg;
+int nvck;
+int nonoff;
+int noabort;
+int num2ok;
+int next2o;
+int nloc2o;
+int nsubce;
+int grib_calendar = -1;
 
 
-  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
-  if ( (blockLength%2) == 1 ) blockLength++;
+void gribSetCalendar(int calendar)
+{
+  grib_calendar = calendar;
+}
 
-  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
 
-  Flag += unused_bits;
+void grsdef(void)
+{
+  /*
+C---->
+C**** GRSDEF - Initial (default) setting of common area variables
+C              for GRIBEX package.
+C
+C     Purpose.
+C     --------
+C
+C     Sets initial values for common area variables for all
+C     routines of GRIBEX package, if not already done.
+C
+C**   Interface.
+C     ----------
+C
+C     CALL GRSDEF
+C
+C     Input Parameters.
+C     -----------------
+C
+C     None.
+C
+C     Output Parameters.
+C     ------------------
+C
+C     None.
+C
+C     Method.
+C     -------
+C
+C     Self-explanatory.
+C
+C     Externals.
+C     ----------
+C
+C     None.
+C
+C     Reference.
+C     ----------
+C
+C     See subroutine GRIBEX.
+C
+C     Comments.
+C     ---------
+C
+C     None
+C
+C     Author.
+C     -------
+C
+C     J. Clochard, Meteo France, for ECMWF - March 1998.
+C
+C     Modifications.
+C     --------------
+C
+C     J. Clochard, Meteo France, for ECMWF - June 1999.
+C     Add variable NSUBCE.
+C     Use a static variable to determine if initialisation has already
+C     been done. NUSER removed .
+C     Reverse defaults for NEXT2O and NLOC2O, for consistency with
+C     version 13.023 of software .
+C
+  */
+  /*
+C     ----------------------------------------------------------------
+C*    Section 0 . Definition of variables.
+C     ----------------------------------------------------------------
+  */
+  char *envString;
+  char *env_stream;
+  static int lfirst = TRUE;
+  extern int CGRIBEX_Const;
 
+  if ( ! lfirst ) return;
 
   /*
-    Adjust number of bits per value if full integer length to
-    avoid hitting most significant bit (sign bit).
+    ----------------------------------------------------------------
+    Section 1 . Set values, conditionally.
+    ----------------------------------------------------------------
   */
-  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
   /*
-    Calculate the binary scaling factor to spread the range of
-    values over the number of bits per value.
-    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
-    as a guideline).           
+    Common area variables have not been set. Set them.
+    
+    User supplied reference value.
   */
-  range = fabs(fmax - fmin);
-
-  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  fref   = 0.0;
   /*
-    Have to allow tolerance in comparisons on some platforms
-    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
-    to avoid clipping ranges which are a power of 2.
+    Reference value supplied by user flag. Set to off.
   */
-  if ( range <= jpepsln )
-    {
-      binscale = 0;
-    }
-  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
-    {
-      binscale = 0;
-    }
-  else if ( fabs(range-1.0) <= jpepsln )
-    {
-      binscale = 1 - nbpv;
-    }
-  else if ( range > 1.0 )
+  nfref  = 0;
+  /*
+    User supplied maximum value.
+  */
+  fmaxval   = 0.0;
+  /*
+    Maximum value supplied by user flag. Set to off.
+  */
+  nfmaxval  = 0;
+  /*
+    Set rounding to 120 bytes on.
+  */
+  nrnd   = 1;
+  /*
+    Set GRIB calendar.
+  */
+  if ( grib_calendar == -1 )
     {
-      rangec = range + jpepsln;
-      for ( jloop = 1; jloop < 128; jloop++ )
-	{
-	  if ( _pow2tab[jloop] > rangec ) break;
-	}
-      if ( jloop == 128 )
-	{
-	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
-	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
-	  return (707);
-	}
-      else
+      grib_calendar = CALENDAR_PROLEPTIC;
+  
+      envString = getenv("GRIB_CALENDAR");
+      if ( envString )
 	{
-	  binscale = jloop - nbpv;
+	  if      ( strncmp(envString, "standard", 8) == 0 )
+	    grib_calendar = CALENDAR_STANDARD;
+	  else if ( strncmp(envString, "proleptic", 9) == 0 )
+	    grib_calendar = CALENDAR_PROLEPTIC;
+	  else if ( strncmp(envString, "360days", 7) == 0 )
+	    grib_calendar = CALENDAR_360DAYS;
+	  else if ( strncmp(envString, "365days", 7) == 0 )
+	    grib_calendar = CALENDAR_365DAYS;
+	  else if ( strncmp(envString, "366days", 7) == 0 )
+	    grib_calendar = CALENDAR_366DAYS;
+	  else if ( strncmp(envString, "none", 4) == 0 )
+	    grib_calendar = CALENDAR_NONE;
 	}
     }
-  else
+  /*
+    Set debug print off.
+  */
+  ndbg   = 0;
+  
+  envString = getenv("GRIBEX_DEBUG");
+  if ( envString != NULL )
     {
-      rangec = range - jpepsln;
-      for ( jloop = 1; jloop < 127; jloop++ )
-	{
-	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
-	}
-      if ( jloop == 127 )
-	{
-	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
-	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
-	  return (707);
-	}
+      if ( !strncmp(envString, "ON", 2) )
+        ndbg = 1;
+      else if( *envString == '1')
+        ndbg = 1;
+      else if( *envString == '2')
+        ndbg = 2;
       else
-	{
-	  binscale = 1 - jloop - nbpv;
-	}
+        ndbg = 0;
+    }
+  /*
+    Set GRIBEX compatibility mode.
+  */
+  envString = getenv("GRIB_GRIBEX_MODE_ON");
+  if ( envString != NULL )
+    {
+      if ( atoi(envString) == 1 ) CGRIBEX_Const = 0;
     }
 
-  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
-  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
-
-  if ( binscale != 0 )
+  /*
+    Set GRIB value checking on.
+  */
+  nvck   = 1;
+  
+  envString = getenv("GRIBEX_CHECK");
+  if ( envString )
     {
-      if ( binscale < 0 )
-	{
-	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
-	}
+      if ( !strncmp(envString, "OFF", 3) )
+        nvck = 0;
       else
-	{
-	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
-	}
-
-      if ( binscale < 0 ) factor =     intpow2(-binscale);
-      else                factor = 1.0/intpow2( binscale);
+        nvck = 1;
     }
-
-  ref2ibm(&zref, BitsPerInt);
-
-  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
-  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
-  if ( binscale < 0 ) binscale = 32768 - binscale;
-  Put2Byte(binscale);         /*  4-5 Scale factor             */
-  Put1Real(zref);             /*  6-9 Reference value          */
-  Put1Byte(nbpv);             /*   10 Packing size             */
-
-  if ( lspherc )
+  /*
+    See if output stream needs changing
+  */
+  grprsm = stdout;
+  env_stream = getenv("GRPRS_STREAM");
+  if ( env_stream )
     {
-      if ( lcomplex )
+      if ( isdigit((int) env_stream[0]) )
 	{
-	  int jup = isubset;
-	  int ioff = z + bds_ext;
-	  if ( ioff > 0xFFFF ) ioff = 0;
-	  Put2Byte(ioff);
-	  Put2Int(isec4[16]);
-	  Put1Byte(jup);
-	  Put1Byte(jup);
-	  Put1Byte(jup);
-	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real(data[i]);
+	  int unit;
+	  unit = atoi(env_stream);
+	  if ( unit < 1 || unit > 99 )
+	    Warning("Invalid number for GRPRS_STREAM: %d", unit);
+	  else if ( unit == 2 )
+	    grprsm = stderr;
+	  else if ( unit == 6 )
+	    grprsm = stdout;
+	  else
+	    {
+	      char filename[] = "unit.00";
+	      sprintf(filename, "%2.2d", unit);
+	      grprsm = fopen(filename, "w");
+	      if ( ! grprsm )
+		SysError("GRPRS_STREAM = %d", unit);
+	    }
 	}
       else
 	{
-	  Put1Real(data[0]);
+	  if ( env_stream[0] )
+	    {
+	      grprsm = fopen(env_stream, "w");
+	      if ( ! grprsm )
+		SysError("GRPRS_STREAM = %s", env_stream);
+	    }
 	}
     }
+  /*
+    Set P factor switch to default, user supplies the P factor.
+  */
+  nonoff = 0;
+  /*
+    Set abort flag to NO abort
+  */
+  noabort = 1;
+  /*
+    Mark common area values set by user.
+  */
+  lfirst = FALSE;
+  /*
+    Exhaustive use of all possible second-order packing methods
+    for HOPER='K'. Set to off.
+  */
+  num2ok  = 0;
+  /*
+    Use of extended second-order packing methods for grid-point
+    encoding (HOPER='C' and 'K'). Set to on.
+  */
+  next2o  = 1;
+  /*
+    Use of non-local second-order packing methods for grid-point
+    encoding (HOPER='C' and 'K'). Set to on.
+  */
+  nloc2o  = 1;
+  /*
+    Use of (all valid) sub-centre values for ECMWF fields encoding .
+    encoding. Set to off.
+  */
+  nsubce  = 0;
+}
 
-  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
+/* pack 8-bit bytes from 64-bit words to a packed buffer */
+/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (unsigned char) up[i]; */
 
-#if  defined  (_ARCH_PWR6)
-  encode_double_array_unrolled(nbpv, PackStart, datasize, lGrib, data, zref, factor, &z);
+long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc)
+{
+#if defined (CRAY)
+  (void) _pack(up, cp, bc, tc);
 #else
-  encode_double_array_byte    (nbpv, PackStart, datasize, lGrib, data, zref, factor, &z);
-#endif
+  U_BYTEORDER;
+  unsigned char *cp0;
+  unsigned INT64 upi, *up0, *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
+  long head, trail, inner, i, j;
+  long ipack = sizeof(INT64);
+  
+  /* Bytes until first word boundary in destination buffer */
 
-  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
 
-  *gribLen = z;
+  inner = bc - head;
 
-  return (0);
-}
+  /* Trailing bytes which do not make a full word */
 
+  trail = inner & (ipack-1);
 
-void gribEncode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
-		int kleng, int *kword, int efunc, int *kret)
-{
-  long gribLen = 0; /* Counter of GRIB length for output */
-  long isLen, pdsLen;
-  GRIBPACK *lpds;
-  unsigned char *CGrib;
-  long fsec4size = 0;
-  int numBytes;
-  int bmsIncluded;
-  size_t len;
-  GRIBPACK *lGrib;
-  long datstart, datsize, bdsstart;
-  int status = 0;
+  /* Number of bytes/words to be processed in fast loop */
 
-  grsdef();
+  inner -= trail;
+  inner /= ipack;
 
-  CGrib = (unsigned char *) kgrib;
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+  ip4 = ip0 + 4;
+  ip5 = ip0 + 5;
+  ip6 = ip0 + 6;
+  ip7 = ip0 + 7;
 
-  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+  up0 = (unsigned INT64 *) (cp + head);
 
-  /* set max header len */
-  len = 16384;
+  /* Here we should process any bytes until the first word boundary 
+   * of our destination buffer 
+   * That code is missing so far  because our output buffer is 
+   * word aligned by FORTRAN 
+   */
 
-  /* add data len */
-  numBytes = (ISEC4_NumBits+7)>>3;
+  j = 0;
 
-  len += numBytes*klenp;
-
-  /* add bitmap len */
-  if ( bmsIncluded ) len += (klenp+7)>>3;
-
-#if defined (VECTORCODE)
-  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
-  if ( lGrib == NULL ) SysError("No Memory!");
-#else
-  lGrib = CGrib;
-#endif
-
-  isLen = 8;
-  encodeIS(lGrib, &gribLen);
-  lpds = &lGrib[isLen];
-  pdsLen = getPdsLen(isec1);
-
-  encodePDS(lpds, pdsLen,  isec1);
-  gribLen += pdsLen;
-  /*
-  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
-    {
-      static int lwarn_cplx = TRUE;
-
-      if ( lwarn_cplx )
-	Message("Complex packing of spectral data unsupported, using simple packing!");
-
-      isec2[5] = 1;
-      isec4[3] = 0;
-
-      lwarn_cplx = FALSE;
-    }
-  */
-  encodeGDS(lGrib, &gribLen, isec2, fsec2);
-  /*
-    ----------------------------------------------------------------
-    BMS Bit-Map Section Section (Section 3)
-    ----------------------------------------------------------------
-  */ 
-  if ( bmsIncluded )
+  if ( IS_BIGENDIAN() )
     {
-      encodeBMS(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  upi =             (   ip0[j]          << 56 ) 
+	                 |  ( ( ip1[j] & 0xFF ) << 48 )
+	                 |  ( ( ip2[j] & 0xFF ) << 40 )
+	                 |  ( ( ip3[j] & 0xFF ) << 32 )
+	                 |  ( ( ip4[j] & 0xFF ) << 24 ) ;
+	  up0[i] = upi   |  ( ( ip5[j] & 0xFF ) << 16 )
+	                 |  ( ( ip6[j] & 0xFF ) <<  8 )
+	                 |    ( ip7[j] & 0xFF ) ;
+	  j += ipack;
+	}
     }
   else
     {
-      fsec4size = ISEC4_NumValues;
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  upi =             (   ip7[j]          << 56 ) 
+	                 |  ( ( ip6[j] & 0xFF ) << 48 )
+                         |  ( ( ip5[j] & 0xFF ) << 40 )
+                         |  ( ( ip4[j] & 0xFF ) << 32 )
+                         |  ( ( ip3[j] & 0xFF ) << 24 ) ;
+	  up0[i] = upi   |  ( ( ip2[j] & 0xFF ) << 16 )
+                         |  ( ( ip1[j] & 0xFF ) <<  8 )
+                         |    ( ip0[j] & 0xFF ) ;
+	  j += ipack;
+	}
     }
 
-  bdsstart = gribLen;
-  status = encodeBDS(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
-		     isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
-  if ( status )
+  cp0 = (unsigned char *) ( up0 + inner );
+  if ( trail > 0 )
     {
-      *kret = status;
-      return;
+      up0[inner] = 0;
+      for ( i = 0 ; i < trail ; i ++ )
+	{
+	  *cp0 = (unsigned char) ip0[ipack*inner+i];
+	  cp0++;
+	}
     }
 
-  encodeES(lGrib, &gribLen, bdsstart);
-
-  if ( (size_t) gribLen > kleng*sizeof(int) )
-    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
-
-#if defined (VECTORCODE)
-  if ( (size_t) gribLen > len )
-    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
-
-  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
-
-  free(lGrib);
+  if ( tc != -1 )
+    {
+      bc++;
+      *cp0 = (unsigned char) tc;
+    }
 #endif
+  return (bc);
+}
 
-  ISEC0_GRIB_Len     = gribLen;
-  ISEC0_GRIB_Version = 1;
-
-  *kword = gribLen / sizeof(int);
-  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+/* unpack 8-bit bytes from a packed buffer with 64-bit words */
+/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT64) cp[i]; */
 
-  *kret = status;
-}
-#include <string.h>
+long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc)
+{
+  U_BYTEORDER;
+  const unsigned char *cp0;
+  unsigned INT64 *up0;
+  unsigned INT64 *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
+  long head, trail, inner, i, j;
+  long offset;
+  long ipack = sizeof(INT64);
 
+  UNUSED(tc);
 
+  /* Bytes until first word boundary in source buffer */
 
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
+  if ( head > bc ) head = bc;
 
+  inner = bc - head;
 
-int gribVersion(unsigned char *is, size_t buffersize)
-{
-  if ( buffersize < 8 )
-    Error("Buffer too small (current size %d)!", (int) buffersize);
+  /* Trailing bytes which do not make a full word */
+ 
+  trail = inner & (ipack-1);
+ 
+  /* Number of bytes/words to be processed in fast loop */
 
-  return (GRIB_EDITION(is));
-}
+  inner -= trail;
+  inner /= ipack;
 
-static 
-double GET_Real(unsigned char *grib)
-{
-  int iexp, imant;
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+  ip4 = ip0 + 4;
+  ip5 = ip0 + 5;
+  ip6 = ip0 + 6;
+  ip7 = ip0 + 7;
 
-  iexp  = GET_UINT1(grib[0]);
-  imant = GET_UINT3(grib[1], grib[2], grib[3]);
+  up0 = (unsigned INT64 *) (cp + head);
 
-  return (decfp2(iexp, imant));
-}
+  /* Process any bytes until the first word boundary 
+   * of our source buffer 
+   */
+  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT64) cp[i];
 
-static 
-int decodeIS(unsigned char *is, int *isec0, int *iret)
-{
-  int isLen = 0;
-  int grib1offset;
-  int lgrib = FALSE, lbudg = FALSE, ltide = FALSE;
+  j = 0;
 
-  /*
-    Octets 1 - 4 : The letters G R I B.
-    Four 8 bit fields.
-  */
-  /*
-    Check letters -> GRIB, BUDG or TIDE.
-  */
-  /*
-    Check that 'GRIB' is found where expected.
-  */
-  if ( GRIB_START(is) ) lgrib = TRUE;
-  /*
-    ECMWF pseudo-grib data uses 'BUDG' and 'TIDE'.
-  */
-  if ( BUDG_START(is) ) lbudg = TRUE;
-  if ( TIDE_START(is) ) ltide = TRUE;
-  /*
-    Data is not GRIB or pseudo-grib.
-  */
-  if ( lgrib == FALSE && lbudg == FALSE && ltide == FALSE )
+  if ( IS_BIGENDIAN() )
     {
-      *iret = 305;
-      gprintf(__func__, "Input data is not GRIB or pseudo-grib.");
-      gprintf(__func__, "Return code = %d", *iret);
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip0[j] = (up0[i] >> 56) & 0xFF;
+	  ip1[j] = (up0[i] >> 48) & 0xFF;
+	  ip2[j] = (up0[i] >> 40) & 0xFF;
+	  ip3[j] = (up0[i] >> 32) & 0xFF;
+	  ip4[j] = (up0[i] >> 24) & 0xFF;
+	  ip5[j] = (up0[i] >> 16) & 0xFF;
+	  ip6[j] = (up0[i] >>  8) & 0xFF;
+	  ip7[j] = (up0[i])       & 0xFF;
+
+	  j += ipack;
+	}
     }
-  if ( lbudg == TRUE || ltide == TRUE )
+  else
     {
-      *iret = 305;
-      gprintf(__func__, "Pseudo-grib data unsupported.");
-      gprintf(__func__, "Return code = %d", *iret);
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip7[j] = (up0[i] >> 56) & 0xFF;
+	  ip6[j] = (up0[i] >> 48) & 0xFF;
+	  ip5[j] = (up0[i] >> 40) & 0xFF;
+	  ip4[j] = (up0[i] >> 32) & 0xFF;
+	  ip3[j] = (up0[i] >> 24) & 0xFF;
+	  ip2[j] = (up0[i] >> 16) & 0xFF;
+	  ip1[j] = (up0[i] >>  8) & 0xFF;
+	  ip0[j] = (up0[i])       & 0xFF;
+
+	  j += ipack;
+	}
     }
 
+  if ( trail > 0 )
+    {
+      offset = head + ipack*inner;
+      cp0 = cp + offset;
+      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT64) cp0[i];
+    }
   /*
-    Octets 5 - 7 : Length of message.
-    One 24 bit field.
-  */
-  ISEC0_GRIB_Len = GRIB1_SECLEN(is);
-  /*
-    Octet 8 : GRIB Edition Number.
-    One 8 bit field.
+  if ( tc != -1 ) {
+    bc++;
+    *cp0 = (unsigned char) tc;
+  }
   */
-  ISEC0_GRIB_Version = GRIB_EDITION(is);
+  return (bc);
+}
 
-  if ( ISEC0_GRIB_Version > 1 )
-    Error("GRIB version %d unsupported!", ISEC0_GRIB_Version);
-
-  grib1offset = ISEC0_GRIB_Version * 4;
-
-  isLen = 4 + grib1offset;
-
-  return (isLen);
-}
-
-static 
-void decodePDS_ECMWF_local_Extension_1(unsigned char *pds, int *isec1)
-{
-  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier       */
-  isec1[37] = GET_UINT1(pds[41]);         /* Class                      */
-  isec1[38] = GET_UINT1(pds[42]);         /* Type                       */
-  isec1[39] = GET_UINT2(pds[43],pds[44]); /* Stream                     */
-  /* isec1[40] = GET_UINT4(pds[45],pds[46],pds[47],pds[48]); */
-  memcpy((char*) &isec1[40], &pds[45], 4);
-  isec1[41] = GET_UINT1(pds[49]);         /* Forecast number            */
-  isec1[42] = GET_UINT1(pds[50]);         /* Total number of forecasts  */
-}
+/* pack 8-bit bytes from 32-bit words to a packed buffer */
+/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (char) up[i]; */
 
-static 
-void decodePDS_DWD_local_Extension_254(unsigned char *pds, int *isec1)
+#if  defined  (INT32)
+long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
 {
-  long i;
-  int isvn;
-
-  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
-  for ( i = 0; i < 11; i++ ) 
-    { 
-      isec1[37+i] =  GET_UINT1(pds[41+i]);
-    } 
-
-  isvn = GET_UINT2(pds[52],pds[53]);
+  U_BYTEORDER;
+  unsigned char *cp0;
+  unsigned INT32 *up0, *ip0, *ip1, *ip2, *ip3;
+  long head, trail, inner, i, j;
+  long ipack = sizeof(INT32);
   
-  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
-  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
-
-}
+  /* Bytes until first word boundary in destination buffer */
 
-static 
-void decodePDS_DWD_local_Extension_253(unsigned char *pds, int *isec1)
-{
-  long i;
-  int isvn;
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
 
-  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
-  for ( i = 0; i < 11; i++ ) 
-    { 
-      isec1[37+i] =  GET_UINT1(pds[41+i]);
-    } 
+  inner = bc - head;
 
-  isvn = GET_UINT2(pds[52],pds[53]);
-  
-  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
-  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
-  isec1[50] =  GET_UINT1(pds[54]);         /* User id, specified by table          */
-  isec1[51] =  GET_UINT2(pds[55],pds[56]); /* Experiment identifier                */
-  isec1[52] =  GET_UINT2(pds[57],pds[58]); /* Ensemble identification by table     */
-  isec1[53] =  GET_UINT2(pds[59],pds[60]); /* Number of ensemble members           */
-  isec1[54] =  GET_UINT2(pds[61],pds[62]); /* Actual number of ensemble member     */
-  isec1[55] =  GET_UINT1(pds[63]);         /* Model major version number           */
-  isec1[56] =  GET_UINT1(pds[64]);         /* Model minor version number           */
+  /* Trailing bytes which do not make a full word */
 
-}
+  trail = inner & (ipack-1);
 
-static 
-void decodePDS_MPIM_local_Extension_1(unsigned char *pds, int *isec1)
-{
-  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier            */
-  isec1[37] = GET_UINT1(pds[41]);         /* type of ensemble forecast       */
-  isec1[38] = GET_UINT2(pds[42],pds[43]); /* individual ensemble member      */
-  isec1[39] = GET_UINT2(pds[44],pds[45]); /* number of forecasts in ensemble */
-}
+  /* Number of bytes/words to be processed in fast loop */
 
-static 
-int decodePDS(unsigned char *pds, int *isec0, int *isec1)
-{
-  int pdsLen;
+  inner -= trail;
+  inner /= ipack;
 
-  pdsLen = PDS_Len;
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
 
-  ISEC1_CodeTable      = PDS_CodeTable;
-  ISEC1_CenterID       = PDS_CenterID;
-  ISEC1_ModelID        = PDS_ModelID;
-  ISEC1_GridDefinition = PDS_GridDefinition;
-  ISEC1_Sec2Or3Flag    = PDS_Sec2Or3Flag;
-  ISEC1_Parameter      = PDS_Parameter;
-  ISEC1_LevelType      = PDS_LevelType;
+  up0 = (unsigned INT32 *) (cp + head);
 
-  if ( (ISEC1_LevelType !=  20) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_99)        && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)  && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)  && 
-       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)    && 
-       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)     && 
-       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)    && 
-       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) && 
-       (ISEC1_LevelType != 115) && 
-       (ISEC1_LevelType != 117) && 
-       (ISEC1_LevelType != 125) && 
-       (ISEC1_LevelType != 127) && 
-       (ISEC1_LevelType != GRIB1_LTYPE_SEADEPTH)  && 
-       (ISEC1_LevelType != 210) )
-    {
-      ISEC1_Level1 = PDS_Level1;
-      ISEC1_Level2 = PDS_Level2;
-    }
-  else
-    {
-      ISEC1_Level1 = PDS_Level;
-      ISEC1_Level2 = 0;
-    }
+  /* Here we should process any bytes until the first word boundary 
+   * of our destination buffer 
+   * That code is missing so far  because our output buffer is 
+   * word aligned by FORTRAN 
+   */
 
-  /* ISEC1_Year        = PDS_Year; */
-  ISEC1_Month          = PDS_Month;
-  ISEC1_Day            = PDS_Day;
-  ISEC1_Hour           = PDS_Hour;
-  ISEC1_Minute         = PDS_Minute;
-  ISEC1_TimeUnit       = PDS_TimeUnit;
-  ISEC1_TimePeriod1    = PDS_TimePeriod1;
-  ISEC1_TimePeriod2    = PDS_TimePeriod2;
-  ISEC1_TimeRange      = PDS_TimeRange;
-  ISEC1_AvgNum         = PDS_AvgNum;
-  ISEC1_AvgMiss        = PDS_AvgMiss;
+  j = 0;
 
-  if ( ISEC0_GRIB_Version == 1 )
+  if ( IS_BIGENDIAN() )
     {
-      ISEC1_Year           = PDS_Year;
-      ISEC1_Century        = PDS_Century;
-      ISEC1_SubCenterID    = PDS_Subcenter;
-      ISEC1_DecScaleFactor = PDS_DecimalScale;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  up0[i] =          (   ip0[j]          << 24 ) 
+	                 |  ( ( ip1[j] & 0xFF ) << 16 )
+	                 |  ( ( ip2[j] & 0xFF ) <<  8 )
+	                 |    ( ip3[j] & 0xFF ) ;
+	  j += ipack;
+	}
     }
   else
     {
-      int year;
-      year                 = GET_UINT1(pds[12]);
-      if ( year <= 100 )
-	{
-	  ISEC1_Year       = year;
-	  ISEC1_Century    = 1;
-	}
-      else
+      for ( i = 0 ; i < inner ; i++ )
 	{
-	  ISEC1_Year       = year%100;
-	  ISEC1_Century    = 1 + (year-ISEC1_Year)/100;
+	  up0[i] =          (   ip3[j]          << 24 ) 
+	                 |  ( ( ip2[j] & 0xFF ) << 16 )
+                         |  ( ( ip1[j] & 0xFF ) <<  8 )
+                         |    ( ip0[j] & 0xFF ) ;
+	  j += ipack;
 	}
-      ISEC1_SubCenterID    = 0;
-      ISEC1_DecScaleFactor = 0;
-    }
-
-  if ( ISEC1_Year < 0 )
-    {
-      ISEC1_Year    = -ISEC1_Year;
-      ISEC1_Century = -ISEC1_Century;
     }
 
-  ISEC1_LocalFLag = 0;
-  if ( pdsLen > 28 )
+  cp0 = (unsigned char *) ( up0 + inner );
+  if ( trail > 0 )
     {
-      int localextlen;
-      localextlen = pdsLen-28;
-
-      if ( localextlen > 4000 )
+      up0[inner] = 0;
+      for ( i = 0 ; i < trail ; i ++ )
 	{
-	  Warning("PDS larger than 4000 bytes not supported!");
+	  *cp0 = (unsigned char) ip0[ipack*inner+i];
+	  cp0++;
 	}
-      else
-	{
-	  ISEC1_LocalFLag = 1;
+    }
 
-	  if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
-	    {
-	      if ( pds[40] == 254 ) 
-		{
-		  decodePDS_DWD_local_Extension_254(pds, isec1);
-		}
-	      else if ( pds[40] == 253 )
-		{ 
-		  decodePDS_DWD_local_Extension_253(pds, isec1);
-		}
-	    }
-	  else if ( (ISEC1_CenterID    == 98 && ISEC1_LocalFLag ==  1) ||
-		    (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag ==  1) ||
-		    (ISEC1_CenterID    ==  7 && ISEC1_SubCenterID == 98) )
-	    {
-	      if ( pds[40] == 1 )
-		decodePDS_ECMWF_local_Extension_1(pds, isec1);
-	    }
-	  else if ( ISEC1_CenterID    == 252 && ISEC1_LocalFLag ==  1 )
-	    {
-	      if ( pds[40] == 1 )
-		decodePDS_MPIM_local_Extension_1(pds, isec1);	      
-	    }
-	  else
-	    {
-	      long i;
-	      for ( i = 0; i < localextlen; i++ )
-		{
-		  isec1[24+i] = pds[28+i];
-		}
-	    }
-	}
+  if ( tc != -1 )
+    {
+      bc++;
+      *cp0 = (unsigned char) tc;
     }
 
-  return (pdsLen);
+  return (bc);
 }
+#endif
 
-static 
-int decodeGDS(unsigned char  *gds, int *isec0, int *isec2, double *fsec2, int *numGridVals, int dfunc)
+/* unpack 8-bit bytes from a packed buffer with 32-bit words */
+/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT32) cp[i]; */
+
+#if  defined  (INT32)
+long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
 {
-  /* int imisng = 0; */
-  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
-  int  locnv = 0, locnl;
-  int  jlenl;
-  long i;
-  int iexp, imant;
-  int ipvpl, ipl;
-  int gdsLen = 0;
-#if defined (VECTORCODE)
-  unsigned char *igrib;
-  GRIBPACK *lgrib = NULL;
-  size_t lGribLen = 0;
-#endif
+  U_BYTEORDER;
+  const unsigned char *cp0;
+  unsigned INT32 *up0;
+  unsigned INT32 *ip0, *ip1, *ip2, *ip3;
+  long head, trail, inner, i, j;
+  long offset;
+  long ipack = sizeof(INT32);
 
-  *numGridVals = 0;
+  UNUSED(tc);
 
-  memset(isec2, 0, 22*sizeof(int));
+  /* Bytes until first word boundary in source buffer */
 
-  gdsLen = GDS_Len;
+  head = ( (long) cp ) & (ipack-1);
+  if ( head != 0 ) head = ipack - head;
+  if ( head > bc ) head = bc;
 
-  ipvpl = GDS_PVPL;
-  if ( ipvpl == 0 ) ipvpl = 0xFF;
+  inner = bc - head;
 
-  if ( ipvpl != 0xFF )
-    { /* Either vct or reduced grid */
-      if ( GDS_NV != 0 )
-	{ /* we have vct */
-	  VertCoorTab = TRUE;
-	  ipl =  4*GDS_NV + ipvpl - 1;
-	  if ( ipl < gdsLen )
-	    {
-	      ReducedGrid = TRUE;
-	    }
-	}
-      else
-	{
-	  VertCoorTab = FALSE;
-	  ReducedGrid = TRUE;
-	}
-      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
-    }
+  /* Trailing bytes which do not make a full word */
  
-  if ( ISEC0_GRIB_Version == 0 )
-    {
-      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
-      else                   VertCoorTab = FALSE;
-    }
-  
-  if ( ReducedGrid )
-    {
-      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
-      jlenl = (gdsLen - locnl)  >> 1;
-      if ( jlenl == GDS_NumLat )
-	{
-	  *numGridVals = 0;
-	  ISEC2_Reduced = TRUE;
-	  for ( i = 0; i < jlenl; i++ )
-	    {
-	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
-	      *numGridVals += ISEC2_RowLon(i);
-	    }
-	}
-      else
-	{
-	  ReducedGrid = FALSE;
-	}
-    }
+  trail = inner & (ipack-1);
+ 
+  /* Number of bytes/words to be processed in fast loop */
 
-  ISEC2_GridType = GDS_GridType;
+  inner -= trail;
+  inner /= ipack;
 
-  /*
-     Gaussian grid definition.
-  */
-  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
-       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
-       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+  ip0 = up + head;
+  ip1 = ip0 + 1;
+  ip2 = ip0 + 2;
+  ip3 = ip0 + 3;
+
+  up0 = (unsigned INT32 *) (cp + head);
+
+  /* Process any bytes until the first word boundary 
+   * of our source buffer 
+   */
+  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT32) cp[i];
+
+  j = 0;
+
+  if ( IS_BIGENDIAN() )
     {
-      ISEC2_NumLat    = GDS_NumLat;
-      if ( ! ReducedGrid )
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+      for ( i = 0 ; i < inner ; i++ )
 	{
-	  ISEC2_NumLon = GDS_NumLon;
-	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-	}
-      ISEC2_FirstLat  = GDS_FirstLat;
-      ISEC2_FirstLon  = GDS_FirstLon;
-      ISEC2_ResFlag   = GDS_ResFlag;
-      ISEC2_LastLat   = GDS_LastLat;
-      ISEC2_LastLon   = GDS_LastLon;
-      ISEC2_LonIncr   = GDS_LonIncr;
+	  ip0[j] = (up0[i] >> 24) & 0xFF;
+	  ip1[j] = (up0[i] >> 16) & 0xFF;
+	  ip2[j] = (up0[i] >>  8) & 0xFF;
+	  ip3[j] = (up0[i])       & 0xFF;
 
-      ISEC2_NumPar    = GDS_NumPar;
-      ISEC2_ScanFlag  = GDS_ScanFlag;
-      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
-	{
-	  ISEC2_LatSP     = GDS_LatSP;
-	  ISEC2_LonSP     = GDS_LonSP;
-	  FSEC2_RotAngle  = GDS_RotAngle;
+	  j += ipack;
 	}
-      /*
-	if ( Lons != Longitudes || Lats != Latitudes )
-	Error("Latitude/Longitude Conflict");
-      */
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
-	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
-    {
-      /*
-      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
-      */
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
-	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
-    {
-      /*
-      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
-      */
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
-    {
-      ISEC2_NumLon    = GDS_NumLon;
-      ISEC2_NumLat    = GDS_NumLat;
-      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-      ISEC2_FirstLat  = GDS_FirstLat;
-      ISEC2_FirstLon  = GDS_FirstLon;
-      ISEC2_ResFlag   = GDS_ResFlag;
-      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
-      ISEC2_Lambert_dx    = GDS_Lambert_dx;
-      ISEC2_Lambert_dy    = GDS_Lambert_dy;
-      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
-      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
-      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
-      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
-      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
-      ISEC2_ScanFlag      = GDS_ScanFlag;
-    }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
-    {
-      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
-      ISEC2_PentaK  = GDS_PentaK;
-      ISEC2_PentaM  = GDS_PentaM;
-      ISEC2_RepType = GDS_RepType;
-      ISEC2_RepMode = GDS_RepMode;
-      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
-      isec2[ 6] = 0;
-      isec2[ 7] = 0;
-      isec2[ 8] = 0;
-      isec2[ 9] = 0;
-      isec2[10] = 0;
-      /*
-      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
-      */
     }
-  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+  else
     {
-      ISEC2_GME_NI2    = GDS_GME_NI2;
-      ISEC2_GME_NI3    = GDS_GME_NI3;
-      ISEC2_GME_ND     = GDS_GME_ND;
-      ISEC2_GME_NI     = GDS_GME_NI;
-      ISEC2_GME_AFlag  = GDS_GME_AFlag;
-      ISEC2_GME_LatPP  = GDS_GME_LatPP;
-      ISEC2_GME_LonPP  = GDS_GME_LonPP;
-      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
-      ISEC2_GME_BFlag  = GDS_GME_BFlag;
-      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
-      /*
-      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
-      */
+      for ( i = 0 ; i < inner ; i++ )
+	{
+	  ip3[j] = (up0[i] >> 24) & 0xFF;
+	  ip2[j] = (up0[i] >> 16) & 0xFF;
+	  ip1[j] = (up0[i] >>  8) & 0xFF;
+	  ip0[j] = (up0[i])       & 0xFF;
+
+	  j += ipack;
+	}
     }
-  else
+
+  if ( trail > 0 )
     {
-      ISEC2_NumLon = GDS_NumLon;
-      ISEC2_NumLat = GDS_NumLat;
-      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
-      Message("Gridtype %d unsupported", ISEC2_GridType);
+      offset = head + ipack*inner;
+      cp0 = cp + offset;
+      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT32) cp0[i];
     }
+  /*
+  if ( tc != -1 ) {
+    bc++;
+    *cp0 = (unsigned char) tc;
+  }
+  */
 
-  /*    vertical coordinate parameters for hybrid levels.     */
-  /*    get number of vertical coordinate parameters, if any. */
+  return (bc);
+}
+#endif
+#include <stdio.h>
 
-  ISEC2_NumVCP = 0;
+void prtbin(int kin, int knbit, int *kout, int *kerr)
+{
+  /*
 
-  isec2[17] = 0;
-  isec2[18] = 0;
+    Produces a decimal number with ones and zeroes
+    corresponding to the ones and zeroes of the input
+    binary number.
+    eg input number 1011 binary, output number 1011 decimal.
 
-  if ( VertCoorTab == TRUE )
-    {
-      if ( ISEC0_GRIB_Version  == 0 )
-	{
-	  locnv = 32;
-	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
-	}
-      else
-	{
-	  locnv = GDS_PVPL - 1;
-	  ISEC2_NumVCP = GDS_NV;
-	}
-#if defined (SX)
-      lGribLen = 4*ISEC2_NumVCP;	      
-      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
 
-      igrib = &gds[locnv];
-      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
-      for ( i = 0; i < ISEC2_NumVCP; i++ )
-	{
-	  iexp   = (lgrib[4*i  ]);
-	  imant  =((lgrib[4*i+1]) << 16) +
-	          ((lgrib[4*i+2]) <<  8) +
-	           (lgrib[4*i+3]);
-	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
-	}
+    Input Parameters:
+    
+       kin   - Integer variable containing binary number.
 
-      free(lgrib);
-#else
-      for ( i = 0; i < ISEC2_NumVCP; i++ )
-	{
-	  iexp   = (gds[locnv+4*i  ]);
-	  imant  =((gds[locnv+4*i+1]) << 16) +
-	          ((gds[locnv+4*i+2]) <<  8) +
-	           (gds[locnv+4*i+3]);
-	  fsec2[10+i] = decfp2(iexp,imant);
-	}
-#endif
-    }
+       knbit - Number of bits in binary number.
 
-  return (gdsLen);
-}
+    Output Parameters:
 
-static
-int decodeBDS(int decscale, unsigned char *bds, int *isec2, int *isec4, 
-	      double *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
-{
-  unsigned char *igrib;
-  int lspherc = FALSE, lcomplex = FALSE;
-  int lcompress;
-  int jup, kup, mup;
-  int locnd;
-  long jlend;
-  long i;
-  int bds_flag, jscale, imiss;
-  int bds_ubits;
-  int ioff = 0;
-  int iexp, imant;
-  int zoff;
-  int bds_head = 11;
-  double fmin = 0., zscale = 0.;
-  double *fpdata = fsec4;
-  int bdsLen;
-  extern int CGRIBEX_Fix_ZSE;
+       kout  - Integer variable containing decimal value
+               with ones and zeroes corresponding to those of
+	       the input binary number.
 
-  *iret = 0;
-  igrib = bds;
+       kerr  - 0, If no error.
+               1, Number of bits in binary number exceeds
+	          maximum allowed or is less than 1.
 
-  memset(isec4, 0, 42*sizeof(int));
 
-  /* get length of binary data block. */
+    Converted from EMOS routine PRTBIN.
+
+       Uwe Schulzweida   MPIfM   01/04/2001
+
+  */
+  int idec;
+  int ik;
+  int itemp;
+  int j;
 
-  bdsLen = BDS_Len;
   /*
-    If a very large product, the section 4 length field holds
-    the number of bytes in the product after section 4 upto
-    the end of the padding bytes.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
+    Check length of binary number to ensure decimal number
+    generated will fit in the computer word - in this case will
+    it fit in a Cray 48 bit integer?
   */
-  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
+  if ( knbit < 1 || knbit > 14 )
+    {
+      *kerr = 1;
+      printf(" prtbin : Error in binary number length - %3d bits.\n", knbit);
+      return;
+    }
+  else
+    *kerr = 0;
+  /*
+    -----------------------------------------------------------------
+    Section 1. Generate required number.
+    -----------------------------------------------------------------
+  */
+  *kout = 0;
+  ik    = kin;
+  idec  = 1;
 
-  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
+  for ( j = 0; j < knbit; j++ )
+    {
+      itemp = ik - ( (ik/2)*2 );
+      *kout = (*kout) + itemp * idec;
+      ik    = ik / 2;
+      idec  = idec * 10;
+    }
 
-  bds_flag = BDS_Flag;
+  return;
+}
 
-  /* 0------- grid point           */
-  /* 1------- spherical harmonics  */
 
-  lspherc = bds_flag >> 7;
+void ref2ibm(double *pref, int kbits)
+{
+  /*
 
-  if ( lspherc ) isec4[2] = 128;
-  else           isec4[2] = 0;
+    Purpose:
+    --------
 
-  /* -0------  simple packing */
-  /* -1------ complex packing */
+    Code and check reference value in IBM format
 
-  lcomplex = (bds_flag >> 6)&1;
+    Input Parameters:
+    -----------------
 
-  if ( lcomplex ) isec4[3] = 64;
-  else            isec4[3] =  0;
+    pref       - Reference value
+    kbits      - Number of bits per computer word.
 
-  /* ---0---- No additional flags */
-  /* ---1---- No additional flags */
+    Output Parameters:
+    ------------------
 
-  lcompress = (bds_flag >> 4)&1; /* compress */
+    pref       - Reference value
 
-  if ( lcompress )
-    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
-  else
-    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+    Method:
+    -------
 
-  /* ----++++ number of unused bits at end of section) */
+    Codes in IBM format, then decides to ensure that reference 
+    value used for packing is not different from that stored
+    because of packing differences.
 
-  bds_ubits = bds_flag & 0xF;
-  
-  /* scale factor (2 bytes) */;
+    Externals.
+    ----------
 
-  jscale = BDS_BinScale;
+    confp3    - Encode into IBM floating point format.
+    decfp2    - Decode from IBM floating point format.
 
-  /* check for missing data indicators. */
+    Reference:
+    ----------
 
-  iexp  = bds[ 6];
-  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
+    None.
 
-  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
+    Comments:
+    --------
 
-  /* convert reference value and scale factor. */
+    None.
 
-  if ( ! (dfunc == 'J') )
-    if ( imiss == 0 )
-      {
-	fmin = BDS_RefValue;
-	
-	if ( jscale < 0 )
-	  zscale = 1.0/intpow2(-jscale);
-	else
-	  zscale = intpow2(jscale);
-      }
+    Author:
+    -------
 
-  /* get number of bits in each data value. */
+    J.D.Chambers     ECMWF      17:05:94
 
-  ISEC4_NumBits = BDS_NumBits;
+    Modifications:
+    --------------
 
-  /* octet number of start of packed data */
-  /* calculated from start of block 4 - 1 */
+    Uwe Schulzweida   MPIfM   01/04/2001
 
-  locnd = zoff + bds_head;
+    Convert to C from EMOS library version 130
 
-  /* if data is in spherical harmonic form, distinguish   */
-  /* between simple/complex packing (lcomplex = 0/1)      */
+  */
 
-  if ( lspherc )
-    {
-      if ( !lcomplex )
-	{
-	  /*    no unpacked binary data present */
+  static int itrnd;
+  static int kexp, kmant;
+  static double ztemp, zdumm;
+  extern int CGRIBEX_Debug;
 
-	  jup = kup = mup = 0;
+  /* ----------------------------------------------------------------- */
+  /*   Section 1. Convert to and from IBM format.                      */
+  /* ----------------------------------------------------------------- */
 
-	  /*    octet number of start of packed data */
-	  /*    calculated from start of block 4 - 1 */
+  /*  Convert floating point reference value to IBM representation. */
 
-	  ioff   = 1;
-	  locnd += 4*ioff;  /* RealCoef */
+  itrnd = 1;
+  zdumm = ztemp = *pref;
+  confp3(zdumm, &kexp, &kmant, kbits, itrnd);
 
-	  /*    get real (0,0) coefficient in grib format and     */
-	  /*    convert to floating point.                        */
+  if ( kexp == 0 && kmant == 0 ) return;
 
-	  if ( dfunc != 'J' )
-	    {
-	      if ( imiss ) *fpdata++ = 0.0;
-	      else         *fpdata++ = BDS_RealCoef;
-	    }
-	}
-      else /* complex packed spherical harmonics */
-	{
-	  isec4[15] = BDS_PackData;
-	  /*    scaling factor */
-	  isec4[16] = BDS_Power;
+  /*  Set reference value to that actually stored in the GRIB code. */
 
-	  /*    pentagonal resolution parameters of the */
-	  /*    unpacked section of data field          */
+  *pref = decfp2(kexp, kmant);
 
-	  jup = bds[zoff+15];
-	  kup = bds[zoff+16];
-	  mup = bds[zoff+17];
+  /*  If the nearest number which can be represented in */
+  /*  GRIB format is greater than the reference value,  */
+  /*  find the nearest number in GRIB format lower      */
+  /*  than the reference value.                         */
 
-	  isec4[zoff+17] = jup;
-	  isec4[zoff+18] = kup;
-	  isec4[zoff+19] = mup;
+  if ( ztemp < *pref )
+    {
+      /*  Convert floating point to GRIB representation */
+      /*  using truncation to ensure that the converted */
+      /*  number is smaller than the original one.      */
 
-	  /*    unpacked binary data */
+      itrnd = 0;
+      zdumm = *pref = ztemp;
+      confp3(zdumm, &kexp, &kmant, kbits, itrnd);
 
-	  locnd += 4; /* 2 + power */
-	  locnd += 3; /* j, k, m   */
-	  ioff   = (jup+1)*(jup+2);
+      /*  Set reference value to that stored in the GRIB code. */
 
-	  if ( dfunc != 'J' )
-	    for ( i = 0; i < ioff; i++ )
-	      {
-		iexp   = (bds[locnd+4*i  ]);
-		imant  =((bds[locnd+4*i+1]) << 16) +
-		        ((bds[locnd+4*i+2]) <<  8) +
-		         (bds[locnd+4*i+3]);
+      *pref = decfp2(kexp, kmant);
 
-		if ( imiss ) *fpdata++ = 0.0;
-		else         *fpdata++ = decfp2(iexp,imant);
-	      }
-	  
-	  locnd += 4*ioff;  /* RealCoef */
-	}
-    }
-  else
-    {
-      if ( lcomplex )
+      if ( ztemp < *pref )
 	{
-	  *iret = 1999;
-	  gprintf(__func__, " Second order packed grids unsupported!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
+	  if ( CGRIBEX_Debug )
+	    {
+	      Message("Reference value error.");
+	      Message("Notify Met.Applications Section.");
+	      Message("ZTEMP = ", ztemp);
+	      Message("PREF = ", pref);
+	    }
+	  *pref = ztemp;
 	}
     }
 
-  /* Decode data values to floating point and store in fsec4.  */
-  /* First calculate the number of data values.                */
-  /* Take into account that spherical harmonics can be packed  */
-  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
+  return;
+} /* ref2ibm */
+#include <string.h>
 
-  jlend = bdsLen - locnd;
 
-  if ( ISEC4_NumBits == 0 )
-    {
-      if ( jlend > 1 )
-	{
-	  *iret = 2001;
-	  gprintf(__func__, " Number of bits per data value = 0!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
-	}
+int correct_bdslen(int bdslen, long recsize, long gribpos)
+{
+  /*
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
+  return (bdslen);
+}
 
-      if ( numGridVals == 0 )
-	{
-	  *iret = 2002;
-	  gprintf(__func__, " Constant field unsupported for this grid type!");
-	  gprintf(__func__, " Return code =  %d", *iret);
-	  return (0);
-	}
 
-      jlend = numGridVals;
-      jlend -= ioff;
-    }
-  else
-    {
-      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
-    }
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
+		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize)
+{
+  unsigned char *pds, *gds, *bms, *bds;
+  unsigned char *bufpointer, *is, *section;
+  int gribversion, grib1offset;
+  long gribsize = 0, recsize;
+  int bdslen;
 
-  ISEC4_NumValues        = jlend + ioff;
-  ISEC4_NumNonMissValues = 0;
+  *gribrecsize = 0;
+  *pdsp = NULL;
+  *gdsp = NULL;
+  *bmsp = NULL;
+  *bdsp = NULL;
 
-  if ( lcompress )
+  section = gribbuffer;
+  is = gribbuffer;
+  if ( ! GRIB_START(section) )
     {
-      size_t len;
+      fprintf(stderr, "Wrong GRIB indicator section: found >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
+    }
 
-      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
-	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
-      else
-        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+  recsize = gribrec_len(section[4], section[5], section[6]);
 
-      ISEC4_NumValues = len*8/ISEC4_NumBits;
+  gribversion = GRIB_EDITION(section);
+  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
 
-      if ( lspherc )
-	{
-	  if ( lcomplex )
-	    ISEC4_NumValues += ioff;
-	  else
-	    ISEC4_NumValues++;
-	}
-    }
+  if ( gribversion == 1 )
+    grib1offset = 4;
+  else
+    grib1offset = 0;
 
-  if ( dfunc == 'J' ) return (bdsLen);
+  pds = is + 4 + grib1offset;
+  bufpointer = pds + PDS_Len;
+  gribsize += 4 + grib1offset + PDS_Len;
 
-  /* check length of output array. */
-  
-  if ( ISEC4_NumValues > fsec4len )
+  if ( PDS_HAS_GDS )
     {
-      *iret = 710;
-      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
-      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
-      gprintf(__func__, " Return code =  %d", *iret);
-      return (0);
+      gds = bufpointer;
+      bufpointer += GDS_Len;
+      gribsize += GDS_Len;
     }
-
-  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(double));
   else
     {
-      igrib += locnd;
-
-#if  defined  (_ARCH_PWR6)
-      decode_double_array_unrolled(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
-#else
-      decode_double_array_byte    (igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
-#endif
+      gds = NULL;
     }
 
-  if ( lspherc && lcomplex )
+  if ( PDS_HAS_BMS )
     {
-      int pcStart, pcScale;
-      pcStart = isec4[19];
-      pcScale = isec4[16];
-      scatterComplex(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
-      scaleComplex(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
+      bms = bufpointer;
+      bufpointer += BMS_Len;
+      gribsize += BMS_Len;
+    }
+  else
+    {
+      bms = NULL;
     }
 
-  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
-    if ( lspherc && !lcomplex )
-      {
-        /* 20100705: Fix ZeroShiftError - Edi Kirk */
-	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
-	  {
-	    double zserr = fsec4[1];
-	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
-	  }
-      }
+  bds = bufpointer;
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, gribsize);
+  bufpointer += bdslen;
+  gribsize += bdslen;
+  gribsize += 4;
 
-  if ( decscale )
+  *pdsp = pds;
+  *gdsp = gds;
+  *bmsp = bms;
+  *bdsp = bds;
+
+  *gribrecsize = gribsize;
+
+  if ( gribbufsize < gribsize )
     {
-      double scale = pow(10.0, (double)-decscale);
-      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+      fprintf(stderr, "Length of GRIB message is inconsistent (grib_buffer_size=%ld < grib_record_size=%ld)!\n", gribbufsize, gribsize);
+      return (1);
     }
 
-  return (bdsLen);
+  /* end section - "7777" in ascii */
+  if ( !GRIB_FIN(bufpointer) )
+    {
+      fprintf(stderr, "Missing GRIB end section: found >%c%c%c%c<\n",
+	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
+      return (-2);
+    }
+
+  return (0);
 }
 
 
-void gribDecode(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
-		double *fsec3, int *isec4, double *fsec4, int fsec4len, int *kgrib,
-		int kleng, int *kword, int dfunc, int *iret)
+int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
+		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
+		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp)
 {
-  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
-  int gribLen = 0;
-  int gdsIncluded = FALSE;
-  int bmsIncluded = FALSE;
-  int bitmapSize = 0;
-  int imaskSize = 0;
-  int ldebug = FALSE;
-  int llarge = FALSE, l_iorj = FALSE;
-  int lsect2 = FALSE, lsect3 = FALSE;
-  int numGridVals = 0;
-  static int lmissvalinfo = 1;
-
-  *iret = 0;
+  unsigned char *section;
+  long sec_len;
+  int sec_num;
+  int gribversion;
+  int i, msec;
+  long gribsize;
+  long grib_len = 0;
 
-  grsdef();
+  UNUSED(gribbufsize);
 
-  ISEC2_Reduced = FALSE;
+  *idsp = NULL;
+  *lusp = NULL;
+  *gdsp = NULL;
+  *pdsp = NULL;
+  *drsp = NULL;
+  *bmsp = NULL;
+  *bdsp = NULL;
 
-  /*
-    ----------------------------------------------------------------
-    IS Indicator Section (Section 0)
-    ----------------------------------------------------------------
-  */
-  is = (unsigned char *) &kgrib[0];
+  section = gribbuffer;
+  sec_len = 16;
 
-  isLen = decodeIS(is, isec0, iret);
+  if ( !GRIB_START(section) )
+    {
+      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
+    }
 
-  /*
-    If count is negative, have to rescale by factor of -120.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( ISEC0_GRIB_Len < 0 )
+  gribversion = GRIB_EDITION(section);
+  if ( gribversion != 2 )
     {
-      if ( ldebug )
-	gprintf(__func__, "Special case, negative length multiplied by -120");
-      llarge = TRUE;
-      ISEC0_GRIB_Len *= (-120);
+      fprintf(stderr, "wrong GRIB version %d\n", gribversion);
+      return (-1);      
     }
-  /*
-    When decoding or calculating length, previous editions
-    of the GRIB code must be taken into account.
 
-    In the table below, covering sections 0 and 1 of the GRIB
-    code, octet numbering is from the beginning of the GRIB
-    message;
-    * indicates that the value is not available in the code edition;
-    R indicates reserved, should be set to 0;
-    Experimental edition is considered as edition -1.
+  gribsize = 0;
+  for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | section[8+i];
 
-    GRIB code edition -1 has fixed length of 20 octets for
-    section 1, the length not included in the message.
-    GRIB code edition 0 has fixed length of 24 octets for
-    section 1, the length being included in the message.
-    GRIB code edition 1 can have different lengths for section
-    1, the minimum being 28 octets, length being included in
-    the message.
+  grib_len += sec_len;
+  section  += sec_len;
 
-                                         Octet numbers for code
-                                                  editions
+  /* section 1 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "ids %d %ld\n", sec_num, sec_len);
 
-                 Contents.                   -1      0      1
-                 ---------                ----------------------
-       Letters GRIB                          1-4    1-4    1-4
-       Total length of GRIB message.          *      *     5-7
-       GRIB code edition number               *      *      8
-       Length of Section 1.                   *     5-7    9-11
-       Reserved octet (R).                    *      8(R)   *
-       Version no. of Code Table 2.           *      *     12
-       Identification of centre.              5      9     13
-       Generating process.                    6     10     14
-       Grid definition .                      7     11     15
-       Flag (Code Table 1).                   8     12     16
-       Indicator of parameter.                9     13     17
-       Indicator of type of level.           10     14     18
-       Height, pressure etc of levels.      11-12  15-16  19-20
-       Year of century.                      13     17     21
-       Month.                                14     18     22
-       Day.                                  15     19     23
-       Hour.                                 16     20     24
-       Minute.                               17     21     25
-       Indicator of unit of time.            18     22     26
-       P1 - Period of time.                  19     23     27
-       P2 - Period of time                  20(R)   24     28
-       or reserved octet (R).
-       Time range indicator.                21(R)   25     29
-       or reserved octet (R).
-       Number included in average.       22-23(R)  26-27  30-31
-       or reserved octet (R).
-       Number missing from average.         24(R)  28(R)   32
-       or reserved octet (R).
-       Century of data.                       *      *     33
-       Designates sub-centre if not 0.        *      *     34
-       Decimal scale factor.                  *      *    35-36
-       Reserved. Set to 0.                    *      *    37-48
-       (Need not be present)
-       For originating centre use only.       *      *    49-nn
-       (Need not be present)
+  if ( sec_num != 1 )
+    {
+      fprintf(stderr, "Unexpected section1 number %d\n", sec_num);
+      return (-1);
+    }
 
-    Identify which GRIB code edition is being decoded.
+  *idsp = section;
 
-    In GRIB edition 1, the edition number is in octet 8.
-    In GRIB edition 0, octet 8 is reserved and set to 0.
-    In GRIB edition -1, octet 8 is a flag field and can have a
-    a valid value of 0, 1, 2 or 3.
+  grib_len += sec_len;
+  section  += sec_len;
 
-    However, GRIB edition number 0 has a fixed
-    length of 24, included in the message, for section 1, so
-    if the value extracted from octets 5-7 is 24 and that from
-    octet 8 is 0, it is safe to assume edition 0 of the code.
+  /* section 2 and 3 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "lus %d %ld\n", sec_num, sec_len);
 
-  */
-  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
+  if ( sec_num == 2 )
     {
-      /*
-	Set length of GRIB message to missing data value.
-      */
-      ISEC0_GRIB_Len = 0;
-    }
-  /*
-    If Grib Edition 1 and only length is required, go to section 9.
-  */
-  if ( dfunc == 'L' ) goto LABEL900;
-
-  /*
-    ----------------------------------------------------------------
-    PDS Product Definition Section (Section 1)
-    ----------------------------------------------------------------
-  */ 
-  pds = is + isLen;
+      *lusp = section;
 
-  pdsLen = decodePDS(pds, isec0, isec1);
+      grib_len += sec_len;
+      section  += sec_len;
 
-  /*
-    ----------------------------------------------------------------
-    GDS Grid Description Section (Section 2)
-    ----------------------------------------------------------------
-  */
-  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
+      /* section 3 */
+      sec_len = GRIB2_SECLEN(section);
+      sec_num = GRIB2_SECNUM(section);
+      //fprintf(stderr, "gds %d %ld\n", sec_num, sec_len);
 
-  if ( gdsIncluded )
+      *gdsp = section;
+    }
+  else if ( sec_num == 3 )
     {
-      gds = is + isLen + pdsLen;
-
-      gdsLen = decodeGDS(gds, isec0, isec2, fsec2, &numGridVals, dfunc);
+      *gdsp = section;
+    }
+  else
+    {
+      fprintf(stderr, "Unexpected section3 number %d\n", sec_num);
+      return (-1);
     }
 
-  /*
-    ----------------------------------------------------------------
-    BMS Bit-Map Section Section (Section 3)
-    ----------------------------------------------------------------
-  */ 
-  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+  grib_len += sec_len;
+  section  += sec_len;
 
-  isec3[0] = 0;
-  if ( bmsIncluded )
-    {
-      bms = is + isLen + pdsLen + gdsLen;
+  /* section 4 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "pds %d %ld\n", sec_num, sec_len);
 
-      bmsLen = BMS_Len;
-      imaskSize = (bmsLen - 6)<<3;
-      bitmapSize = imaskSize - BMS_UnusedBits;
-      /*
-      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
-      */
+  if ( sec_num != 4 )
+    {
+      fprintf(stderr, "Unexpected section4 number %d\n", sec_num);
+      return (-1);
     }
 
-  /*
-    ----------------------------------------------------------------
-    BDS Binary Data Section (Section 4)
-    ----------------------------------------------------------------
-  */
-  bds = is + isLen + pdsLen + gdsLen + bmsLen;
+  *pdsp = section;
 
-  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
+  grib_len += sec_len;
+  section  += sec_len;
 
-  bdsLen = decodeBDS(ISEC1_DecScaleFactor, bds, isec2, isec4, 
-		     fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
+  /* section 5 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "drs %d %ld\n", sec_num, sec_len);
 
-  if ( *iret != 0 ) return;
+  if ( sec_num != 5 )
+    {
+      fprintf(stderr, "Unexpected section5 number %d\n", sec_num);
+      return (-1);
+    }
 
-  ISEC4_NumNonMissValues = ISEC4_NumValues;
+  *drsp = section;
 
-  if ( bitmapSize > 0 )
+  grib_len += sec_len;
+  section  += sec_len;
+
+  /* section 6 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "bms %d %ld\n", sec_num, sec_len);
+
+  if ( sec_num != 6 )
     {
-      if ( dfunc != 'L' && dfunc != 'J' )
-	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
-	  {
-	    lmissvalinfo = 0;
-	    FSEC3_MissVal = GRIB_MISSVAL;
-	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
-	  }
+      fprintf(stderr, "Unexpected section6 number %d\n", sec_num);
+      return (-1);
+    }
 
-      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
-      ISEC4_NumValues        = bitmapSize;
+  *bmsp = section;
 
-      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
-	{
-	  long i, j;
-	  GRIBPACK *pbitmap;
-	  GRIBPACK bitmap;
-	  GRIBPACK *imask;
+  grib_len += sec_len;
+  section  += sec_len;
 
-	  /*
-	  unsigned char *bitmap;
-	  bitmap = BMS_Bitmap;
-	  j = ISEC4_NumNonMissValues;
-	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
-	    {
-	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
-		fsec4[i] = fsec4[--j];
-	      else
-		fsec4[i] = FSEC3_MissVal;
-	    }
-	  */
+  /* section 7 */
+  sec_len = GRIB2_SECLEN(section);
+  sec_num = GRIB2_SECNUM(section);
+  //fprintf(stderr, "bds %d %ld\n", sec_num, sec_len);
 
-	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
+  if ( sec_num != 7 )
+    {
+      fprintf(stderr, "Unexpected section7 number %d\n", sec_num);
+      return (-1);
+    }
 
-#if defined (VECTORCODE)
-	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
-	  pbitmap = imask;
-#else
-	  pbitmap = BMS_Bitmap;
-#endif
+  *bdsp = section;
 
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-	  for ( i = imaskSize/8-1; i >= 0; i-- )
-	    {
-	      bitmap = pbitmap[i];
-	      imask[i*8+0] = 1 & (bitmap >> 7);
-	      imask[i*8+1] = 1 & (bitmap >> 6);
-	      imask[i*8+2] = 1 & (bitmap >> 5);
-	      imask[i*8+3] = 1 & (bitmap >> 4);
-	      imask[i*8+4] = 1 & (bitmap >> 3);
-	      imask[i*8+5] = 1 & (bitmap >> 2);
-	      imask[i*8+6] = 1 & (bitmap >> 1);
-	      imask[i*8+7] = 1 & (bitmap);
-	    }
+  grib_len += sec_len;
+  section  += sec_len;
 
-	  j = 0;
-	  for ( i = 0; i < ISEC4_NumValues; i++ )
-	    if ( imask[i] ) j++;
+  /* skip multi GRIB sections */
+  msec = 1;
+  while ( !GRIB_FIN(section) )
+    {
+      sec_len = GRIB2_SECLEN(section);
+      sec_num = GRIB2_SECNUM(section);
 
-	  if ( ISEC4_NumNonMissValues != j )
-	    {
-	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
-		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
-			j, ISEC4_NumNonMissValues);
+      if ( sec_num < 1 || sec_num > 7 ) break;
 
-	      ISEC4_NumNonMissValues = j;
-	    }
+      if ( sec_num == 7 )
+	fprintf(stderr, "Skipped unsupported multi GRIB section %d!\n", ++msec);
 
-	  if ( dfunc != 'J' )
-	    {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
-		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
-	    }
+      if ( (grib_len + sec_len) > gribsize ) break;
 
-	  free(imask);
-	}
+      grib_len += sec_len;
+      section  += sec_len;
     }
 
-  if ( ISEC2_Reduced )
+  /* end section - "7777" in ASCII */
+  if ( !GRIB_FIN(section) )
     {
-      int nlon, nlat;
-      int lsect3, lperio = 1, lveggy;
-      int ilat;
-      int nvalues = 0;
-      int dlon;
-
-      nlat = ISEC2_NumLat;
-      nlon = ISEC2_RowLonPtr[0];
-      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
-      for ( ilat = 1; ilat < nlat; ++ilat )
-	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
-
-      dlon = ISEC2_LastLon-ISEC2_FirstLon;
-      if ( dlon < 0 ) dlon += 360000;
-	  
-      if ( nvalues != ISEC4_NumValues )
-	{
-	  *iret = -801;
-	}
-      //printf("nlat %d  nlon %d \n", nlat, nlon);
-      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
-
-      if ( dfunc == 'R' && *iret == -801 )
-	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
-		ISEC4_NumValues, nvalues);
-      
-      if ( dfunc == 'R' && *iret != -801 )
-	{
-	  ISEC2_Reduced = 0;
-	  ISEC2_NumLon = nlon;
-	  ISEC4_NumValues = nlon*nlat;
-
-	  lsect3 = bitmapSize > 0;
-	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
-	    ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
-	     (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
-	      
-	  (void) qu2reg3(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
-	      
-	  if ( bitmapSize > 0 )
-	    {
-	      long i;
-	      int j = 0;
-	      
-	      for ( i = 0; i < ISEC4_NumValues; i++ )
-		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
-		  
-	      ISEC4_NumNonMissValues = j;
-	    }
-	}
+      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-2);
     }
 
+  return (0);
+}
 
-  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
-  esLen = 4;
 
-  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
+			int *intnum, float *fltnum, off_t *bignum)
+{
+  unsigned char *pds, *gds, *bms, *bds;
+  unsigned char *bufpointer, *is, *section;
+  int gribversion, grib1offset;
+  long gribsize = 0;
+  off_t dpos, bpos = 0;
+  int bdslen;
+  float bsf;
 
-  if ( ISEC0_GRIB_Len )
-    if ( gribLen > ISEC0_GRIB_Len )
-      {
-	Warning("grib1Len = %d gribLen = %d", ISEC0_GRIB_Len, gribLen);
-      }
+  section = gribbuffer;
+  is = gribbuffer;
+  if ( ! GRIB_START(section) )
+    {
+      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
+	      section[0], section[1], section[2], section[3]);
+      return (-1);
+    }
 
-  ISEC0_GRIB_Len = gribLen;
+  gribversion = GRIB_EDITION(section);
+  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
 
-  *kword = gribLen / sizeof(int);
-  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+  if ( gribversion == 1 )
+    grib1offset = 4;
+  else
+    grib1offset = 0;
 
-  /*
-    ----------------------------------------------------------------
-    Section 9 . Abort/return to calling routine.
-    ----------------------------------------------------------------
-  */
- LABEL900:;
+  pds = is + 4 + grib1offset;
+  bufpointer = pds + PDS_Len;
+  gribsize += 4 + grib1offset + PDS_Len;
 
-  if ( ldebug )
+  if ( PDS_HAS_GDS )
     {
-      gprintf(__func__, "Section 9.");
-      gprintf(__func__, "Output values set -");
+      gds = bufpointer;
+      bufpointer += GDS_Len;
+      gribsize += GDS_Len;
+    }
+  else
+    {
+      gds = NULL;
+    }
 
-      gribPrintSec0(isec0);
-      gribPrintSec1(isec0, isec1);
-      /*
-	Print section 2 if present.
-      */
-      if ( lsect2 ) gribPrintSec2DP(isec0, isec2, fsec2);
+  if ( PDS_HAS_BMS )
+    {
+      bms = bufpointer;
+      bufpointer += BMS_Len;
 
-      if ( ! l_iorj )
-	{
-	  /*
-	    Print section 3 if present.
-	  */
-	  if ( lsect3 ) gribPrintSec3DP(isec0, isec3, fsec3);
+      bpos = recpos + gribsize + 6;
 
-	  gribPrintSec4DP(isec0, isec4, fsec4);
-	  /*
-	    Special print for 2D spectra wave field real values in
-	    section 4
-	  */
-	  if ( (isec1[ 0] ==  140) && 
-	       (isec1[ 1] ==   98) && 
-	       (isec1[23] ==    1) && 
-	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
-	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
-	    gribPrintSec4Wave(isec4);
-	}
+      gribsize += BMS_Len;
+    }
+  else
+    {
+      bms = NULL;
     }
-}
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <string.h>
-#include <ctype.h>
 
+  bds = bufpointer;
 
+  dpos = recpos + gribsize + 11;
 
-int gribOpen(const char *filename, const char *mode)
-{
-  int fileID;
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
+  bufpointer += bdslen;
+  gribsize += bdslen;
+  gribsize += 4;
 
-  fileID = fileOpen(filename, mode);
+  if ( gribsize > recsize )
+    {
+      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", recsize, gribsize);
+      return (1);
+    }
 
-#if defined (__sun)
-  if ( fileID != FILE_UNDEFID && tolower(*mode) == 'r' )
+  /* end section - "7777" in ascii */
+  if ( !GRIB_FIN(bufpointer) )
     {
-      fileSetBufferType(fileID, FILE_BUFTYPE_MMAP);
+      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
+	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
     }
-#endif
 
-  return (fileID);  
-}
+  bsf = BDS_BinScale;
+  if ( bsf > 32767 ) bsf = 32768-bsf;
+  bsf = pow(2.0,(double)bsf);
 
+  bignum[0] = dpos;
+  if ( bms ) bignum[1] = bpos;
+  else       bignum[1] = -999;
+  intnum[0] = BDS_NumBits;
 
-void gribClose(int fileID)
-{
-  fileClose(fileID);
+  /*  fltnum[0] = 1.0; */
+  fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
+  fltnum[1] = bsf;
+  fltnum[2] = BDS_RefValue;
+  /*
+  printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
+  printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
+  */
+  return (0);
 }
 
 
-off_t gribGetPos(int fileID)
+void grib1PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  return (fileGetPos(fileID));
-}
+  static int header = 1;
+  int GridType, level, nerr;
+  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
+  int bdslen;
+  int llarge = 0;
 
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : Off Position   Size : V PDS  GDS    BMS    BDS : Code Level :  LType GType: CR LL\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
 
-int gribCheckFiletype(int fileID)
-{
-  int ierr;
-  int found = 0;
-  char buffer[4];
+  is = gribbuffer;
 
-  if ( fileRead(fileID, buffer, 4) != 4 ) return(found);
+  if ( gribrec_len(is[4], is[5], is[6]) > JP23SET ) llarge = 1;
 
-  if ( memcmp(buffer, "GRIB", 4) == 0 )
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      found = 1;
-      if ( CGRIBEX_Debug ) Message("found GRIB file = %s", fileInqName(fileID));
+      fprintf(stdout, "%5d :%4ld %8ld %6ld : GRIB message error\n", nrec, offset, recpos, recsize);
+      return;
     }
-  else
-    {
-      long offset;
 
-      ierr = gribFileSeek(fileID, &offset);
-      fileRewind(fileID);
-      if ( !ierr )
-	{
-	  found = 1;
-	  if ( CGRIBEX_Debug ) Message("found seek GRIB file = %s", fileInqName(fileID));
-	}
-    }
+  if ( gds == NULL )
+    GridType = -1;
+  else
+    GridType = GDS_GridType;
 
-  return (found);
-}
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else if ( PDS_LevelType == 109 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
+  bdslen = BDS_Len;
+  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
 
-int gribCheckSeek(int fileID, long *offset, int *version)
-{
-  int ierr;
-  char buffer[4];
-
-  ierr = gribFileSeek(fileID, offset);
-
-  *version = -1;
-  if ( !ierr )
+  if ( ((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130) )
     {
-      if ( fileRead(fileID, buffer, 4) == 4 )
-	*version = buffer[3];
+      int s1, s2;
+      s1 = gribrec_len(bds[14], bds[15], bds[16]);
+      s2 = gribrec_len(gribbuffer[4], gribbuffer[5], gribbuffer[6]);
+      cr = ((double)s1)/s2;
     }
 
-  return (ierr);
+  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d%4d%5d %6d %6d : %3d %6d : %5d %5d %6.4g  %c",
+	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
+	  PDS_Len, GDS_Len, BMS_Len, bdslen,
+	  PDS_Parameter, level, PDS_LevelType, GridType, cr, llarge?'T':'F');
+
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-int gribFileSeekOld(int fileID, long *offset)
+void grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  /* position file pointer after GRIB */
-  int ch;
-  int buffersize = 4096;
-  unsigned char buffer[4096];
-  int retry = 4096;
-  int i;
-  void *fileptr;
-
-  *offset = 0;
+  static int header = 1;
+  int nerr;
+  unsigned char *is  = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  unsigned char *ids = NULL, *lus = NULL, *drs = NULL;
+  long ids_len = 0, lus_len = 0, gds_len = 0, pds_len = 0, drs_len = 0, bms_len = 0, bds_len = 0;
+  int gridtype, paramnum, level1type /*, level2type*/;
+  int level1 /*, level1sf*/;
+  /* int level2, level2sf; */
+  double cr = 1;
 
-  fileptr = filePtr(fileID);
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : Off Position   Size : V IDS LUS GDS PDS  DRS    BMS    BDS : Code Level :  LType GType: CR\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
 
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
-  ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
-  /*
-  fileRead(fileID, buffer, 4);
-  */
+  is = gribbuffer;
 
-  while ( retry-- )
+  nerr = grib2Sections(gribbuffer, recsize, &ids, &lus, &gds, &pds, &drs, &bms, &bds);
+  if ( nerr )
     {
-      for ( i = 0; i < buffersize-4; ++i )
-	{
-	  if (buffer[i  ] == 'G' && 
-	      buffer[i+1] == 'R' &&
-	      buffer[i+2] == 'I' &&
-	      buffer[i+3] == 'B')
-	    {
-	      if ( CGRIBEX_Debug )
-		Message("record offset = %d", (int) *offset);
-	      return (0);
-	    }
-	  else
-	    {
-	      ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
-	      (*offset)++;
-	    }
-	}
-      buffer[0] = buffer[i  ];
-      buffer[1] = buffer[i+1];
-      buffer[2] = buffer[i+2];
-      buffer[3] = buffer[i+3];
+      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
+      return;
     }
 
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
+  if ( ids ) ids_len = GRIB2_SECLEN(ids);
+  if ( lus ) lus_len = GRIB2_SECLEN(lus);
+  if ( gds ) gds_len = GRIB2_SECLEN(gds);
+  if ( pds ) pds_len = GRIB2_SECLEN(pds);
+  if ( drs ) drs_len = GRIB2_SECLEN(drs);
+  if ( bms ) bms_len = GRIB2_SECLEN(bms);
+  if ( bds ) bds_len = GRIB2_SECLEN(bds);
 
-  return (1);
+  /*
+  if ( (BDS_Flag >> 4)&1 && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[14]<<16)+(bds[15]<<8)+bds[16]));
+      s2 = ((int) ((gribbuffer[4]<<16)+(gribbuffer[5]<<8)+gribbuffer[6]));
+      cr = ((double)s1)/s2;
+    }
+  */
+  gridtype   = GET_UINT2(gds[12],gds[13]);
+  paramnum   = GET_UINT1(pds[10]);
+  level1type = GET_UINT1(pds[22]);
+  /* level1sf   = GET_UINT1(pds[23]); */
+  level1     = GET_UINT4(pds[24],pds[25],pds[26],pds[27]);
+  /* level2type = GET_UINT1(pds[28]); */
+  /* level2sf   = GET_UINT1(pds[29]); */
+  /* level2     = GET_UINT4(pds[30],pds[31],pds[32],pds[33]); */
+  /*
+  printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
+  */
+  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %3d%7d : %5d %5d %6.4g\n",
+	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
+	  ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len,
+	  paramnum, level1, level1type, gridtype, cr);
 }
 
 
-int gribFileSeek(int fileID, long *offset)
+void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  /* position file pointer after GRIB */
-  const long GRIB = 0x47524942;
-  long code = 0;
-  int ch;
-  int retry = 4096*4096;
-  void *fileptr;
-
-  *offset = 0;
+  int gribversion;
 
-  fileptr = filePtr(fileID);
+  gribversion = gribVersion(gribbuffer, recsize);
 
-  while ( retry-- )
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
+  else if ( gribversion == 2 )
+    grib2PrintALL(nrec, offset, recpos, recsize, gribbuffer);
+  else
     {
-      ch = filePtrGetc(fileptr);
-      if ( ch == EOF ) return (-1);
-    
-      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
-
-      if ( code == GRIB )
-	{
-	  if ( CGRIBEX_Debug )
-	    Message("record offset = %d", (int) *offset);
-	  return (0);
-	}
-
-      (*offset)++;
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, offset, recpos, recsize, gribversion); 
     }
-
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
-
-  return (1);
 }
 
 
-int gribFileSeekTest(int fileID, long *offset)
+void grib1PrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  /* position file pointer after GRIB */
-  const long GRIB = 0x47524942;
-  long code = 0;
-  int ch;
-  int i = 0;
-  const int buffersize = 8;
-  unsigned char buffer[8];
-  int retry = 4096*4096;
-  void *fileptr;
-  int nread = 0;
-
-  *offset = 0;
+  static int header = 1;
+  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int century, subcenter, decimalscale, nerr;
+  int fc_num = 0;
+  int year = 0, date;
 
-  fileptr = filePtr(fileID);
+  UNUSED(recpos);
 
-  while ( retry-- )
+  if ( header )
     {
-      if ( i >= nread )
-	{
-	  nread = (int) filePtrRead(fileptr, buffer, buffersize);
-	  if ( nread == 0 ) return (-1);
-	  i = 0;
-	}
+      fprintf(stdout, 
+      "  Rec : PDS Tab Cen Sub Ver Grid Code LTyp Level1 Level2    Date  Time P1 P2 TU TR NAVE Scale FCnum CT\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
 
-      ch = buffer[i++];
-      code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+  is = gribbuffer;
 
-      if ( code == GRIB )
-	{
-	  /* printf("end: %d %d\n", nread, i); */
-	  if ( CGRIBEX_Debug )
-	    Message("record offset = %d", (int) *offset);
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-	  if ( i != nread ) fileSetPos(fileID, (off_t) i-nread, SEEK_CUR);
+  switch(GRIB_EDITION(is))
+    {   
+    case 0:
+      year                = GET_UINT1(pds[12]);
+      century             = 1;
+      subcenter           = 0;
+      decimalscale        = 0;
+      break;
+    case 1:
+      year                = PDS_Year;
+      century             = PDS_Century;
+      subcenter           = PDS_Subcenter;
+      decimalscale        = PDS_DecimalScale;
+      break;
+    default:
+      fprintf(stderr, "Grib version %d not supported!", GRIB_EDITION(is));
+      exit(EXIT_FAILURE);
+    }
 
-	  return (0);
-	}
+  if ( PDS_Len > 28 )
+    if ( PDS_CenterID    == 98 || PDS_Subcenter == 98 ||
+	(PDS_CenterID    ==  7 && PDS_Subcenter == 98) )
+      if ( pds[40] == 1 )
+	fc_num = GET_UINT1(pds[49]);
 
-      (*offset)++;
+  if ( year < 0 )
+    {
+      date = (-year)*10000+PDS_Month*100+PDS_Day;
+      century = -century;
     }
+  else
+    {
+      date =    year*10000+PDS_Month*100+PDS_Day;
+    }
+      
+  fprintf(stdout, "%5d :%4d%4d%4d%4d%4d %4d %4d%4d%7d%7d %8d%6d%3d%3d%3d%3d%5d%6d%5d%4d", nrec,
+	  PDS_Len,  PDS_CodeTable,   PDS_CenterID, subcenter, PDS_ModelID,
+	  PDS_GridDefinition, PDS_Parameter, PDS_LevelType, PDS_Level1, PDS_Level2,
+	  date, PDS_Time, PDS_TimePeriod1, PDS_TimePeriod2, PDS_TimeUnit, PDS_TimeRange,
+	  PDS_AvgNum, decimalscale, fc_num, century);
 
-  if ( CGRIBEX_Debug )
-    Message("record offset = %d", (int) *offset);
-
-  return (1);
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-int gribReadSize(int fileID)
+void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int gribversion, gribsize;
-  int b1, b2, b3;
-  off_t pos;
-  void *fileptr;
-  /*
-  const int buffersize = 4;
-  unsigned char buffer[4];
-  */
-  fileptr = filePtr(fileID);
+  int gribversion;
 
-  pos = fileGetPos(fileID); 
-  /* bug: order of functions calls!
-     gribsize = (filePtrGetc(fileptr) << 16) + (filePtrGetc(fileptr) << 8) + filePtrGetc(fileptr);
-  */
-  b1 = filePtrGetc(fileptr);
-  b2 = filePtrGetc(fileptr);
-  b3 = filePtrGetc(fileptr);
-  // gribsize = (b1 << 16) + (b2 << 8) + b3;
-  gribsize = gribrec_len(b1, b2, b3);
+  gribversion = gribVersion(gribbuffer, recsize);
 
-  gribversion = filePtrGetc(fileptr);
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
   /*
-  filePtrRead(fileptr, buffer, buffersize);
-
-  gribsize = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
-
-  gribversion = buffer[3];
+  else if ( gribversion == 2 )
+    grib2PrintPDS(nrec, recpos, recsize, gribbuffer);
   */
-  if ( gribsize == 24 )
-    {
-      if ( gribversion != 1 && gribversion != 2 ) gribversion = 0;
-    }
-
-  if ( CGRIBEX_Debug )
-    Message("gribversion = %d", gribversion);
-
-  if ( gribversion == 0 )
+  else
     {
-      int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
-      int issize = 4, essize = 4;
-      int flag;
-
-      pdssize = gribsize;
-      fileSetPos(fileID, (off_t) 3, SEEK_CUR);
-      if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
-      flag = filePtrGetc(fileptr);
-      if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
-  
-      fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
-
-      if ( flag & 128 )
-	{
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  gdssize = (b1 << 16) + (b2 << 8) + b3;
-	  fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
-	  if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
-	}
-
-      if ( flag & 64 )
-	{
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  bmssize = (b1 << 16) + (b2 << 8) + b3;
-	  fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
-	  if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
-	}
-
-      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-      bdssize = (b1 << 16) + (b2 << 8) + b3;
-      if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
-
-      gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
     }
-  else if ( gribversion == 1 )
-    {
-      if ( gribsize > JP23SET ) /* Large GRIB record */
-	{
-	  int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
-	  int issize = 4, essize = 4;
-	  int flag;
-
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  pdssize = (b1 << 16) + (b2 << 8) + b3;
-	  if ( CGRIBEX_Debug ) Message("pdssize     = %d", pdssize);
+}
 
-	  for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
-	  if ( CGRIBEX_Debug ) Message("flag        = %d", flag);
-  
-	  fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
 
-	  if ( flag & 128 )
-	    {
-	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	      gdssize = (b1 << 16) + (b2 << 8) + b3;
-	      fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
-	      if ( CGRIBEX_Debug ) Message("gdssize     = %d", gdssize);
-	    }
-	  
-	  if ( flag & 64 )
-	    {
-	      b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	      bmssize = (b1 << 16) + (b2 << 8) + b3;
-	      fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
-	      if ( CGRIBEX_Debug ) Message("bmssize     = %d", bmssize);
-	    }
+void grib1PrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  static int header = 1;
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-	  b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
-	  bdssize = (b1 << 16) + (b2 << 8) + b3;
-	  bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
-	  if ( CGRIBEX_Debug ) Message("bdssize     = %d", bdssize);
+  UNUSED(recpos);
 
-	  gribsize = issize+pdssize+gdssize+bmssize+bdssize+essize;
-	}
-    }
-  else if ( gribversion == 2 )
+  if ( header )
     {
-      int i;
-      /* we set gribsize the following way because it doesn't matter then
-	 whether int is 4 or 8 bytes long - we don't have to care if the size
-	 really fits: if it does not, the record can not be read at all */
-      gribsize = 0;
-      for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | filePtrGetc(fileptr);
+      fprintf(stdout, 
+      "  Rec : GDS  NV PVPL Typ : xsize ysize   Lat1   Lon1   Lat2   Lon2    dx    dy\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
-  else
+
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      gribsize = 0;
-      Warning("GRIB version %d unsupported!", gribversion);
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
     }
 
-  if ( filePtrEOF(fileptr) ) gribsize = 0;
-
-  if ( CGRIBEX_Debug )
-    Message("gribsize    = %d", gribsize);
+  fprintf(stdout, "%5d :", nrec);
 
-  fileSetPos(fileID, pos, SEEK_SET);
+  if ( gds )
+    fprintf(stdout, "%4d%4d%4d %4d :%6d%6d%7d%7d%7d%7d%6d%6d",
+	    GDS_Len,  GDS_NV,   GDS_PVPL, GDS_GridType,
+	    GDS_NumLon,   GDS_NumLat,
+	    GDS_FirstLat, GDS_FirstLon,
+	    GDS_LastLat,  GDS_LastLon,
+	    GDS_LonIncr,  GDS_LatIncr);
+  else
+    fprintf(stdout, " Grid Description Section not defined");
 
-  return (gribsize);
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-int gribGetSize(int fileID)
+void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int recsize;
-  long offset;
-  int ierr;
+  int gribversion;
 
-  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
-  if ( ierr > 0 )
+  gribversion = gribVersion(gribbuffer, recsize);
+
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
+  /*
+  else if ( gribversion == 2 )
+    grib2PrintGDS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
     {
-      Warning("GRIB record not found!");
-      return (0);
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
     }
-
-  if ( ierr == -1 )
-    return (0);
-  else if ( ierr == 1 )
-    return (0);
-
-  recsize = gribReadSize(fileID);
-
-  if ( CGRIBEX_Debug ) Message("recsize = %d", recsize);
-
-  fileSetPos(fileID, (off_t) -4, SEEK_CUR);
-
-  return (recsize);
 }
 
 
-int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
+void grib1PrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  long offset;
-  int ierr = 0;
-  size_t nread, recsize, recsize0;
+  static int header = 1;
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-  ierr = gribFileSeek(fileID, &offset); /* position file pointer after GRIB */
-  if ( ierr > 0 )
-    {
-      Warning("GRIB record not found!");
-      return (-2);
-    }
+  UNUSED(recpos);
 
-  if ( ierr == -1 )
-    {
-      *buffersize = 0;
-      return (-1);
-    }
-  else if ( ierr == 1 )
+  if ( header )
     {
-      *buffersize = 0;
-      return (-2);
+      fprintf(stdout, 
+      "  Rec : Code Level     BMS    Size\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
     }
 
-  recsize = gribReadSize(fileID);
-
-  buffer[0] = 'G';
-  buffer[1] = 'R';
-  buffer[2] = 'I';
-  buffer[3] = 'B';
-
-  recsize0 = recsize;
-
-  if ( recsize > *buffersize )
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      recsize = *buffersize;
-      ierr = -3;
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
     }
 
-  *buffersize = recsize0;
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-  nread = fileRead(fileID, &buffer[4], recsize-4);
+  fprintf(stdout, "%5d :", nrec);
 
-  if ( nread != recsize-4 ) ierr = 1;
+  if ( bms )
+    fprintf(stdout, "%4d%7d %7d %7d",
+	    PDS_Parameter, level,
+	    BMS_Len, BMS_BitmapSize);
+  else
+    fprintf(stdout, "%4d%7d Bit Map Section not defined", PDS_Parameter, level);
 
-  return (ierr);
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
 }
 
 
-int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
+void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int  nwrite = 0;
+  int gribversion;
 
-  if( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
+  gribversion = gribVersion(gribbuffer, recsize);
+
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
+  /*
+  else if ( gribversion == 2 )
+    grib2PrintBMS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
     {
-      perror(__func__);
-      nwrite = -1;
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
     }
-
-  return ((int) nwrite);
 }
 
 
-int gribrec_len(int b1, int b2, int b3)
+void grib1PrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
 {
-  int gribsize;
+  static int header = 1;
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
+  double refval, scale;
 
-  gribsize = (1-(int) ((unsigned) (b1&128) >> 6)) * (int) (((b1&127) << 16)+(b2<<8) + b3);
-  /*
-    If count is negative, have to rescale by factor of -120.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( gribsize < 0 ) gribsize *= (-120);
+  UNUSED(recpos);
 
-  return (gribsize);
-}
+  if ( header )
+    {
+      fprintf(stdout, 
+      "  Rec : Code Level     BDS Flag     Scale   RefValue Bits  CR\n");
+/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
+      header = 0;
+    }
 
-#include <stdio.h>
-#include <math.h>
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-/* calculate_pfactor: source code from grib_api-1.8.0 */
-double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation)
-{
-  /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
-  long loop, index, m, n = 0;
-  double pFactor, zeps = 1.0e-15;
-  long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
-  double* weights, range, * norms;
-  double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
-  double numerator = 0.0, denominator = 0.0, slope;
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
+    }
 
-  /*
-  // Setup the weights
-   */
+  refval = BDS_RefValue;
 
-  range = (double) (ismax - ismin +1);
+  if ( BDS_BinScale < 0 )
+    scale = 1.0/pow(2.0, (double) -BDS_BinScale);
+  else
+    scale = pow(2.0, (double) BDS_BinScale);
 
-  weights = (double*) malloc((ismax+1)*sizeof(double));
-  for( loop = ismin; loop <= ismax; loop++ )
-    weights[loop] = range / (double) (loop-ismin+1);
-  /*
-  // Compute norms
-  // Handle values 2 at a time (real and imaginary parts).
-   */
-  norms = (double*) malloc((ismax+1)*sizeof(double));
+  if ( PDS_DecimalScale )
+    {
+      double decscale;
+      decscale = pow(10.0, (double)-PDS_DecimalScale);
+      refval *= decscale;
+      scale  *= decscale;
+    }
 
-  for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
-  /*
-  // Form norms for the rows which contain part of the unscaled subset.
-   */
+  fprintf(stdout, "%5d :", nrec);
 
-  index = -2;
-  for( m = 0; m < subsetTruncation; m++ )
-    for( n = m; n <= fieldTruncation; n++ ) {
-      index += 2;
-      if( n >= subsetTruncation ) {
-        double tval = spectralField[index];
-        tval=tval<0?-tval:tval;
-        norms[n] = norms[n] > tval ? norms[n] : tval;
-        tval = spectralField[index+1];
-        tval=tval<0?-tval:tval;
-        norms[n] = norms[n] > tval ? norms[n] : tval;
-      }
-    }
-  /*
-  // Form norms for the rows which do not contain part of the unscaled subset.
-   */
+  if ( bds )
+    fprintf(stdout, "%4d%7d %7d %4d %8.5g %11.5g%4d %6.4g",
+	    PDS_Parameter, level,
+	    BDS_Len, BDS_Flag, scale, refval, BDS_NumBits, cr);
+  else
+    fprintf(stdout, " Binary Data Section not defined");
 
-  for( m = subsetTruncation; m <= fieldTruncation; m++ )
-    for( n = m; n <= fieldTruncation; n++ ) {
-      double tval = spectralField[index];
-      index += 2;
-      tval=tval<0?-tval:tval;
-      norms[n] = norms[n] > tval ? norms[n] : tval;
-      tval = spectralField[index+1];
-      tval=tval<0?-tval:tval;
-      norms[n] = norms[n] > tval ? norms[n] : tval;
-    }
+  if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
+  fprintf(stdout, "\n");
+}
 
-  /*
-  // Ensure the norms have a value which is not too small in case of
-  // problems with math functions (e.g. LOG).
-   */
 
-  for( loop = ismin; loop <= ismax; loop++ ) {
-    norms[n] = norms[n] > zeps ? norms[n] : zeps;
-    if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
-  }
+void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  int gribversion;
 
+  gribversion = gribVersion(gribbuffer, recsize);
+
+  if ( gribversion == 0 || gribversion == 1 )
+    grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
   /*
-  // Do linear fit to find the slope
-   */
+  else if ( gribversion == 2 )
+    grib2PrintBDS(nrec, recpos, recsize, gribbuffer);
+  */
+  else
+    {
+      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
+	      nrec, 0L, recpos, recsize, gribversion); 
+    }
+}
 
-  for( loop = ismin; loop <= ismax; loop++ ) {
-    x = log( (double) (loop*(loop+1)) );
-    y = log( norms[loop] );
-    weightedSumOverX = weightedSumOverX + x * weights[loop];
-    weightedSumOverY = weightedSumOverY + y * weights[loop];
-    sumOfWeights = sumOfWeights + weights[loop];
-  }
-  weightedSumOverX = weightedSumOverX / sumOfWeights;
-  weightedSumOverY = weightedSumOverY / sumOfWeights;
 
-  /*
-  // Perform a least square fit for the equation
-   */
+void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+{
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
 
-  for( loop = ismin; loop <= ismax; loop++ ) {
+  UNUSED(recpos);
 
-    x = log( (double)(loop*(loop+1)) );
-    y = log( norms[loop] );
-    numerator =
-      numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
-    denominator =
-      denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
-  }
-  slope = numerator / denominator;
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-  free(weights);
-  free(norms);
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
+      return;
+    }
 
-  pFactor = -slope;
-  if( pFactor < -9999.9 ) pFactor = -9999.9;
-  if( pFactor > 9999.9 )  pFactor = 9999.9;
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-  return pFactor;
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
+    }
+
+  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+    {
+      fprintf(stdout, "GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+    }
 }
 
 
-void scaleComplex(double *fpdata, int pcStart, int pcScale, int trunc, int inv)
+static
+void repair1(unsigned char *gbuf, long gbufsize)
 {
-  double power;
-  double *scale = (double*) malloc((trunc+1)*sizeof(double));
-  int  n, m;
-  int  index;
-
-  if ( scale == NULL ) SysError("No Memory!");
+  long i;
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  /* int recLen; */
+  unsigned char *source;
+  size_t sourceLen;
+  int bds_len, bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress */;
+  int bds_head = 11;
+  int bds_ext = 0, bds_ubits;
+  int datstart = 0;
+  /* int llarge = FALSE; */
 
-  if ( pcScale < -10000 || pcScale > 10000 )
+  long gribrecsize;
+  nerr = grib1Sections(gbuf, gbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
     {
-      fprintf(stderr, " scaleComplex: Invalid power given %6d\n", pcScale);
+      fprintf(stdout, "GRIB message error\n");
       return;
-   }
+    }
 
-  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return;
+    }
 
-  if ( pcScale == 0 ) return;
+  /* recLen = gribrec_len(gbuf[4], gbuf[5], gbuf[6]); */
+  /* if ( recLen > JP23SET ) llarge = TRUE; */
 
-  power = (double) pcScale / 1000.;
-  scale[0] = 1.0;
+  bds_len   = BDS_Len;
+  bds_nbits = BDS_NumBits;
+  bds_flag  = BDS_Flag;
+  bds_ubits = bds_flag & 15;
+  lspherc   =  bds_flag >> 7;
+  lcomplex  = (bds_flag >> 6)&1;
+  /* lcompress = (bds_flag >> 4)&1; */
 
-  for ( n = 1; n <= trunc; n++ )
+  if ( lspherc )
     {
-      if (pcScale != 1000)
-         scale[n] = pow((double) (n*(n+1)), power);
+      if ( lcomplex  )
+	{
+	  int jup, ioff;
+	  jup  = bds[15];
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	}
       else
-         scale[n] =     (double) (n*(n+1));
+	{
+	  bds_ext = 4;
+	}
     }
 
-  if ( inv )
-    for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
-
-  /* Scale the values */
+  datstart = bds_head + bds_ext;
 
-  index = 0;
+  source = bds + datstart;
 
-  for ( m = 0;   m < pcStart; m++ )
-    for ( n = m; n <= trunc; n++ )
-      {
-	if ( n >= pcStart )
-	  {
-	    fpdata[index  ] *= scale[n];
-	    fpdata[index+1] *= scale[n];
-	  }
-	index += 2;
-      }
+  sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
 
-  for ( m = pcStart; m <= trunc; m++ )
-    for ( n = m;     n <= trunc; n++ )
-      {
-	fpdata[index  ] *= scale[n];
-	fpdata[index+1] *= scale[n];
-	index += 2;
-      }
-
-  free(scale);
+  if ( bds_nbits == 24 )
+    {
+      long nelem;
+      unsigned char *pbuf;
+      nelem = sourceLen/3;
+      pbuf = (unsigned char*) malloc(sourceLen);
+      for ( i = 0; i < nelem; i++ )
+	{
+	  pbuf[3*i  ] = source[        i];
+	  pbuf[3*i+1] = source[  nelem+i];
+	  pbuf[3*i+2] = source[2*nelem+i];
+	}
+      memcpy(source, pbuf, sourceLen);
+      free(pbuf);
+    }
 }
 
 
-void scatterComplex(double *fpdata, int pcStart, int trunc, int nsp)
+void gribRepair1(int nrec, long recsize, unsigned char *gribbuffer)
 {
-  double *fphelp = (double*) malloc(nsp*sizeof(double));
-  int  m, n;
-  int  index, inext;
-
-  if ( fphelp == NULL ) SysError("No Memory!");
+  int level, nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  double cr = 1;
 
-  index = inext = 0;
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "%5d : GRIB message error\n", nrec);
+      return;
+    }
 
-  for ( m = 0;   m <= pcStart; m++ )
-    for ( n = m; n <= trunc; n++ )
-      {
-	if ( pcStart >= n )
-	  {
-	    fphelp[index  ] = fpdata[inext++];
-	    fphelp[index+1] = fpdata[inext++];
-	  }
-	index += 2;
-      }
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
+      return;
+    }
 
-  index = 0;
-  for ( m = 0;   m <= trunc; m++ )
-    for ( n = m; n <= trunc; n++ )
-      {
-	if ( n > pcStart )
-	  {
-	    fphelp[index  ] = fpdata[inext++];
-	    fphelp[index+1] = fpdata[inext++];
-	  }
-	index += 2;
-      }
+  if ( PDS_LevelType == 100 )
+    level = PDS_Level * 100;
+  else if ( PDS_LevelType == 99 )
+    level = PDS_Level;
+  else
+    level = PDS_Level1;
 
-  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+    {
+      int s1, s2;
+      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+      cr = ((double)s1)/s2;
+    }
 
-  free(fphelp);
+  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+    {
+      fprintf(stdout, "Repair GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+      repair1(gribbuffer, recsize);
+    }
 }
+#include <stdio.h>
+#include <string.h>
 
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
 
-void gatherComplex(double *fpdata, int pcStart, int trunc, int nsp)
-{
-  double *fphelp = (double*) malloc(nsp*sizeof(double));
-  int  m, n;
-  int  index, inext;
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if defined (HAVE_LIBAEC)
+#  include <libaec.h>
+#else
+#  include <szlib.h>
+#endif
+#if defined (__cplusplus)
+}
+#endif
 
-  if ( fphelp == NULL ) SysError("No Memory!");
+#if defined (HAVE_LIBAEC)
+#  define AEC_FLAGS           (AEC_DATA_MSB | AEC_DATA_PREPROCESS)
+#else
+#  define OPTIONS_MASK        (SZ_RAW_OPTION_MASK | SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK)
+#endif
 
-  index = inext = 0;
+#  define PIXELS_PER_BLOCK    (8)
+#  define PIXELS_PER_SCANLINE (PIXELS_PER_BLOCK*128)
 
-  for ( m = 0;   m <= pcStart; m++ )
-    for ( n = m; n <= trunc; n++ )
-      {
-	if ( pcStart >= n )
-	  {
-	    fphelp[inext++] = fpdata[index];
-	    fphelp[inext++] = fpdata[index+1];
-	  }
-	index += 2;
-      }
+#  define MIN_COMPRESS        (0.95)
+#  define MIN_SIZE            (256)
+#endif
 
-  index = 0;
-  for ( m = 0;   m <= trunc; m++ )
-    for ( n = m; n <= trunc; n++ )
-      {
-	if ( n > pcStart )
-	  {
-	    fphelp[inext++] = fpdata[index];
-	    fphelp[inext++] = fpdata[index+1];
-	  }
-	index += 2;
-      }
+#define  Z_SZIP  128
+#define  Z_AEC   130
 
-  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
 
-  free(fphelp);
-}
+#define SetLen3(var, offset, value) ((var[offset+0] = 0xFF & (value >> 16)), \
+				     (var[offset+1] = 0xFF & (value >>  8)), \
+				     (var[offset+2] = 0xFF & (value      )))
+#define SetLen4(var, offset, value) ((var[offset+0] = 0xFF & (value >> 24)), \
+				     (var[offset+1] = 0xFF & (value >> 16)), \
+				     (var[offset+2] = 0xFF & (value >>  8)), \
+				     (var[offset+3] = 0xFF & (value      )))
 
 
-void scm0(double *pdl, double *pdr, double *pfl, double *pfr, int klg)
+int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
 {
-  /* System generated locals */
-  double r_1;
+  /* urecsize : uncompressed record size  */
+  int compress = 0;
+  int nerr;
+  /* int  bds_len, bds_nbits, lspherc, lcomplex; */
+  int bds_flag, lcompress;
+  long gribsize = 0;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int gribversion;
 
-  /* Local variables */
-  double zfac, zeps, zbeta;
-  int jl;
-  double zalpha;
+  gribversion = gribVersion(gribbuffer, recsize);
 
-  /* **** SCM0   - Apply SCM0 limiter to derivative estimates. */
-  /* output: */
-  /*   pdl   = the limited derivative at the left edge of the interval */
-  /*   pdr   = the limited derivative at the right edge of the interval */
-  /* inputs */
-  /*   pdl   = the original derivative at the left edge */
-  /*   pdr   = the original derivative at the right edge */
-  /*   pfl   = function value at the left edge of the interval */
-  /*   pfr   = function value at the right edge of the interval */
-  /*   klg   = number of intervals where the derivatives are limited */
+  if ( gribversion == 2 ) return (compress);
 
-  /*  define constants */
+  long gribrecsize;
+  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (compress);
+    }
 
-  zeps = 1.0e-12;
-  zfac = (1.0 - zeps) * 3.0;
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (compress);
+    }
 
-  for ( jl = 0; jl < klg; ++jl )
+  /* bds_len   = BDS_Len; */
+  /* bds_nbits = BDS_NumBits; */
+  bds_flag  = BDS_Flag;
+  /* lspherc   =  bds_flag >> 7; */
+  /* lcomplex  = (bds_flag >> 6)&1; */
+  lcompress = (bds_flag >> 4)&1;
+
+  *urecsize = 0;
+  if ( lcompress )
     {
-      if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
-	{
-	  zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
-	  zbeta  = pdr[jl] / (pfr[jl] - pfl[jl]);
-	  if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
-	  if ( zbeta  <= 0.0 ) pdr[jl] = 0.0;
-	  if ( zalpha > zfac ) pdl[jl] = zfac * (pfr[jl] - pfl[jl]);
-	  if ( zbeta  > zfac ) pdr[jl] = zfac * (pfr[jl] - pfl[jl]);
-	}
-      else
+      compress = BDS_Z;
+      if ( compress == Z_SZIP || compress == Z_AEC )
 	{
-	  pdl[jl] = 0.0;
-	  pdr[jl] = 0.0;
+	  gribsize = gribrec_len(bds[14], bds[15], bds[16]);
 	}
     }
-} /* scm0 */
 
+  *urecsize = gribsize;
 
-int rowina2(double *p, int ko, int ki, double *pw,
-	    int kcode, double msval, int *kret)
-{
-  /* System generated locals */
-  int pw_dim1, pw_offset, i_1;
+  return (compress);
+}
 
-  /* Local variables */
-  double zwt1, zrdi, zpos;
-  int jl, ip;
-  double zdo, zwt;
 
-  /* Parameter adjustments */
-  --p;
-  pw_dim1 = ko + 3;
-  pw_offset = pw_dim1;
-  pw -= pw_offset;
+int  gribZip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
+{
+  int nerr;
+  int gribLen;
+  int rec_len;
+  int llarge = FALSE;
+#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
+  static int libszwarn = 1;
+#endif
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
 
-  /* **** ROWINA2 - Interpolation of row of values. */
-  /*     Input Parameters. */
-  /*     ----------------- */
-  /*     P      - Row of values to be interpolated. */
-  /*              Dimension must be at least KO. */
-  /*     KO     - Number of values required. */
-  /*     KI     - Number of values in P on input. */
-  /*     PW     - Working array. */
-  /*              Dimension must be at least (0:KO+2,3). */
-  /*     KCODE  - Interpolation required. */
-  /*              1 , linear. */
-  /*              3 , cubic. */
-  /*     PMSVAL - Value used for missing data indicator. */
+  gribLen = gribrec_len(dbuf[4], dbuf[5], dbuf[6]);
+  if ( gribLen > JP23SET ) llarge = TRUE;
 
-  /*     Output Parameters. */
-  /*     ------------------ */
-  /*     P     - Now contains KO values. */
-  /*     KRET  - Return code */
-  /*             0, OK */
-  /*             Non-zero, error */
+  rec_len = gribLen;
 
-  /*     Author. */
-  /*     ------- */
-  /*     J.D.Chambers    ECMWF     22.07.94 */
-
-  /*     ********************************    */
-  /*     Section 1.  Linear interpolation .. */
-  /*     ********************************    */
-
-  *kret = 0;
+  long gribrecsize;
+  nerr = grib1Sections(dbuf, dbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (rec_len);
+    }
 
-  if ( kcode == 1 )
+  if ( nerr > 0 )
     {
-      /*    Move input values to work array */
-      for ( jl = 1; jl <= ki; ++jl )
-	pw[jl + pw_dim1] = p[jl];
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (rec_len);
+    }
 
-      /*    Arrange wrap-around value in work array */
-      pw[ki + 1 + pw_dim1] = p[1];
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
 
-      /*    Set up constants to be used to figure out weighting for */
-      /*    values in interpolation. */
-      zrdi = (double) ki;
-      zdo = 1.0 / (double) ko;
+  {
+    long i;
+    int bdsLen;
+    int gribLenOld = 0;
+    int status;
+    size_t datstart, datsize;
+#if defined (HAVE_LIBAEC)
+    struct aec_stream strm;
+#else
+    SZ_com_t sz_param;          /* szip parameter block */
+#endif
+    unsigned char *dest, *source;
+    size_t destLen, sourceLen;
+    int bits_per_sample;
+    int bds_len, bds_nbits, bds_flag, lspherc, lcomplex,/* lcompress,*/ bds_ubits;
+    int bds_head = 11;
+    int bds_ext = 0;
+    int bds_zoffset, bds_zstart;
+    unsigned char *pbuf = NULL;
 
-      /*    Loop through the output points */
-      for ( jl = 1; jl <= ko; ++jl )
-	{
+    bds_zstart  = 14;
+    bds_zoffset = 12;
+    if ( llarge ) bds_zoffset += 2;
 
-	  /*    Calculate weight from the start of row */
-	  zpos = (jl - 1) * zdo;
-	  zwt = zpos * zrdi;
+    bds_len   = BDS_Len;
+    bds_len   = correct_bdslen(bds_len, gribLen, bds-dbuf);
+    bds_nbits = BDS_NumBits;
+    bds_flag  = BDS_Flag;
+    bds_ubits = bds_flag & 15;
+    lspherc   =  bds_flag >> 7;
+    lcomplex  = (bds_flag >> 6)&1;
+    /* lcompress = (bds_flag >> 4)&1; */
+    
+    if ( bds_nbits != 8 && bds_nbits != 16 && bds_nbits != 24 && bds_nbits != 32 )
+      {
+	static int linfo = 1;
+	if ( linfo && bds_nbits != 0 )
+	  {
+	    linfo = 0;
+	    fprintf(stderr, "GRIB szip only supports 8, 16, 24 and 32 bit data!\n");
+	  }
+	return (rec_len);
+      }
 
-	  /*    Get the current array position(minus 1) from the weight - */
-	  /*    note the implicit truncation. */
-	  ip = (int) zwt;
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      bits_per_sample    = 8;
+    else
+#endif
+      bits_per_sample    = bds_nbits;
 
-	  /*    If the left value is missing, use the right value */
-	  if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
-	    {
-	      p[jl] = pw[ip + 2 + pw_dim1];
-	    }
-	  /*    If the right value is missing, use the left value */
-	  else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
-	    {
-	      p[jl] = pw[ip + 1 + pw_dim1];
-	    }
-	  /*    If neither missing, interpolate ... */
-	  else
-	    {
+#if defined (HAVE_LIBAEC)
+    strm.bits_per_sample = bits_per_sample;
+    strm.block_size      = PIXELS_PER_BLOCK;
+    strm.rsi             = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
+    strm.flags           = AEC_FLAGS;
+    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
+#else
+    sz_param.options_mask        = OPTIONS_MASK;
+    sz_param.bits_per_pixel      = bits_per_sample;
+    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
+    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
+#endif
 
-	      /*       Adjust the weight to range (0.0 to 1.0) */
-	      zwt -= ip;
+    if ( lspherc )
+      {
+	if ( lcomplex  )
+	  {
+	    int jup, ioff;
+	    jup  = bds[15];
+	    ioff = (jup+1)*(jup+2);
+	    bds_ext = 4 + 3 + 4*ioff;
+	  }
+	else
+	  {
+	    bds_ext = 4;
+	  }
+      }
 
-	      /*       Interpolate using the weighted values on either side */
-	      /*       of the output point position */
-	      p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
-		zwt * pw[ip + 2 + pw_dim1];
-	    }
-	}
+    datstart = bds_head + bds_ext;
 
-      /*     *******************************    */
-      /*     Section 2.  Cubic interpolation .. */
-      /*     *******************************    */
+    datsize = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
 
-    }
-  else if ( kcode == 3 )
-    {
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          if ( IS_EQUAL(p[jl], msval) )
-	    {
-	      fprintf(stderr," ROWINA2: ");
-	      fprintf(stderr," Cubic interpolation not supported");
-	      fprintf(stderr," for fields containing missing data.\n");
-	      *kret = 1;
-	      goto L900;
-	    }
-          pw[jl + pw_dim1] = p[jl];
-	}
-      pw[pw_dim1] = p[ki];
-      pw[ki + 1 + pw_dim1] = p[1];
-      pw[ki + 2 + pw_dim1] = p[2];
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          pw[jl + (pw_dim1 << 1)] =
-	        - pw[jl - 1 + pw_dim1] / 3.0 -
-	          pw[jl     + pw_dim1] * 0.5 +
-	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
-          pw[jl + 1 + pw_dim1 * 3] =
-                  pw[jl - 1 + pw_dim1] / 6.0 -
-                  pw[jl     + pw_dim1] +
-                  pw[jl + 1 + pw_dim1] * 0.5 +
-                  pw[jl + 2 + pw_dim1] / 3.0;
-	}
+    if ( datsize < MIN_SIZE ) return (rec_len);
+    /*
+    fprintf(stderr, "%d %d %d %d\n", bds_len, datstart, bds_len - datstart, datsize);
+    */
+    sourceLen = datsize;
+    destLen   = sbufsize;
+    
+    source = bds + datstart;
+    dest = sbuf;
 
-      scm0(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
-	   &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      {
+	long nelem;
+	nelem = sourceLen/3;
+	pbuf = (unsigned char*) malloc(sourceLen);
+	for ( i = 0; i < nelem; i++ )
+	  {
+	    pbuf[        i] = source[3*i  ];
+	    pbuf[  nelem+i] = source[3*i+1];
+	    pbuf[2*nelem+i] = source[3*i+2];
+	  }
+	source = pbuf;
+      }
+#endif
 
-      zrdi = (double) ki;
-      zdo = 1.0 / (double) ko;
-      for ( jl = 1; jl <= ko; ++jl )
-	{
-          zpos = (jl - 1) * zdo;
-          zwt = zpos * zrdi;
-          ip = (int) zwt + 1;
-          zwt = zwt + 1.0 - ip;
-          zwt1 = 1.0 - zwt;
-          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
-                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
-                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
-                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
-	}
+#if defined (HAVE_LIBAEC)
+    strm.next_in = source;
+    strm.avail_in = sourceLen;
+    strm.next_out = dest;
+    strm.avail_out = destLen;
 
-    }
-  else
-    {
-      /*    **************************************    */
-      /*    Section 3.  Invalid interpolation code .. */
-      /*    **************************************    */
-      fprintf(stderr," ROWINA2:");
-      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
-      *kret = 2;
-    }
+    status = aec_buffer_encode(&strm);
+    if ( status != AEC_OK )
+      {
+       	if ( status != AEC_DATA_ERROR )
+	  Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
 
-L900:
-    return 0;
-} /* rowina2 */
+    destLen = strm.total_out;
+#else
+    status = SZ_BufftoBuffCompress(dest, &destLen, source, sourceLen, &sz_param);
+    if ( status != SZ_OK )
+      {
+	if ( status == SZ_NO_ENCODER_ERROR )
+	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_PARAM_ERROR )
+	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_MEM_ERROR )
+	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_OUTBUFF_FULL )
+	  /*Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2)*/;
+	else
+	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
+#endif
+    
+    if ( pbuf ) free(pbuf);
+    /*
+    fprintf(stderr, "sourceLen, destLen %d %d\n", sourceLen, destLen);
+    */
+    if ( destLen < MIN_COMPRESS*sourceLen )
+      {
+	source = bds + datstart + bds_zoffset;
+	memcpy(source, dest, destLen);
+	
+	/* ----++++ number of unused bits at end of section) */
 
+	BDS_Flag -= bds_ubits;
+    
+	gribLenOld = gribLen;
 
-int rowina3(double *p, int ko, int ki, double *pw,
-	    int kcode, double msval, int *kret, int omisng, int operio, int oveggy)
-{
-  /*
-C---->
-C**** ROWINA3 - Interpolation of row of values.
-C
-C     Purpose.
-C     --------
-C
-C     Interpolate a row of values.
-C
-C
-C**   Interface.
-C     ----------
-C
-C     CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
-C
-C
-C     Input Parameters.
-C     -----------------
-C
-C     P      - Row of values to be interpolated.
-C              Dimension must be at least KO.
-C
-C     KO     - Number of values required.
-C
-C     KI     - Number of values in P on input.
-C
-C     PW     - Working array.
-C              Dimension must be at least (0:KO+2,3).
-C
-C     KCODE  - Interpolation required.
-C              1 , linear.
-C              3 , cubic.
-C
-C     PMSVAL - Value used for missing data indicator.
-C
-C     OMISNG - True if missing values are present in field.
-C
-C     OPERIO - True if input field is periodic.
-C
-C     OVEGGY - True if 'nearest neighbour' processing must be used
-C              for interpolation
-C
-C     Output Parameters.
-C     ------------------
-C
-C     P     - Now contains KO values.
-C     KRET  - Return code
-C             0, OK
-C             Non-zero, error
-C
-C
-C     Method.
-C     -------
-C
-C     Linear or cubic interpolation performed as required.
-C
-C     Comments.
-C     ---------
-C
-C     This is a version of ROWINA which allows for missing data
-C     values and hence for bitmapped fields.
-C
-C
-C     Author.
-C     -------
-C
-C     J.D.Chambers    ECMWF     22.07.94
-C
-C
-C     Modifications.
-C     --------------
-C
-C     J.D.Chambers    ECMWF     13.09.94
-C     Add return code KRET and remove calls to ABORT.
-C
-C     J. Clochard, Meteo France, for ECMWF - January 1998.
-C     Addition of OMISNG and OPERIO arguments.
-C
-C
-C     -----------------------------------------------------------------
-*/
-  /* System generated locals */
-  int pw_dim1, pw_offset, i_1;
+	if ( bds_ext )
+	  for ( i = bds_ext-1; i >= 0; --i )
+	    bds[bds_zoffset+bds_head+i] = bds[bds_head+i];
 
-  /* Local variables */
-  double zwt1, zrdi, zpos;
-  int jl, ip;
-  double zdo, zwt;
+	/*
+	fprintf(stderr, "destLen, datsize, datstart %d %d %d\n", destLen, datsize, datstart);
+	*/
+	/*	memcpy(bds + datstart + bds_zoffset, source, destLen); */
+	/*
+	  fprintf(stderr, "z>>> %d %d %d %d <<<\n", (int) bds[0+datstart+bds_zoffset],
+	    (int)bds[1+datstart+bds_zoffset], (int)bds[2+datstart+bds_zoffset], (int)bds[3+datstart+bds_zoffset]);
+	*/
+	if ( llarge )
+	  {
+	    if ( gribLenOld%120 )
+	      {
+		fprintf(stderr, "Internal problem, record length not multiple of 120!");
+		while ( gribLenOld%120 ) gribLenOld++;
+	      }
+	    gribLenOld = gribLenOld / (-120);
+	    gribLenOld = JP23SET - gribLenOld + 1;
 
-  /* Parameter adjustments */
-  --p;
-  pw_dim1 = ko + 3;
-  pw_offset = pw_dim1;
-  pw -= pw_offset;
+	    SetLen3(bds, bds_zstart, gribLenOld);
+	    SetLen4(bds, bds_zstart+3, sourceLen);
+	    SetLen4(bds, bds_zstart+7, destLen);
+	  }
+	else
+	  {
+	    SetLen3(bds, bds_zstart, gribLenOld);
+	    SetLen3(bds, bds_zstart+3, sourceLen);
+	    SetLen3(bds, bds_zstart+6, destLen);
+	  }
 
-  *kret = 0;
+	bdsLen = datstart + bds_zoffset + destLen;
 
-  if ( kcode == 1 )
-    {
-      /*    Move input values to work array */
-      for ( jl = 1; jl <= ki; ++jl )
-	pw[jl + pw_dim1] = p[jl];
+	bds[11] = 0;
+	bds[12] = 0;
+#if defined (HAVE_LIBAEC)
+	BDS_Z   = Z_AEC;
+#else
+	BDS_Z   = Z_SZIP;
+#endif
 
-      if ( operio )
-	{
-	  /* Arrange wrap-around value in work array */
-	  pw[ki + 1 + pw_dim1] = p[1];
+	BDS_Flag += 16;
+	if ( (bdsLen%2) == 1 )
+	  {
+	    BDS_Flag += 8;
+	    bds[bdsLen++] = 0;
+	  }
 
-	  /* Set up constants to be used to figure out weighting for */
-	  /* values in interpolation. */
-	  zrdi = (double) ki;
-	  zdo = 1.0 / (double) ko;
-	}
-      else
-	{
-	  /* Repeat last value, to cope with "implicit truncation" below */
-	  pw[ki + 1 + pw_dim1] = p[ki];
+	SetLen3(bds, 0, bdsLen);
 
-	  /* Set up constants to be used to figure out weighting for */
-	  /* values in interpolation. */
-	  zrdi = (double) (ki-1);
-	  zdo = 1.0 / (double) (ko-1);
- 	}
+	gribLen = (bds - dbuf) + bdsLen;
 
-      /*    Loop through the output points */
-      for ( jl = 1; jl <= ko; ++jl )
-	{
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
+	dbuf[gribLen++] = '7';
 
-	  /* Calculate weight from the start of row */
-	  zpos = (jl - 1) * zdo;
-	  zwt = zpos * zrdi;
+	if ( llarge )
+	  {
+	    long itemp;
+	    long bdslen = gribLen - 4;
 
-	  /* Get the current array position(minus 1) from the weight - */
-	  /* note the implicit truncation. */
-	  ip = (int) zwt;
-		  
-	  /* Adjust the weight to range (0.0 to 1.0) */
-	  zwt -= ip;
+	    /*
+	      If a very large product, the section 4 length field holds
+	      the number of bytes in the product after section 4 upto
+	      the end of the padding bytes.
+	      This is a fixup to get round the restriction on product lengths
+	      due to the count being only 24 bits. It is only possible because
+	      the (default) rounding for GRIB products is 120 bytes.
+	    */
+	    while ( gribLen%120 ) dbuf[gribLen++] = 0;
 
-          /* If 'nearest neighbour' processing must be used */
-	  if ( oveggy )
-	    {
-              if ( zwt < 0.5 )
-                p[jl] = pw[ip + 1 + pw_dim1];
-	      else
-		p[jl] = pw[ip + 2 + pw_dim1];
-	    }
-	  else
-	    {
-	      /*    If the left value is missing, use the right value */
-	      if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
-		{
-		  p[jl] = pw[ip + 2 + pw_dim1];
-		}
-	      /*    If the right value is missing, use the left value */
-	      else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
-		{
-		  p[jl] = pw[ip + 1 + pw_dim1];
-		}
-	      /*    If neither missing, interpolate ... */
-	      else
-		{
-		  /*       Interpolate using the weighted values on either side */
-		  /*       of the output point position */
-		  p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
-		    zwt * pw[ip + 2 + pw_dim1];
-		}
-	    }
-	}
+	    itemp = gribLen / (-120);
+	    itemp = JP23SET - itemp + 1;
 
-      /*     *******************************    */
-      /*     Section 2.  Cubic interpolation .. */
-      /*     *******************************    */
+	    SetLen3(dbuf, 4, itemp);
 
-    }
-  else if ( kcode == 3 )
+	    bdslen = gribLen - bdslen;
+
+	    SetLen3(bds, 0, bdslen);
+	  }
+	else
+	  {
+	    SetLen3(dbuf, 4, gribLen);
+	  }
+      }
+    else
+      {
+      }
+    /*
+    fprintf(stderr, "%3d %3d griblen in %6d  out %6d  CR %g   slen %6d dlen %6d  CR %g\n",
+	    PDS_Parameter, PDS_Level1, gribLenOld, gribLen,
+	    ((double)gribLenOld)/gribLen, sourceLen, destLen,
+	    ((double)sourceLen)/destLen);
+    */
+  }
+
+#else
+  if ( libszwarn )
     {
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          if ( IS_EQUAL(p[jl], msval) )
-	    {
-	      fprintf(stderr," ROWINA2: ");
-	      fprintf(stderr," Cubic interpolation not supported");
-	      fprintf(stderr," for fields containing missing data.\n");
-	      *kret = 1;
-	      goto L900;
-	    }
-          pw[jl + pw_dim1] = p[jl];
-	}
-      pw[pw_dim1] = p[ki];
-      pw[ki + 1 + pw_dim1] = p[1];
-      pw[ki + 2 + pw_dim1] = p[2];
-      i_1 = ki;
-      for ( jl = 1; jl <= i_1; ++jl )
-	{
-          pw[jl + (pw_dim1 << 1)] =
-	        - pw[jl - 1 + pw_dim1] / 3.0 -
-	          pw[jl     + pw_dim1] * 0.5 +
-	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
-          pw[jl + 1 + pw_dim1 * 3] =
-                  pw[jl - 1 + pw_dim1] / 6.0 -
-                  pw[jl     + pw_dim1] +
-                  pw[jl + 1 + pw_dim1] * 0.5 +
-                  pw[jl + 2 + pw_dim1] / 3.0;
-	}
-
-      scm0(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
-	   &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
-
-      zrdi = (double) ki;
-      zdo = 1.0 / (double) ko;
-      for ( jl = 1; jl <= ko; ++jl )
-	{
-          zpos = (jl - 1) * zdo;
-          zwt = zpos * zrdi;
-          ip = (int) zwt + 1;
-          zwt = zwt + 1.0 - ip;
-          zwt1 = 1.0 - zwt;
-          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
-                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
-                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
-                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
-	}
-
+      Warning("Compression disabled, szlib or libaec not available!");
+      libszwarn = 0;
     }
+#endif
+
+  if ( llarge )
+    while ( gribLen%120 ) dbuf[gribLen++] = 0;
   else
-    {
-      /*    **************************************    */
-      /*    Section 3.  Invalid interpolation code .. */
-      /*    **************************************    */
-      fprintf(stderr," ROWINA2:");
-      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
-      *kret = 2;
-    }
+    while ( gribLen & 7 ) dbuf[gribLen++] = 0;
 
-L900:
-    return 0;
-} /* rowina3 */
+  rec_len = gribLen;
 
+  return (rec_len);
+}
 
-int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
-	    double *ztemp, double msval, int *kret)
-{
-   /* System generated locals */
-   int i_1, i_2;
-   int kcode = 1;
 
-   /* Local variables */
-   int ilii, ilio, icode;
-   double *zline = NULL;
-   double *zwork = NULL;
-   int iregno, iquano, j210, j220, j230, j240, j225;
+int  gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
+{
+#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
+  static int libszwarn = 1;
+#endif
+  int nerr;
+  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int bdsLen, recLen, gribLen = 0;
+  unsigned char *dest, *source;
+  size_t destLen, sourceLen;
+  int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
+  int bds_head = 11;
+  int bds_ext = 0;
+  int bds_zoffset, bds_zstart;
+  int datstart = 0;
+  int llarge = FALSE;
 
+  UNUSED(dbufsize);
 
-   zline = (double*) malloc(2*klon*sizeof(double));
-   if ( zline == NULL ) SysError("No Memory!");
+  long gribrecsize;
+  nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (0);
+    }
 
-   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
-   if ( zwork == NULL ) SysError("No Memory!");
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (0);
+    }
 
-   /* Parameter adjustments */
-   --pfield;
-   --kpoint;
+  bds_zstart = 14;
 
-/* **** QU2REG - Convert quasi-regular grid data to regular. */
-/*     Input Parameters. */
-/*     ----------------- */
-/*     PFIELD     - Array containing quasi-regular grid */
-/*                  data. */
-/*     KPOINT     - Array containing list of the number of */
-/*                  points on each latitude (or longitude) of */
-/*                  the quasi-regular grid. */
-/*     KLAT       - Number of latitude lines */
-/*     KLON       - Number of longitude lines */
-/*     KCODE      - Interpolation required. */
-/*                  1 , linear - data quasi-regular on */
-/*                               latitude lines. */
-/*                  3 , cubic -  data quasi-regular on */
-/*                               latitude lines. */
-/*                  11, linear - data quasi-regular on */
-/*                               longitude lines. */
-/*                  13, cubic -  data quasi-regular on */
-/*                               longitude lines. */
-/*     PMSVAL     - Value used for missing data indicator. */
-/*     Output Parameters. */
-/*     ------------------ */
-/*     KRET       - return code */
-/*                  0 = OK */
-/*                  non-zero indicates fatal error */
-/*     PFIELD     - Array containing regular grid data. */
-/*     Author. */
-/*     ------- */
-/*     J.D.Chambers     ECMWF      22.07.94 */
-/*     J.D.Chambers     ECMWF      13.09.94 */
-/*     Add return code KRET and remove calls to ABORT. */
+  recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
+  if ( recLen > JP23SET ) llarge = TRUE;
 
+  bds_zoffset = 12;
+  if ( llarge ) bds_zoffset += 2;
 
-/* ------------------------------ */
-/* Section 1. Set initial values. */
-/* ------------------------------ */
+  /* bds_len   = BDS_Len; */
+  bds_nbits = BDS_NumBits;
+  bds_flag  = BDS_Flag;
+  lspherc   =  bds_flag >> 7;
+  lcomplex  = (bds_flag >> 6)&1;
+  /* lcompress = (bds_flag >> 4)&1; */
 
-   *kret = 0;
+  if ( lspherc )
+    {
+      if ( lcomplex  )
+	{
+	  int jup, ioff;
+	  jup  = bds[bds_zoffset+15];
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	}
+      else
+	{
+	  bds_ext = 4;
+	}
+    }
 
-/* Check input parameters. */
+  datstart = bds_head + bds_ext;
 
-   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
-      fprintf(stderr," QU2REG :");
-      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
-      *kret = 1;
-      goto L900;
-   }
+  source = bds + datstart + bds_zoffset;
+  if ( llarge )
+    sourceLen = ((size_t) ((bds[21]<<24)+(bds[22]<<16)+(bds[23]<<8)+bds[24]));
+  else
+    sourceLen = ((size_t) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
 
-/* Set array indices to 0. */
+  nerr = grib1Sections(dbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+  if ( nerr < 0 )
+    {
+      fprintf(stdout, "GRIB message error\n");
+      return (0);
+    }
 
-   ilii = 0;
-   ilio = 0;
+  if ( nerr > 0 )
+    {
+      fprintf(stdout, "GRIB data corrupted!\n");
+      return (0);
+    }
 
-/* Establish values of loop parameters. */
+  dest = bds + datstart;
+   if ( llarge )
+    destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+  else
+    destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
 
-   if (kcode > 10) {
+  BDS_Flag -= 16;
 
-/*    Quasi-regular along longitude lines. */
+  bdsLen = datstart + destLen;
 
-      iquano = klon;
-      iregno = klat;
-      icode = kcode - 10;
-   } else {
+#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+  {
+    int status;
+    long i;
+    size_t tmpLen;
+    int bds_ubits;
+    int bits_per_sample;
+#if defined (HAVE_LIBAEC)
+    struct aec_stream strm;
+#else
+    SZ_com_t sz_param;          /* szip parameter block */
+#endif
 
-/*    Quasi-regular along latitude lines. */
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      bits_per_sample    = 8;
+    else
+#endif
+      bits_per_sample    = bds_nbits;
 
-      iquano = klat;
-      iregno = klon;
-      icode = kcode;
-   }
+#if defined (HAVE_LIBAEC)
+    strm.bits_per_sample         = bits_per_sample;
+    strm.block_size              = PIXELS_PER_BLOCK;
+    strm.rsi                     = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
+    strm.flags                   = AEC_FLAGS;
+    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
+#else
+    sz_param.options_mask        = OPTIONS_MASK;
+    sz_param.bits_per_pixel      = bits_per_sample;
+    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
+    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
+#endif
 
-/*     -------------------------------------------------------- */
-/**    Section 2. Interpolate field from quasi to regular grid. */
-/*     -------------------------------------------------------- */
+    if ( bds_ext )
+      for ( i = 0; i < bds_ext; ++i )
+	bds[bds_head+i] = bds[bds_zoffset+bds_head+i];
 
-   i_1 = iquano;
-   for (j230 = 1; j230 <= i_1; ++j230) {
+    /*
+    fprintf(stderr, "gribUnzip: sourceLen %ld; destLen %ld\n", (long)sourceLen, (long)destLen);
+    fprintf(stderr, "gribUnzip: sourceOff %d; destOff %d\n", bds[12], bds[11]);
+    fprintf(stderr, "gribUnzip: reclen %d; bdslen %d\n", recLen, bdsLen);
+    */
 
-      if (iregno != kpoint[j230]) {
+    tmpLen = destLen;
+#if defined (HAVE_LIBAEC)
+    strm.next_in   = source;
+    strm.avail_in  = sourceLen;
+    strm.next_out  = dest;
+    strm.avail_out = tmpLen;
 
-/*       Line contains less values than required,so */
-/*       extract quasi-regular grid values for a line */
+    status = aec_buffer_decode(&strm);
+    if ( status != AEC_OK )
+      Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
 
-         i_2 = kpoint[j230];
-         for (j210 = 1; j210 <= i_2; ++j210) {
-            ++ilii;
-            zline[j210 - 1] = pfield[ilii];
-         }
+    tmpLen = strm.total_out;
+#else
+    status = SZ_BufftoBuffDecompress(dest, &tmpLen, source, sourceLen, &sz_param);
+    if ( status != SZ_OK )
+      {
+	if ( status == SZ_NO_ENCODER_ERROR )
+	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_PARAM_ERROR )
+	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_MEM_ERROR )
+	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else if ( status == SZ_OUTBUFF_FULL )
+	  Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2);
+	else
+	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+      }
+#endif
+    /*
+    fprintf(stderr, "gribUnzip: sl = %ld  dl = %ld   tl = %ld\n",
+	    (long)sourceLen, (long)destLen,(long) tmpLen);
+    */
+    if ( tmpLen != destLen )
+      Warning("unzip size differ: code %3d level %3d  ibuflen %ld ubuflen %ld",
+	      PDS_Parameter, PDS_Level2, (long) destLen, (long) tmpLen);
 
-/*       and interpolate this line. */
+#if defined (HAVE_LIBSZ)
+    if ( bds_nbits == 24 )
+      {
+	long nelem;
+	unsigned char *pbuf;
+	nelem = tmpLen/3;
+	pbuf = (unsigned char*) malloc(tmpLen);
+	for ( i = 0; i < nelem; i++ )
+	  {
+	    pbuf[3*i  ] = dest[        i];
+	    pbuf[3*i+1] = dest[  nelem+i];
+	    pbuf[3*i+2] = dest[2*nelem+i];
+	  }
+	memcpy(dest, pbuf, tmpLen);
+	free(pbuf);
+      }
+#endif
 
-         rowina2(zline, iregno, kpoint[j230], zwork, icode, msval, kret);
-         if (*kret != 0) goto L900;
+    bds_ubits = BDS_Flag & 15;
+    BDS_Flag -= bds_ubits;
 
-/*       Add regular grid values for this line to the
-         temporary array. */
+    if ( (bdsLen%2) == 1 )
+      {
+	BDS_Flag += 8;
+	bds[bdsLen++] = 0;
+      }
 
-         i_2 = iregno;
-         for (j220 = 1; j220 <= i_2; ++j220) {
-            ++ilio;
-            ztemp[ilio - 1] = zline[j220 - 1];
-         }
+    SetLen3(bds, 0, bdsLen);
 
-      } else {
+    gribLen = (bds - dbuf) + bdsLen;
+    
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
+    dbuf[gribLen++] = '7';
 
-/*       Line contains the required number of values, so add */
-/*       this line to the temporary array. */
+    if ( llarge )
+      {
+	long itemp;
+        bdsLen = gribLen - 4;
+	/*
+	  If a very large product, the section 4 length field holds
+	  the number of bytes in the product after section 4 upto
+	  the end of the padding bytes.
+	  This is a fixup to get round the restriction on product lengths
+	  due to the count being only 24 bits. It is only possible because
+	  the (default) rounding for GRIB products is 120 bytes.
+	*/
+	while ( gribLen%120 ) dbuf[gribLen++] = 0;
 
-         i_2 = iregno;
-         for (j225 = 1; j225 <= i_2; ++j225) {
-            ++ilio;
-            ++ilii;
-            ztemp[ilio - 1] = pfield[ilii];
-         }
+	if ( gribLen != recLen )
+	  fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
+	
+	itemp = gribLen / (-120);
+	itemp = JP23SET - itemp + 1;
+	
+	SetLen3(dbuf, 4, itemp);
+
+	bdsLen = gribLen - bdsLen;
+	    
+	SetLen3(bds, 0, bdsLen);
       }
-   }
+    else
+      {
+	SetLen3(dbuf, 4, recLen);
+      }
+    /*
+    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
+    */
+    if ( llarge )
+      while ( gribLen%120 ) dbuf[gribLen++] = 0;
+    else
+      while ( gribLen & 7 ) dbuf[gribLen++] = 0;
+    /*
+    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
+    */
+  }
+#else
+  if ( libszwarn )
+    {
+      Warning("Decompression disabled, szlib or libaec not available!");
+      libszwarn = 0;
+    }
+#endif
 
-/* Copy temporary array to user array. */
+  return (gribLen);
+}
+#include <stdio.h>
+#include <math.h>
 
-   i_1 = klon * klat;
-   for (j240 = 1; j240 <= i_1; ++j240) {
-      pfield[j240] = ztemp[j240 - 1];
-   }
 
-/* -------------------------------------------------------- */
-/* Section 9. Return to calling routine. Format statements. */
-/* -------------------------------------------------------- */
+/* calculate_pfactor: source code from grib_api-1.8.0 */
+double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation)
+{
+  /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
+  long loop, index, m, n = 0;
+  double pFactor, zeps = 1.0e-15;
+  long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
+  double* weights, range, * norms;
+  double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
+  double numerator = 0.0, denominator = 0.0, slope;
 
-L900:
+  /*
+  // Setup the weights
+   */
 
-   free(zline);
-   free(zwork);
+  range = (double) (ismax - ismin +1);
 
-   return 0;
-} /* qu2reg2 */
+  weights = (double*) malloc((ismax+1)*sizeof(double));
+  for( loop = ismin; loop <= ismax; loop++ )
+    weights[loop] = range / (double) (loop-ismin+1);
+  /*
+  // Compute norms
+  // Handle values 2 at a time (real and imaginary parts).
+   */
+  norms = (double*) malloc((ismax+1)*sizeof(double));
 
+  for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
+  /*
+  // Form norms for the rows which contain part of the unscaled subset.
+   */
 
-int qu2reg3(double *pfield, int *kpoint, int klat, int klon,
-	    double msval, int *kret, int omisng, int operio, int oveggy)
-{
+  index = -2;
+  for( m = 0; m < subsetTruncation; m++ )
+    for( n = m; n <= fieldTruncation; n++ ) {
+      index += 2;
+      if( n >= subsetTruncation ) {
+        double tval = spectralField[index];
+        tval=tval<0?-tval:tval;
+        norms[n] = norms[n] > tval ? norms[n] : tval;
+        tval = spectralField[index+1];
+        tval=tval<0?-tval:tval;
+        norms[n] = norms[n] > tval ? norms[n] : tval;
+      }
+    }
   /*
-C**** QU2REG3 - Convert quasi-regular grid data to regular.
-C
-C     Purpose.
-C     --------
-C
-C     Convert quasi-regular grid data to regular,
-C     using either a linear or cubic interpolation.
-C
-C
-C**   Interface.
-C     ----------
-C
-C     CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
-C    X            OVEGGY)
-C
-C
-C     Input Parameters.
-C     -----------------
-C
-C     PFIELD     - Array containing quasi-regular grid data.
-C
-C     KPOINT     - Array containing list of the number of
-C                  points on each latitude (or longitude) of
-C                  the quasi-regular grid.
-C
-C     KLAT       - Number of latitude lines
-C
-C     KLON       - Number of longitude lines
-C
-C     KCODE      - Interpolation required.
-C                  1 , linear - data quasi-regular on latitude lines.
-C                  3 , cubic -  data quasi-regular on latitude lines.
-C                  11, linear - data quasi-regular on longitude lines.
-C                  13, cubic -  data quasi-regular on longitude lines.
-C
-C     PMSVAL     - Value used for missing data indicator.
-C
-C     OMISNG     - True if missing values are present in field.
-C
-C     OPERIO     - True if input field is periodic.
-C
-C     OVEGGY     - True if 'nearest neighbour' processing must be used
-C                  for interpolation
-C
-C
-C     Output Parameters.
-C     ------------------
-C
-C     KRET       - return code
-C                  0 = OK
-C                  non-zero indicates fatal error
-C
-C
-C     Output Parameters.
-C     ------------------
-C
-C     PFIELD     - Array containing regular grid data.
-C
-C
-C     Method.
-C     -------
-C
-C     Data is interpolated and expanded into a temporary array,
-C     which is then copied back into the user's array.
-C     Returns an error code if an invalid interpolation is requested
-C     or field size exceeds array dimensions.
-C
-C     Comments.
-C     ---------
-C
-C     This routine is an adaptation of QU2REG to allow missing data
-C     values, and hence bit mapped fields.
-C
-C
-C     Author.
-C     -------
-C
-C     J.D.Chambers     ECMWF      22.07.94
-C
-C
-C     Modifications.
-C     --------------
-C
-C     J.D.Chambers     ECMWF      13.09.94
-C     Add return code KRET and remove calls to ABORT.
-C
-C     J.D.Chambers     ECMWF        Feb 1997
-C     Allow for 64-bit pointers
-C
-C     J. Clochard, Meteo France, for ECMWF - January 1998.
-C     Addition of OMISNG and OPERIO arguments.
-C     Fix message for longitude number out of bounds, and routine
-C     name in title and formats.
-C
-*/
-   /* System generated locals */
-   int i_1, i_2;
-   int kcode = 1;
-
-   /* Local variables */
-   int ilii, ilio, icode;
-   double *ztemp = NULL;
-   double *zline = NULL;
-   double *zwork = NULL;
-   int iregno, iquano, j210, j220, j230, j240, j225;
-
-   ztemp = (double*) malloc(klon*klat*sizeof(double));
-   if ( ztemp == NULL ) SysError("No Memory!");
-
-   zline = (double*) malloc(2*klon*sizeof(double));
-   if ( zline == NULL ) SysError("No Memory!");
-
-   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
-   if ( zwork == NULL ) SysError("No Memory!");
-
-   /* Parameter adjustments */
-   --pfield;
-   --kpoint;
-
-/* ------------------------------ */
-/* Section 1. Set initial values. */
-/* ------------------------------ */
-
-   *kret = 0;
+  // Form norms for the rows which do not contain part of the unscaled subset.
+   */
 
-/* Check input parameters. */
+  for( m = subsetTruncation; m <= fieldTruncation; m++ )
+    for( n = m; n <= fieldTruncation; n++ ) {
+      double tval = spectralField[index];
+      index += 2;
+      tval=tval<0?-tval:tval;
+      norms[n] = norms[n] > tval ? norms[n] : tval;
+      tval = spectralField[index+1];
+      tval=tval<0?-tval:tval;
+      norms[n] = norms[n] > tval ? norms[n] : tval;
+    }
 
-   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
-      fprintf(stderr," QU2REG :");
-      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
-      *kret = 1;
-      goto L900;
-   }
+  /*
+  // Ensure the norms have a value which is not too small in case of
+  // problems with math functions (e.g. LOG).
+   */
 
-/* Set array indices to 0. */
+  for( loop = ismin; loop <= ismax; loop++ ) {
+    norms[n] = norms[n] > zeps ? norms[n] : zeps;
+    if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
+  }
 
-   ilii = 0;
-   ilio = 0;
+  /*
+  // Do linear fit to find the slope
+   */
 
-/* Establish values of loop parameters. */
+  for( loop = ismin; loop <= ismax; loop++ ) {
+    x = log( (double) (loop*(loop+1)) );
+    y = log( norms[loop] );
+    weightedSumOverX = weightedSumOverX + x * weights[loop];
+    weightedSumOverY = weightedSumOverY + y * weights[loop];
+    sumOfWeights = sumOfWeights + weights[loop];
+  }
+  weightedSumOverX = weightedSumOverX / sumOfWeights;
+  weightedSumOverY = weightedSumOverY / sumOfWeights;
 
-   if (kcode > 10) {
+  /*
+  // Perform a least square fit for the equation
+   */
 
-/*    Quasi-regular along longitude lines. */
+  for( loop = ismin; loop <= ismax; loop++ ) {
 
-      iquano = klon;
-      iregno = klat;
-      icode = kcode - 10;
-   } else {
+    x = log( (double)(loop*(loop+1)) );
+    y = log( norms[loop] );
+    numerator =
+      numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
+    denominator =
+      denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
+  }
+  slope = numerator / denominator;
 
-/*    Quasi-regular along latitude lines. */
+  free(weights);
+  free(norms);
 
-      iquano = klat;
-      iregno = klon;
-      icode = kcode;
-   }
+  pFactor = -slope;
+  if( pFactor < -9999.9 ) pFactor = -9999.9;
+  if( pFactor > 9999.9 )  pFactor = 9999.9;
 
-/*     -------------------------------------------------------- */
-/**    Section 2. Interpolate field from quasi to regular grid. */
-/*     -------------------------------------------------------- */
+  return pFactor;
+}
 
-   i_1 = iquano;
-   for (j230 = 1; j230 <= i_1; ++j230) {
+static
+int rowina2(double *p, int ko, int ki, double *pw,
+	    int kcode, double msval, int *kret)
+{
+  /* System generated locals */
+  int pw_dim1, pw_offset, i_1;
 
-      if (iregno != kpoint[j230]) {
+  /* Local variables */
+  double zwt1, zrdi, zpos;
+  int jl, ip;
+  double zdo, zwt;
 
-/*       Line contains less values than required,so */
-/*       extract quasi-regular grid values for a line */
+  /* Parameter adjustments */
+  --p;
+  pw_dim1 = ko + 3;
+  pw_offset = pw_dim1;
+  pw -= pw_offset;
 
-         i_2 = kpoint[j230];
-         for (j210 = 1; j210 <= i_2; ++j210) {
-            ++ilii;
-            zline[j210 - 1] = pfield[ilii];
-         }
+  /* **** ROWINA2 - Interpolation of row of values. */
+  /*     Input Parameters. */
+  /*     ----------------- */
+  /*     P      - Row of values to be interpolated. */
+  /*              Dimension must be at least KO. */
+  /*     KO     - Number of values required. */
+  /*     KI     - Number of values in P on input. */
+  /*     PW     - Working array. */
+  /*              Dimension must be at least (0:KO+2,3). */
+  /*     KCODE  - Interpolation required. */
+  /*              1 , linear. */
+  /*              3 , cubic. */
+  /*     PMSVAL - Value used for missing data indicator. */
 
-/*       and interpolate this line. */
+  /*     Output Parameters. */
+  /*     ------------------ */
+  /*     P     - Now contains KO values. */
+  /*     KRET  - Return code */
+  /*             0, OK */
+  /*             Non-zero, error */
 
-         rowina3(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
-         if (*kret != 0) goto L900;
+  /*     Author. */
+  /*     ------- */
+  /*     J.D.Chambers    ECMWF     22.07.94 */
 
-/*       Add regular grid values for this line to the
-         temporary array. */
+  /*     ********************************    */
+  /*     Section 1.  Linear interpolation .. */
+  /*     ********************************    */
 
-         i_2 = iregno;
-         for (j220 = 1; j220 <= i_2; ++j220) {
-            ++ilio;
-            ztemp[ilio - 1] = zline[j220 - 1];
-         }
+  *kret = 0;
 
-      } else {
+  if ( kcode == 1 )
+    {
+      /*    Move input values to work array */
+      for ( jl = 1; jl <= ki; ++jl )
+	pw[jl + pw_dim1] = p[jl];
 
-/*       Line contains the required number of values, so add */
-/*       this line to the temporary array. */
+      /*    Arrange wrap-around value in work array */
+      pw[ki + 1 + pw_dim1] = p[1];
 
-         i_2 = iregno;
-         for (j225 = 1; j225 <= i_2; ++j225) {
-            ++ilio;
-            ++ilii;
-            ztemp[ilio - 1] = pfield[ilii];
-         }
-      }
-   }
+      /*    Set up constants to be used to figure out weighting for */
+      /*    values in interpolation. */
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
 
-/* Copy temporary array to user array. */
+      /*    Loop through the output points */
+      for ( jl = 1; jl <= ko; ++jl )
+	{
 
-   i_1 = klon * klat;
-   for (j240 = 1; j240 <= i_1; ++j240) {
-      pfield[j240] = ztemp[j240 - 1];
-   }
+	  /*    Calculate weight from the start of row */
+	  zpos = (jl - 1) * zdo;
+	  zwt = zpos * zrdi;
 
-/* -------------------------------------------------------- */
-/* Section 9. Return to calling routine. Format statements. */
-/* -------------------------------------------------------- */
+	  /*    Get the current array position(minus 1) from the weight - */
+	  /*    note the implicit truncation. */
+	  ip = (int) zwt;
 
-L900:
+	  /*    If the left value is missing, use the right value */
+	  if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
+	    {
+	      p[jl] = pw[ip + 2 + pw_dim1];
+	    }
+	  /*    If the right value is missing, use the left value */
+	  else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
+	    {
+	      p[jl] = pw[ip + 1 + pw_dim1];
+	    }
+	  /*    If neither missing, interpolate ... */
+	  else
+	    {
 
-   free(zwork);
-   free(zline);
-   free(ztemp);
+	      /*       Adjust the weight to range (0.0 to 1.0) */
+	      zwt -= ip;
 
-   return 0;
-} /* qu2reg3 */
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
+	      /*       Interpolate using the weighted values on either side */
+	      /*       of the output point position */
+	      p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
+		zwt * pw[ip + 2 + pw_dim1];
+	    }
+	}
 
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
 
-FILE *grprsm = NULL;
-double fref;
-double fmaxval;
-int nfref;
-int nfmaxval;
-int nrnd;
-int ndbg;
-int nvck;
-int nonoff;
-int noabort;
-int num2ok;
-int next2o;
-int nloc2o;
-int nsubce;
-int grib_calendar = -1;
+    }
+  else if ( kcode == 3 )
+    {
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          if ( IS_EQUAL(p[jl], msval) )
+	    {
+	      fprintf(stderr," ROWINA2: ");
+	      fprintf(stderr," Cubic interpolation not supported");
+	      fprintf(stderr," for fields containing missing data.\n");
+	      *kret = 1;
+	      goto L900;
+	    }
+          pw[jl + pw_dim1] = p[jl];
+	}
+      pw[pw_dim1] = p[ki];
+      pw[ki + 1 + pw_dim1] = p[1];
+      pw[ki + 2 + pw_dim1] = p[2];
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          pw[jl + (pw_dim1 << 1)] =
+	        - pw[jl - 1 + pw_dim1] / 3.0 -
+	          pw[jl     + pw_dim1] * 0.5 +
+	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+          pw[jl + 1 + pw_dim1 * 3] =
+                  pw[jl - 1 + pw_dim1] / 6.0 -
+                  pw[jl     + pw_dim1] +
+                  pw[jl + 1 + pw_dim1] * 0.5 +
+                  pw[jl + 2 + pw_dim1] / 3.0;
+	}
+
+      scm0_double(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		  &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+          zpos = (jl - 1) * zdo;
+          zwt = zpos * zrdi;
+          ip = (int) zwt + 1;
+          zwt = zwt + 1.0 - ip;
+          zwt1 = 1.0 - zwt;
+          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+	}
+
+    }
+  else
+    {
+      /*    **************************************    */
+      /*    Section 3.  Invalid interpolation code .. */
+      /*    **************************************    */
+      fprintf(stderr," ROWINA2:");
+      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
+      *kret = 2;
+    }
+
+L900:
+    return 0;
+} /* rowina2 */
+
+
+
+int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
+	    double *ztemp, double msval, int *kret)
+{
+   /* System generated locals */
+   int i_1, i_2;
+   int kcode = 1;
+
+   /* Local variables */
+   int ilii, ilio, icode;
+   double *zline = NULL;
+   double *zwork = NULL;
+   int iregno, iquano, j210, j220, j230, j240, j225;
+
+
+   zline = (double*) malloc(2*klon*sizeof(double));
+   if ( zline == NULL ) SysError("No Memory!");
+
+   zwork = (double*) malloc(3*(2*klon+3)*sizeof(double));
+   if ( zwork == NULL ) SysError("No Memory!");
+
+   /* Parameter adjustments */
+   --pfield;
+   --kpoint;
+
+/* **** QU2REG - Convert quasi-regular grid data to regular. */
+/*     Input Parameters. */
+/*     ----------------- */
+/*     PFIELD     - Array containing quasi-regular grid */
+/*                  data. */
+/*     KPOINT     - Array containing list of the number of */
+/*                  points on each latitude (or longitude) of */
+/*                  the quasi-regular grid. */
+/*     KLAT       - Number of latitude lines */
+/*     KLON       - Number of longitude lines */
+/*     KCODE      - Interpolation required. */
+/*                  1 , linear - data quasi-regular on */
+/*                               latitude lines. */
+/*                  3 , cubic -  data quasi-regular on */
+/*                               latitude lines. */
+/*                  11, linear - data quasi-regular on */
+/*                               longitude lines. */
+/*                  13, cubic -  data quasi-regular on */
+/*                               longitude lines. */
+/*     PMSVAL     - Value used for missing data indicator. */
+/*     Output Parameters. */
+/*     ------------------ */
+/*     KRET       - return code */
+/*                  0 = OK */
+/*                  non-zero indicates fatal error */
+/*     PFIELD     - Array containing regular grid data. */
+/*     Author. */
+/*     ------- */
+/*     J.D.Chambers     ECMWF      22.07.94 */
+/*     J.D.Chambers     ECMWF      13.09.94 */
+/*     Add return code KRET and remove calls to ABORT. */
+
+
+/* ------------------------------ */
+/* Section 1. Set initial values. */
+/* ------------------------------ */
+
+   *kret = 0;
+
+/* Check input parameters. */
+
+   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
+      fprintf(stderr," QU2REG :");
+      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
+      *kret = 1;
+      goto L900;
+   }
+
+/* Set array indices to 0. */
+
+   ilii = 0;
+   ilio = 0;
+
+/* Establish values of loop parameters. */
+
+   if (kcode > 10) {
+
+/*    Quasi-regular along longitude lines. */
+
+      iquano = klon;
+      iregno = klat;
+      icode = kcode - 10;
+   } else {
+
+/*    Quasi-regular along latitude lines. */
+
+      iquano = klat;
+      iregno = klon;
+      icode = kcode;
+   }
+
+/*     -------------------------------------------------------- */
+/**    Section 2. Interpolate field from quasi to regular grid. */
+/*     -------------------------------------------------------- */
+
+   i_1 = iquano;
+   for (j230 = 1; j230 <= i_1; ++j230) {
+
+      if (iregno != kpoint[j230]) {
+
+/*       Line contains less values than required,so */
+/*       extract quasi-regular grid values for a line */
+
+         i_2 = kpoint[j230];
+         for (j210 = 1; j210 <= i_2; ++j210) {
+            ++ilii;
+            zline[j210 - 1] = pfield[ilii];
+         }
+
+/*       and interpolate this line. */
+
+         rowina2(zline, iregno, kpoint[j230], zwork, icode, msval, kret);
+         if (*kret != 0) goto L900;
+
+/*       Add regular grid values for this line to the
+         temporary array. */
+
+         i_2 = iregno;
+         for (j220 = 1; j220 <= i_2; ++j220) {
+            ++ilio;
+            ztemp[ilio - 1] = zline[j220 - 1];
+         }
+
+      } else {
+
+/*       Line contains the required number of values, so add */
+/*       this line to the temporary array. */
+
+         i_2 = iregno;
+         for (j225 = 1; j225 <= i_2; ++j225) {
+            ++ilio;
+            ++ilii;
+            ztemp[ilio - 1] = pfield[ilii];
+         }
+      }
+   }
+
+/* Copy temporary array to user array. */
+
+   i_1 = klon * klat;
+   for (j240 = 1; j240 <= i_1; ++j240) {
+      pfield[j240] = ztemp[j240 - 1];
+   }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+   free(zline);
+   free(zwork);
+
+   return 0;
+} /* qu2reg2 */
+
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
+{
+  double power;
+  double *scale = (double*) malloc((trunc+1)*sizeof(double));
+  int  n, m;
+  int  index;
+
+  if ( scale == NULL ) SysError("No Memory!");
+
+  if ( pcScale < -10000 || pcScale > 10000 )
+    {
+      fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
+      return;
+   }
+
+  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+
+  if ( pcScale == 0 ) return;
+
+  power = (double) pcScale / 1000.;
+  scale[0] = 1.0;
+
+  for ( n = 1; n <= trunc; n++ )
+    {
+      if (pcScale != 1000)
+         scale[n] = pow((double) (n*(n+1)), power);
+      else
+         scale[n] =     (double) (n*(n+1));
+    }
+
+  if ( inv )
+    for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+
+  /* Scale the values */
+
+  index = 0;
+
+  for ( m = 0;   m < pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n >= pcStart )
+	  {
+	    fpdata[index  ] *= scale[n];
+	    fpdata[index+1] *= scale[n];
+	  }
+	index += 2;
+      }
+
+  for ( m = pcStart; m <= trunc; m++ )
+    for ( n = m;     n <= trunc; n++ )
+      {
+	fpdata[index  ] *= scale[n];
+	fpdata[index+1] *= scale[n];
+	index += 2;
+      }
+
+  free(scale);
+}
+
+
+void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+{
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
+}
+
+
+void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+{
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
+}
+
+
+void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
+{
+  /* System generated locals */
+  double r_1;
+
+  /* Local variables */
+  int jl;
+  double zfac, zeps, zbeta;
+  double zalpha;
+
+  /* **** SCM0   - Apply SCM0 limiter to derivative estimates. */
+  /* output: */
+  /*   pdl   = the limited derivative at the left edge of the interval */
+  /*   pdr   = the limited derivative at the right edge of the interval */
+  /* inputs */
+  /*   pdl   = the original derivative at the left edge */
+  /*   pdr   = the original derivative at the right edge */
+  /*   pfl   = function value at the left edge of the interval */
+  /*   pfr   = function value at the right edge of the interval */
+  /*   klg   = number of intervals where the derivatives are limited */
+
+  /*  define constants */
+
+  zeps = 1.0e-12;
+  zfac = (1.0 - zeps) * 3.0;
+
+  for ( jl = 0; jl < klg; ++jl )
+    {
+      if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
+	{
+	  zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
+	  zbeta  = pdr[jl] / (pfr[jl] - pfl[jl]);
+	  if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
+	  if ( zbeta  <= 0.0 ) pdr[jl] = 0.0;
+	  if ( zalpha > zfac ) pdl[jl] = zfac * (pfr[jl] - pfl[jl]);
+	  if ( zbeta  > zfac ) pdr[jl] = zfac * (pfr[jl] - pfl[jl]);
+	}
+      else
+	{
+	  pdl[jl] = 0.0;
+	  pdr[jl] = 0.0;
+	}
+    }
+} /* scm0 */
+
+static
+int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
+			int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
+{
+  /*
+C---->
+C**** ROWINA3 - Interpolation of row of values.
+C
+C     Purpose.
+C     --------
+C
+C     Interpolate a row of values.
+C
+C
+C**   Interface.
+C     ----------
+C
+C     CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
+C
+C
+C     Input Parameters.
+C     -----------------
+C
+C     P      - Row of values to be interpolated.
+C              Dimension must be at least KO.
+C
+C     KO     - Number of values required.
+C
+C     KI     - Number of values in P on input.
+C
+C     PW     - Working array.
+C              Dimension must be at least (0:KO+2,3).
+C
+C     KCODE  - Interpolation required.
+C              1 , linear.
+C              3 , cubic.
+C
+C     PMSVAL - Value used for missing data indicator.
+C
+C     OMISNG - True if missing values are present in field.
+C
+C     OPERIO - True if input field is periodic.
+C
+C     OVEGGY - True if 'nearest neighbour' processing must be used
+C              for interpolation
+C
+C     Output Parameters.
+C     ------------------
+C
+C     P     - Now contains KO values.
+C     KRET  - Return code
+C             0, OK
+C             Non-zero, error
+C
+C
+C     Method.
+C     -------
+C
+C     Linear or cubic interpolation performed as required.
+C
+C     Comments.
+C     ---------
+C
+C     This is a version of ROWINA which allows for missing data
+C     values and hence for bitmapped fields.
+C
+C
+C     Author.
+C     -------
+C
+C     J.D.Chambers    ECMWF     22.07.94
+C
+C
+C     Modifications.
+C     --------------
+C
+C     J.D.Chambers    ECMWF     13.09.94
+C     Add return code KRET and remove calls to ABORT.
+C
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C
+C
+C     -----------------------------------------------------------------
+*/
+  /* System generated locals */
+  int pw_dim1, pw_offset, i_1;
+
+  /* Local variables */
+  int jl, ip;
+  double zwt1, zrdi, zpos;
+  double zdo, zwt;
+
+  UNUSED(omisng);
+
+  /* Parameter adjustments */
+  --p;
+  pw_dim1 = ko + 3;
+  pw_offset = pw_dim1;
+  pw -= pw_offset;
+
+  *kret = 0;
+
+  if ( kcode == 1 )
+    {
+      /*    Move input values to work array */
+      for ( jl = 1; jl <= ki; ++jl )
+	pw[jl + pw_dim1] = p[jl];
+
+      if ( operio )
+	{
+	  /* Arrange wrap-around value in work array */
+	  pw[ki + 1 + pw_dim1] = p[1];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) ki;
+	  zdo = 1.0 / (double) ko;
+	}
+      else
+	{
+	  /* Repeat last value, to cope with "implicit truncation" below */
+	  pw[ki + 1 + pw_dim1] = p[ki];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) (ki-1);
+	  zdo = 1.0 / (double) (ko-1);
+ 	}
+
+      /*    Loop through the output points */
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+
+	  /* Calculate weight from the start of row */
+	  zpos = (jl - 1) * zdo;
+	  zwt = zpos * zrdi;
+
+	  /* Get the current array position(minus 1) from the weight - */
+	  /* note the implicit truncation. */
+	  ip = (int) zwt;
+		  
+	  /* Adjust the weight to range (0.0 to 1.0) */
+	  zwt -= ip;
+
+          /* If 'nearest neighbour' processing must be used */
+	  if ( oveggy )
+	    {
+              if ( zwt < 0.5 )
+                p[jl] = pw[ip + 1 + pw_dim1];
+	      else
+		p[jl] = pw[ip + 2 + pw_dim1];
+	    }
+	  else
+	    {
+	      /*    If the left value is missing, use the right value */
+	      if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 2 + pw_dim1];
+		}
+	      /*    If the right value is missing, use the left value */
+	      else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 1 + pw_dim1];
+		}
+	      /*    If neither missing, interpolate ... */
+	      else
+		{
+		  /*  Interpolate using the weighted values on either side */
+		  /*  of the output point position */
+		  p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
+		                  zwt * pw[ip+2 + pw_dim1];
+		}
+	    }
+	}
+    }
+  else if ( kcode == 3 )
+    {
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          if ( IS_EQUAL(p[jl], msval) )
+	    {
+	      fprintf(stderr," ROWINA3: ");
+	      fprintf(stderr," Cubic interpolation not supported");
+	      fprintf(stderr," for fields containing missing data.\n");
+	      *kret = 1;
+	      goto L900;
+	    }
+          pw[jl + pw_dim1] = p[jl];
+	}
+      pw[pw_dim1] = p[ki];
+      pw[ki + 1 + pw_dim1] = p[1];
+      pw[ki + 2 + pw_dim1] = p[2];
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          pw[jl + (pw_dim1 << 1)] =
+	        - pw[jl - 1 + pw_dim1] / 3.0 -
+	          pw[jl     + pw_dim1] * 0.5 +
+	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+          pw[jl + 1 + pw_dim1 * 3] =
+                  pw[jl - 1 + pw_dim1] / 6.0 -
+                  pw[jl     + pw_dim1] +
+                  pw[jl + 1 + pw_dim1] * 0.5 +
+                  pw[jl + 2 + pw_dim1] / 3.0;
+	}
+
+      TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		       &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+          zpos = (jl - 1) * zdo;
+          zwt = zpos * zrdi;
+          ip = (int) zwt + 1;
+          zwt = zwt + 1.0 - ip;
+          zwt1 = 1.0 - zwt;
+          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+	}
+
+    }
+  else
+    {
+      /*    **************************************    */
+      /*    Section 3.  Invalid interpolation code .. */
+      /*    **************************************    */
+      fprintf(stderr," ROWINA3:");
+      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
+      *kret = 2;
+    }
+
+L900:
+    return 0;
+} /* rowina3 */
+
+
+int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
+			T msval, int *kret, int omisng, int operio, int oveggy)
+{
+  /*
+C**** QU2REG3 - Convert quasi-regular grid data to regular.
+C
+C     Purpose.
+C     --------
+C
+C     Convert quasi-regular grid data to regular,
+C     using either a linear or cubic interpolation.
+C
+C
+C**   Interface.
+C     ----------
+C
+C     CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
+C    X            OVEGGY)
+C
+C
+C     Input Parameters.
+C     -----------------
+C
+C     PFIELD     - Array containing quasi-regular grid data.
+C
+C     KPOINT     - Array containing list of the number of
+C                  points on each latitude (or longitude) of
+C                  the quasi-regular grid.
+C
+C     KLAT       - Number of latitude lines
+C
+C     KLON       - Number of longitude lines
+C
+C     KCODE      - Interpolation required.
+C                  1 , linear - data quasi-regular on latitude lines.
+C                  3 , cubic -  data quasi-regular on latitude lines.
+C                  11, linear - data quasi-regular on longitude lines.
+C                  13, cubic -  data quasi-regular on longitude lines.
+C
+C     PMSVAL     - Value used for missing data indicator.
+C
+C     OMISNG     - True if missing values are present in field.
+C
+C     OPERIO     - True if input field is periodic.
+C
+C     OVEGGY     - True if 'nearest neighbour' processing must be used
+C                  for interpolation
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     KRET       - return code
+C                  0 = OK
+C                  non-zero indicates fatal error
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     PFIELD     - Array containing regular grid data.
+C
+C
+C     Method.
+C     -------
+C
+C     Data is interpolated and expanded into a temporary array,
+C     which is then copied back into the user's array.
+C     Returns an error code if an invalid interpolation is requested
+C     or field size exceeds array dimensions.
+C
+C     Comments.
+C     ---------
+C
+C     This routine is an adaptation of QU2REG to allow missing data
+C     values, and hence bit mapped fields.
+C
+C
+C     Author.
+C     -------
+C
+C     J.D.Chambers     ECMWF      22.07.94
+C
+C
+C     Modifications.
+C     --------------
+C
+C     J.D.Chambers     ECMWF      13.09.94
+C     Add return code KRET and remove calls to ABORT.
+C
+C     J.D.Chambers     ECMWF        Feb 1997
+C     Allow for 64-bit pointers
+C
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C     Fix message for longitude number out of bounds, and routine
+C     name in title and formats.
+C
+*/
+   /* System generated locals */
+   int i_1, i_2;
+   int kcode = 1;
+
+   /* Local variables */
+   int ilii, ilio, icode;
+   int iregno, iquano, j210, j220, j230, j240, j225;
+   T *ztemp = NULL;
+   T *zline = NULL;
+   T *zwork = NULL;
+
+   ztemp = (T*) malloc(klon*klat*sizeof(T));
+   if ( ztemp == NULL ) SysError("No Memory!");
+
+   zline = (T*) malloc(2*klon*sizeof(T));
+   if ( zline == NULL ) SysError("No Memory!");
+
+   zwork = (T*) malloc(3*(2*klon+3)*sizeof(T));
+   if ( zwork == NULL ) SysError("No Memory!");
+
+   /* Parameter adjustments */
+   --pfield;
+   --kpoint;
+
+/* ------------------------------ */
+/* Section 1. Set initial values. */
+/* ------------------------------ */
+
+   *kret = 0;
+
+/* Check input parameters. */
+
+   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
+      fprintf(stderr," QU2REG :");
+      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
+      *kret = 1;
+      goto L900;
+   }
+
+/* Set array indices to 0. */
+
+   ilii = 0;
+   ilio = 0;
+
+/* Establish values of loop parameters. */
+
+   if (kcode > 10) {
+
+/*    Quasi-regular along longitude lines. */
+
+      iquano = klon;
+      iregno = klat;
+      icode = kcode - 10;
+   } else {
+
+/*    Quasi-regular along latitude lines. */
+
+      iquano = klat;
+      iregno = klon;
+      icode = kcode;
+   }
+
+/*     -------------------------------------------------------- */
+/**    Section 2. Interpolate field from quasi to regular grid. */
+/*     -------------------------------------------------------- */
+
+   i_1 = iquano;
+   for (j230 = 1; j230 <= i_1; ++j230) {
+
+      if (iregno != kpoint[j230]) {
+
+/*       Line contains less values than required,so */
+/*       extract quasi-regular grid values for a line */
+
+         i_2 = kpoint[j230];
+         for (j210 = 1; j210 <= i_2; ++j210) {
+            ++ilii;
+            zline[j210 - 1] = pfield[ilii];
+         }
+
+/*       and interpolate this line. */
+
+         TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
+         if (*kret != 0) goto L900;
+
+/*       Add regular grid values for this line to the
+         temporary array. */
+
+         i_2 = iregno;
+         for (j220 = 1; j220 <= i_2; ++j220) {
+            ++ilio;
+            ztemp[ilio - 1] = zline[j220 - 1];
+         }
+
+      } else {
+
+/*       Line contains the required number of values, so add */
+/*       this line to the temporary array. */
+
+         i_2 = iregno;
+         for (j225 = 1; j225 <= i_2; ++j225) {
+            ++ilio;
+            ++ilii;
+            ztemp[ilio - 1] = pfield[ilii];
+         }
+      }
+   }
+
+/* Copy temporary array to user array. */
+
+   i_1 = klon * klat;
+   for (j240 = 1; j240 <= i_1; ++j240) {
+      pfield[j240] = ztemp[j240 - 1];
+   }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+   free(zwork);
+   free(zline);
+   free(ztemp);
+
+   return 0;
+} /* qu2reg3 */
+
+#endif /* T */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
+{
+  double power;
+  double *scale = (double*) malloc((trunc+1)*sizeof(double));
+  int  n, m;
+  int  index;
+
+  if ( scale == NULL ) SysError("No Memory!");
+
+  if ( pcScale < -10000 || pcScale > 10000 )
+    {
+      fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
+      return;
+   }
+
+  /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
+
+  if ( pcScale == 0 ) return;
+
+  power = (double) pcScale / 1000.;
+  scale[0] = 1.0;
+
+  for ( n = 1; n <= trunc; n++ )
+    {
+      if (pcScale != 1000)
+         scale[n] = pow((double) (n*(n+1)), power);
+      else
+         scale[n] =     (double) (n*(n+1));
+    }
+
+  if ( inv )
+    for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+
+  /* Scale the values */
+
+  index = 0;
+
+  for ( m = 0;   m < pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n >= pcStart )
+	  {
+	    fpdata[index  ] *= scale[n];
+	    fpdata[index+1] *= scale[n];
+	  }
+	index += 2;
+      }
+
+  for ( m = pcStart; m <= trunc; m++ )
+    for ( n = m;     n <= trunc; n++ )
+      {
+	fpdata[index  ] *= scale[n];
+	fpdata[index+1] *= scale[n];
+	index += 2;
+      }
+
+  free(scale);
+}
+
+
+void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+{
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[index  ] = fpdata[inext++];
+	    fphelp[index+1] = fpdata[inext++];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
+}
+
+
+void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+{
+  T *fphelp = (T*) malloc(nsp*sizeof(T));
+  int  m, n;
+  int  index, inext;
+
+  if ( fphelp == NULL ) SysError("No Memory!");
+
+  index = inext = 0;
+
+  for ( m = 0;   m <= pcStart; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( pcStart >= n )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  index = 0;
+  for ( m = 0;   m <= trunc; m++ )
+    for ( n = m; n <= trunc; n++ )
+      {
+	if ( n > pcStart )
+	  {
+	    fphelp[inext++] = fpdata[index];
+	    fphelp[inext++] = fpdata[index+1];
+	  }
+	index += 2;
+      }
+
+  for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+
+  free(fphelp);
+}
+
+
+void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
+{
+  /* System generated locals */
+  double r_1;
+
+  /* Local variables */
+  int jl;
+  double zfac, zeps, zbeta;
+  double zalpha;
+
+  /* **** SCM0   - Apply SCM0 limiter to derivative estimates. */
+  /* output: */
+  /*   pdl   = the limited derivative at the left edge of the interval */
+  /*   pdr   = the limited derivative at the right edge of the interval */
+  /* inputs */
+  /*   pdl   = the original derivative at the left edge */
+  /*   pdr   = the original derivative at the right edge */
+  /*   pfl   = function value at the left edge of the interval */
+  /*   pfr   = function value at the right edge of the interval */
+  /*   klg   = number of intervals where the derivatives are limited */
+
+  /*  define constants */
+
+  zeps = 1.0e-12;
+  zfac = (1.0 - zeps) * 3.0;
+
+  for ( jl = 0; jl < klg; ++jl )
+    {
+      if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
+	{
+	  zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
+	  zbeta  = pdr[jl] / (pfr[jl] - pfl[jl]);
+	  if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
+	  if ( zbeta  <= 0.0 ) pdr[jl] = 0.0;
+	  if ( zalpha > zfac ) pdl[jl] = zfac * (pfr[jl] - pfl[jl]);
+	  if ( zbeta  > zfac ) pdr[jl] = zfac * (pfr[jl] - pfl[jl]);
+	}
+      else
+	{
+	  pdl[jl] = 0.0;
+	  pdr[jl] = 0.0;
+	}
+    }
+} /* scm0 */
+
+static
+int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
+			int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
+{
+  /*
+C---->
+C**** ROWINA3 - Interpolation of row of values.
+C
+C     Purpose.
+C     --------
+C
+C     Interpolate a row of values.
+C
+C
+C**   Interface.
+C     ----------
+C
+C     CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
+C
+C
+C     Input Parameters.
+C     -----------------
+C
+C     P      - Row of values to be interpolated.
+C              Dimension must be at least KO.
+C
+C     KO     - Number of values required.
+C
+C     KI     - Number of values in P on input.
+C
+C     PW     - Working array.
+C              Dimension must be at least (0:KO+2,3).
+C
+C     KCODE  - Interpolation required.
+C              1 , linear.
+C              3 , cubic.
+C
+C     PMSVAL - Value used for missing data indicator.
+C
+C     OMISNG - True if missing values are present in field.
+C
+C     OPERIO - True if input field is periodic.
+C
+C     OVEGGY - True if 'nearest neighbour' processing must be used
+C              for interpolation
+C
+C     Output Parameters.
+C     ------------------
+C
+C     P     - Now contains KO values.
+C     KRET  - Return code
+C             0, OK
+C             Non-zero, error
+C
+C
+C     Method.
+C     -------
+C
+C     Linear or cubic interpolation performed as required.
+C
+C     Comments.
+C     ---------
+C
+C     This is a version of ROWINA which allows for missing data
+C     values and hence for bitmapped fields.
+C
+C
+C     Author.
+C     -------
+C
+C     J.D.Chambers    ECMWF     22.07.94
+C
+C
+C     Modifications.
+C     --------------
+C
+C     J.D.Chambers    ECMWF     13.09.94
+C     Add return code KRET and remove calls to ABORT.
+C
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C
+C
+C     -----------------------------------------------------------------
+*/
+  /* System generated locals */
+  int pw_dim1, pw_offset, i_1;
+
+  /* Local variables */
+  int jl, ip;
+  double zwt1, zrdi, zpos;
+  double zdo, zwt;
+
+  UNUSED(omisng);
+
+  /* Parameter adjustments */
+  --p;
+  pw_dim1 = ko + 3;
+  pw_offset = pw_dim1;
+  pw -= pw_offset;
+
+  *kret = 0;
+
+  if ( kcode == 1 )
+    {
+      /*    Move input values to work array */
+      for ( jl = 1; jl <= ki; ++jl )
+	pw[jl + pw_dim1] = p[jl];
+
+      if ( operio )
+	{
+	  /* Arrange wrap-around value in work array */
+	  pw[ki + 1 + pw_dim1] = p[1];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) ki;
+	  zdo = 1.0 / (double) ko;
+	}
+      else
+	{
+	  /* Repeat last value, to cope with "implicit truncation" below */
+	  pw[ki + 1 + pw_dim1] = p[ki];
+
+	  /* Set up constants to be used to figure out weighting for */
+	  /* values in interpolation. */
+	  zrdi = (double) (ki-1);
+	  zdo = 1.0 / (double) (ko-1);
+ 	}
+
+      /*    Loop through the output points */
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+
+	  /* Calculate weight from the start of row */
+	  zpos = (jl - 1) * zdo;
+	  zwt = zpos * zrdi;
+
+	  /* Get the current array position(minus 1) from the weight - */
+	  /* note the implicit truncation. */
+	  ip = (int) zwt;
+		  
+	  /* Adjust the weight to range (0.0 to 1.0) */
+	  zwt -= ip;
+
+          /* If 'nearest neighbour' processing must be used */
+	  if ( oveggy )
+	    {
+              if ( zwt < 0.5 )
+                p[jl] = pw[ip + 1 + pw_dim1];
+	      else
+		p[jl] = pw[ip + 2 + pw_dim1];
+	    }
+	  else
+	    {
+	      /*    If the left value is missing, use the right value */
+	      if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 2 + pw_dim1];
+		}
+	      /*    If the right value is missing, use the left value */
+	      else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
+		{
+		  p[jl] = pw[ip + 1 + pw_dim1];
+		}
+	      /*    If neither missing, interpolate ... */
+	      else
+		{
+		  /*  Interpolate using the weighted values on either side */
+		  /*  of the output point position */
+		  p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
+		                  zwt * pw[ip+2 + pw_dim1];
+		}
+	    }
+	}
+    }
+  else if ( kcode == 3 )
+    {
+      /*     *******************************    */
+      /*     Section 2.  Cubic interpolation .. */
+      /*     *******************************    */
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          if ( IS_EQUAL(p[jl], msval) )
+	    {
+	      fprintf(stderr," ROWINA3: ");
+	      fprintf(stderr," Cubic interpolation not supported");
+	      fprintf(stderr," for fields containing missing data.\n");
+	      *kret = 1;
+	      goto L900;
+	    }
+          pw[jl + pw_dim1] = p[jl];
+	}
+      pw[pw_dim1] = p[ki];
+      pw[ki + 1 + pw_dim1] = p[1];
+      pw[ki + 2 + pw_dim1] = p[2];
+      i_1 = ki;
+      for ( jl = 1; jl <= i_1; ++jl )
+	{
+          pw[jl + (pw_dim1 << 1)] =
+	        - pw[jl - 1 + pw_dim1] / 3.0 -
+	          pw[jl     + pw_dim1] * 0.5 +
+	          pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+          pw[jl + 1 + pw_dim1 * 3] =
+                  pw[jl - 1 + pw_dim1] / 6.0 -
+                  pw[jl     + pw_dim1] +
+                  pw[jl + 1 + pw_dim1] * 0.5 +
+                  pw[jl + 2 + pw_dim1] / 3.0;
+	}
+
+      TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
+		       &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
+
+      zrdi = (double) ki;
+      zdo = 1.0 / (double) ko;
+      for ( jl = 1; jl <= ko; ++jl )
+	{
+          zpos = (jl - 1) * zdo;
+          zwt = zpos * zrdi;
+          ip = (int) zwt + 1;
+          zwt = zwt + 1.0 - ip;
+          zwt1 = 1.0 - zwt;
+          p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+                  zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+                  ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+                  zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+	}
+
+    }
+  else
+    {
+      /*    **************************************    */
+      /*    Section 3.  Invalid interpolation code .. */
+      /*    **************************************    */
+      fprintf(stderr," ROWINA3:");
+      fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
+      *kret = 2;
+    }
+
+L900:
+    return 0;
+} /* rowina3 */
+
+
+int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
+			T msval, int *kret, int omisng, int operio, int oveggy)
+{
+  /*
+C**** QU2REG3 - Convert quasi-regular grid data to regular.
+C
+C     Purpose.
+C     --------
+C
+C     Convert quasi-regular grid data to regular,
+C     using either a linear or cubic interpolation.
+C
+C
+C**   Interface.
+C     ----------
+C
+C     CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
+C    X            OVEGGY)
+C
+C
+C     Input Parameters.
+C     -----------------
+C
+C     PFIELD     - Array containing quasi-regular grid data.
+C
+C     KPOINT     - Array containing list of the number of
+C                  points on each latitude (or longitude) of
+C                  the quasi-regular grid.
+C
+C     KLAT       - Number of latitude lines
+C
+C     KLON       - Number of longitude lines
+C
+C     KCODE      - Interpolation required.
+C                  1 , linear - data quasi-regular on latitude lines.
+C                  3 , cubic -  data quasi-regular on latitude lines.
+C                  11, linear - data quasi-regular on longitude lines.
+C                  13, cubic -  data quasi-regular on longitude lines.
+C
+C     PMSVAL     - Value used for missing data indicator.
+C
+C     OMISNG     - True if missing values are present in field.
+C
+C     OPERIO     - True if input field is periodic.
+C
+C     OVEGGY     - True if 'nearest neighbour' processing must be used
+C                  for interpolation
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     KRET       - return code
+C                  0 = OK
+C                  non-zero indicates fatal error
+C
+C
+C     Output Parameters.
+C     ------------------
+C
+C     PFIELD     - Array containing regular grid data.
+C
+C
+C     Method.
+C     -------
+C
+C     Data is interpolated and expanded into a temporary array,
+C     which is then copied back into the user's array.
+C     Returns an error code if an invalid interpolation is requested
+C     or field size exceeds array dimensions.
+C
+C     Comments.
+C     ---------
+C
+C     This routine is an adaptation of QU2REG to allow missing data
+C     values, and hence bit mapped fields.
+C
+C
+C     Author.
+C     -------
+C
+C     J.D.Chambers     ECMWF      22.07.94
+C
+C
+C     Modifications.
+C     --------------
+C
+C     J.D.Chambers     ECMWF      13.09.94
+C     Add return code KRET and remove calls to ABORT.
+C
+C     J.D.Chambers     ECMWF        Feb 1997
+C     Allow for 64-bit pointers
+C
+C     J. Clochard, Meteo France, for ECMWF - January 1998.
+C     Addition of OMISNG and OPERIO arguments.
+C     Fix message for longitude number out of bounds, and routine
+C     name in title and formats.
+C
+*/
+   /* System generated locals */
+   int i_1, i_2;
+   int kcode = 1;
+
+   /* Local variables */
+   int ilii, ilio, icode;
+   int iregno, iquano, j210, j220, j230, j240, j225;
+   T *ztemp = NULL;
+   T *zline = NULL;
+   T *zwork = NULL;
+
+   ztemp = (T*) malloc(klon*klat*sizeof(T));
+   if ( ztemp == NULL ) SysError("No Memory!");
+
+   zline = (T*) malloc(2*klon*sizeof(T));
+   if ( zline == NULL ) SysError("No Memory!");
+
+   zwork = (T*) malloc(3*(2*klon+3)*sizeof(T));
+   if ( zwork == NULL ) SysError("No Memory!");
+
+   /* Parameter adjustments */
+   --pfield;
+   --kpoint;
+
+/* ------------------------------ */
+/* Section 1. Set initial values. */
+/* ------------------------------ */
+
+   *kret = 0;
+
+/* Check input parameters. */
+
+   if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
+      fprintf(stderr," QU2REG :");
+      fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
+      *kret = 1;
+      goto L900;
+   }
+
+/* Set array indices to 0. */
+
+   ilii = 0;
+   ilio = 0;
+
+/* Establish values of loop parameters. */
+
+   if (kcode > 10) {
+
+/*    Quasi-regular along longitude lines. */
+
+      iquano = klon;
+      iregno = klat;
+      icode = kcode - 10;
+   } else {
+
+/*    Quasi-regular along latitude lines. */
+
+      iquano = klat;
+      iregno = klon;
+      icode = kcode;
+   }
+
+/*     -------------------------------------------------------- */
+/**    Section 2. Interpolate field from quasi to regular grid. */
+/*     -------------------------------------------------------- */
+
+   i_1 = iquano;
+   for (j230 = 1; j230 <= i_1; ++j230) {
+
+      if (iregno != kpoint[j230]) {
+
+/*       Line contains less values than required,so */
+/*       extract quasi-regular grid values for a line */
+
+         i_2 = kpoint[j230];
+         for (j210 = 1; j210 <= i_2; ++j210) {
+            ++ilii;
+            zline[j210 - 1] = pfield[ilii];
+         }
+
+/*       and interpolate this line. */
+
+         TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
+         if (*kret != 0) goto L900;
+
+/*       Add regular grid values for this line to the
+         temporary array. */
+
+         i_2 = iregno;
+         for (j220 = 1; j220 <= i_2; ++j220) {
+            ++ilio;
+            ztemp[ilio - 1] = zline[j220 - 1];
+         }
+
+      } else {
+
+/*       Line contains the required number of values, so add */
+/*       this line to the temporary array. */
+
+         i_2 = iregno;
+         for (j225 = 1; j225 <= i_2; ++j225) {
+            ++ilio;
+            ++ilii;
+            ztemp[ilio - 1] = pfield[ilii];
+         }
+      }
+   }
+
+/* Copy temporary array to user array. */
+
+   i_1 = klon * klat;
+   for (j240 = 1; j240 <= i_1; ++j240) {
+      pfield[j240] = ztemp[j240 - 1];
+   }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+   free(zwork);
+   free(zline);
+   free(ztemp);
+
+   return 0;
+} /* qu2reg3 */
+
+#endif /* T */
+#include <string.h>
+
+
+
+int gribVersion(unsigned char *is, size_t buffersize)
+{
+  if ( buffersize < 8 )
+    Error("Buffer too small (current size %d)!", (int) buffersize);
+
+  return (GRIB_EDITION(is));
+}
+
+static 
+double GET_Real(unsigned char *grib)
+{
+  int iexp, imant;
+
+  iexp  = GET_UINT1(grib[0]);
+  imant = GET_UINT3(grib[1], grib[2], grib[3]);
+
+  return (decfp2(iexp, imant));
+}
+
+static 
+int decodeIS(unsigned char *is, int *isec0, int *iret)
+{
+  int isLen = 0;
+  int grib1offset;
+  int lgrib = FALSE, lbudg = FALSE, ltide = FALSE;
+
+  /*
+    Octets 1 - 4 : The letters G R I B.
+    Four 8 bit fields.
+  */
+  /*
+    Check letters -> GRIB, BUDG or TIDE.
+  */
+  /*
+    Check that 'GRIB' is found where expected.
+  */
+  if ( GRIB_START(is) ) lgrib = TRUE;
+  /*
+    ECMWF pseudo-grib data uses 'BUDG' and 'TIDE'.
+  */
+  if ( BUDG_START(is) ) lbudg = TRUE;
+  if ( TIDE_START(is) ) ltide = TRUE;
+  /*
+    Data is not GRIB or pseudo-grib.
+  */
+  if ( lgrib == FALSE && lbudg == FALSE && ltide == FALSE )
+    {
+      *iret = 305;
+      gprintf(__func__, "Input data is not GRIB or pseudo-grib.");
+      gprintf(__func__, "Return code = %d", *iret);
+    }
+  if ( lbudg == TRUE || ltide == TRUE )
+    {
+      *iret = 305;
+      gprintf(__func__, "Pseudo-grib data unsupported.");
+      gprintf(__func__, "Return code = %d", *iret);
+    }
+
+  /*
+    Octets 5 - 7 : Length of message.
+    One 24 bit field.
+  */
+  ISEC0_GRIB_Len = GRIB1_SECLEN(is);
+  /*
+    Octet 8 : GRIB Edition Number.
+    One 8 bit field.
+  */
+  ISEC0_GRIB_Version = GRIB_EDITION(is);
+
+  if ( ISEC0_GRIB_Version > 1 )
+    Error("GRIB version %d unsupported!", ISEC0_GRIB_Version);
+
+  grib1offset = ISEC0_GRIB_Version * 4;
+
+  isLen = 4 + grib1offset;
+
+  return (isLen);
+}
+
+static 
+void decodePDS_ECMWF_local_Extension_1(unsigned char *pds, int *isec1)
+{
+  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier       */
+  isec1[37] = GET_UINT1(pds[41]);         /* Class                      */
+  isec1[38] = GET_UINT1(pds[42]);         /* Type                       */
+  isec1[39] = GET_UINT2(pds[43],pds[44]); /* Stream                     */
+  /* isec1[40] = GET_UINT4(pds[45],pds[46],pds[47],pds[48]); */
+  memcpy((char*) &isec1[40], &pds[45], 4);
+  isec1[41] = GET_UINT1(pds[49]);         /* Forecast number            */
+  isec1[42] = GET_UINT1(pds[50]);         /* Total number of forecasts  */
+}
+
+static 
+void decodePDS_DWD_local_Extension_254(unsigned char *pds, int *isec1)
+{
+  long i;
+  int isvn;
+
+  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
+  for ( i = 0; i < 11; i++ ) 
+    { 
+      isec1[37+i] =  GET_UINT1(pds[41+i]);
+    } 
+
+  isvn = GET_UINT2(pds[52],pds[53]);
+  
+  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
+  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
+
+}
+
+static 
+void decodePDS_DWD_local_Extension_253(unsigned char *pds, int *isec1)
+{
+  long i;
+  int isvn;
+
+  isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
+  for ( i = 0; i < 11; i++ ) 
+    { 
+      isec1[37+i] =  GET_UINT1(pds[41+i]);
+    } 
+
+  isvn = GET_UINT2(pds[52],pds[53]);
+  
+  isec1[48] =  isvn % 0x8000;              /* DWD experiment identifier            */
+  isec1[49] =  isvn >> 15;                 /* DWD run type (0=main, 2=ass, 3=test) */
+  isec1[50] =  GET_UINT1(pds[54]);         /* User id, specified by table          */
+  isec1[51] =  GET_UINT2(pds[55],pds[56]); /* Experiment identifier                */
+  isec1[52] =  GET_UINT2(pds[57],pds[58]); /* Ensemble identification by table     */
+  isec1[53] =  GET_UINT2(pds[59],pds[60]); /* Number of ensemble members           */
+  isec1[54] =  GET_UINT2(pds[61],pds[62]); /* Actual number of ensemble member     */
+  isec1[55] =  GET_UINT1(pds[63]);         /* Model major version number           */
+  isec1[56] =  GET_UINT1(pds[64]);         /* Model minor version number           */
+
+}
+
+static 
+void decodePDS_MPIM_local_Extension_1(unsigned char *pds, int *isec1)
+{
+  isec1[36] = GET_UINT1(pds[40]);         /* extension identifier            */
+  isec1[37] = GET_UINT1(pds[41]);         /* type of ensemble forecast       */
+  isec1[38] = GET_UINT2(pds[42],pds[43]); /* individual ensemble member      */
+  isec1[39] = GET_UINT2(pds[44],pds[45]); /* number of forecasts in ensemble */
+}
+
+static 
+int decodePDS(unsigned char *pds, int *isec0, int *isec1)
+{
+  int pdsLen;
+
+  pdsLen = PDS_Len;
+
+  ISEC1_CodeTable      = PDS_CodeTable;
+  ISEC1_CenterID       = PDS_CenterID;
+  ISEC1_ModelID        = PDS_ModelID;
+  ISEC1_GridDefinition = PDS_GridDefinition;
+  ISEC1_Sec2Or3Flag    = PDS_Sec2Or3Flag;
+  ISEC1_Parameter      = PDS_Parameter;
+  ISEC1_LevelType      = PDS_LevelType;
+
+  if ( (ISEC1_LevelType !=  20) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_99)        && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)  && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)  && 
+       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)    && 
+       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)     && 
+       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)    && 
+       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) && 
+       (ISEC1_LevelType != 115) && 
+       (ISEC1_LevelType != 117) && 
+       (ISEC1_LevelType != 125) && 
+       (ISEC1_LevelType != 127) && 
+       (ISEC1_LevelType != GRIB1_LTYPE_SEADEPTH)  && 
+       (ISEC1_LevelType != 210) )
+    {
+      ISEC1_Level1 = PDS_Level1;
+      ISEC1_Level2 = PDS_Level2;
+    }
+  else
+    {
+      ISEC1_Level1 = PDS_Level;
+      ISEC1_Level2 = 0;
+    }
+
+  /* ISEC1_Year        = PDS_Year; */
+  ISEC1_Month          = PDS_Month;
+  ISEC1_Day            = PDS_Day;
+  ISEC1_Hour           = PDS_Hour;
+  ISEC1_Minute         = PDS_Minute;
+  ISEC1_TimeUnit       = PDS_TimeUnit;
+  ISEC1_TimePeriod1    = PDS_TimePeriod1;
+  ISEC1_TimePeriod2    = PDS_TimePeriod2;
+  ISEC1_TimeRange      = PDS_TimeRange;
+  ISEC1_AvgNum         = PDS_AvgNum;
+  ISEC1_AvgMiss        = PDS_AvgMiss;
+
+  if ( ISEC0_GRIB_Version == 1 )
+    {
+      ISEC1_Year           = PDS_Year;
+      ISEC1_Century        = PDS_Century;
+      ISEC1_SubCenterID    = PDS_Subcenter;
+      ISEC1_DecScaleFactor = PDS_DecimalScale;
+    }
+  else
+    {
+      int year;
+      year                 = GET_UINT1(pds[12]);
+      if ( year <= 100 )
+	{
+	  ISEC1_Year       = year;
+	  ISEC1_Century    = 1;
+	}
+      else
+	{
+	  ISEC1_Year       = year%100;
+	  ISEC1_Century    = 1 + (year-ISEC1_Year)/100;
+	}
+      ISEC1_SubCenterID    = 0;
+      ISEC1_DecScaleFactor = 0;
+    }
+
+  if ( ISEC1_Year < 0 )
+    {
+      ISEC1_Year    = -ISEC1_Year;
+      ISEC1_Century = -ISEC1_Century;
+    }
+
+  ISEC1_LocalFLag = 0;
+  if ( pdsLen > 28 )
+    {
+      int localextlen;
+      localextlen = pdsLen-28;
+
+      if ( localextlen > 4000 )
+	{
+	  Warning("PDS larger than 4000 bytes not supported!");
+	}
+      else
+	{
+	  ISEC1_LocalFLag = 1;
+
+	  if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
+	    {
+	      if ( pds[40] == 254 ) 
+		{
+		  decodePDS_DWD_local_Extension_254(pds, isec1);
+		}
+	      else if ( pds[40] == 253 )
+		{ 
+		  decodePDS_DWD_local_Extension_253(pds, isec1);
+		}
+	    }
+	  else if ( (ISEC1_CenterID    == 98 && ISEC1_LocalFLag ==  1) ||
+		    (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag ==  1) ||
+		    (ISEC1_CenterID    ==  7 && ISEC1_SubCenterID == 98) )
+	    {
+	      if ( pds[40] == 1 )
+		decodePDS_ECMWF_local_Extension_1(pds, isec1);
+	    }
+	  else if ( ISEC1_CenterID    == 252 && ISEC1_LocalFLag ==  1 )
+	    {
+	      if ( pds[40] == 1 )
+		decodePDS_MPIM_local_Extension_1(pds, isec1);	      
+	    }
+	  else
+	    {
+	      long i;
+	      for ( i = 0; i < localextlen; i++ )
+		{
+		  isec1[24+i] = pds[28+i];
+		}
+	    }
+	}
+    }
+
+  return (pdsLen);
+}
+
+
+void gribPrintSec2_double(int *isec0, int *isec2, double *fsec2) {gribPrintSec2DP(isec0, isec2, fsec2);}
+void gribPrintSec3_double(int *isec0, int *isec3, double *fsec3) {gribPrintSec3DP(isec0, isec3, fsec3);}
+void gribPrintSec4_double(int *isec0, int *isec4, double *fsec4) {gribPrintSec4DP(isec0, isec4, fsec4);}
+void gribPrintSec2_float(int *isec0, int *isec2, float *fsec2) {gribPrintSec2SP(isec0, isec2, fsec2);}
+void gribPrintSec3_float(int *isec0, int *isec3, float *fsec3) {gribPrintSec3SP(isec0, isec3, fsec3);}
+void gribPrintSec4_float(int *isec0, int *isec4, float *fsec4) {gribPrintSec4SP(isec0, isec4, fsec4);}
+
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+static 
+void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				     T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  unsigned int jmask;
+  long i;
+  unsigned int tbits = 0;
+  int n_bits = NumBits;
+  int t_bits = 0;
+      
+  jmask = (1 << n_bits) - 1;
+  for ( i = 0; i < jlend; i++ )
+    {
+      if (n_bits - t_bits > 8)
+	{
+	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+	  bits += 2;
+	  t_bits += 16;
+	}
+
+      while ( t_bits < n_bits )
+	{
+	  tbits = (tbits * 256) + *bits++;
+	  t_bits += 8;
+	}
+      t_bits -= n_bits;
+      fpdata[i] = (tbits >> t_bits) & jmask;
+    }
+  /* at least this vectorizes :) */
+  for ( i = 0; i < jlend; i++ )
+    fpdata[i] = fmin + zscale*fpdata[i];
+}
+
+#if !defined(_MASK_AND_SHIFT_)
+#define _MASK_AND_SHIFT_
+static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+#endif
+
+static 
+void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				      T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  long i;
+  int n_bits = NumBits;
+  int c_bits, j_bits;
+  double jj;
+
+  /* older unoptimized code, not often used */
+  c_bits = 8;
+  for ( i = 0; i < jlend; i++ )
+    {
+      jj = 0.0;
+      j_bits = n_bits;
+      while (c_bits <= j_bits)
+	{
+	  if (c_bits == 8)
+	    {
+	      jj = jj * 256.0  + (double) (*bits++);
+	      j_bits -= 8;
+	    }
+	  else
+	    {
+	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
+	      bits++;
+	      j_bits -= c_bits;
+	      c_bits = 8;
+	    }
+	}
+
+      if (j_bits)
+	{
+	  c_bits -= j_bits;
+	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+	}
+      
+      fpdata[i] = fmin + zscale*jj;
+    }
+} 
+
+static 
+void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits, 
+			      T fmin, T zscale, T *restrict fpdata)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_decode, end_decode;
+#endif
+
+  long i;
+  T dval;
+#if defined (VECTORCODE)
+  GRIBPACK *lgrib = NULL;
+
+  if ( numBits%8 == 0 )
+    {
+      long jlenc = jlend * numBits / 8;
+      if ( jlenc > 0 ) 
+	{
+	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
+	  if ( lgrib == NULL ) SysError("No Memory!");
+
+	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
+	}
+    }
+
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)lgrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
+	  	 (int)lgrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+
+  if ( lgrib ) free(lgrib);
+
+#else
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)igrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(6, "unpack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_decode = mach_absolute_time();
+#endif
+      
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+	  printf("AVX selected ...\n");
+	  avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#elif defined _ENABLE_SSE4_1
+	  printf("SSE4 selected ...\n");
+	  sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#else
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+#endif
+	}
+      else
+	{
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+	}
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_decode = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(6);
+#endif
+    }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
+		 (int)igrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+#endif
+}
+
+#endif /* T */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+static 
+void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				     T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  unsigned int jmask;
+  long i;
+  unsigned int tbits = 0;
+  int n_bits = NumBits;
+  int t_bits = 0;
+      
+  jmask = (1 << n_bits) - 1;
+  for ( i = 0; i < jlend; i++ )
+    {
+      if (n_bits - t_bits > 8)
+	{
+	  tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+	  bits += 2;
+	  t_bits += 16;
+	}
+
+      while ( t_bits < n_bits )
+	{
+	  tbits = (tbits * 256) + *bits++;
+	  t_bits += 8;
+	}
+      t_bits -= n_bits;
+      fpdata[i] = (tbits >> t_bits) & jmask;
+    }
+  /* at least this vectorizes :) */
+  for ( i = 0; i < jlend; i++ )
+    fpdata[i] = fmin + zscale*fpdata[i];
+}
+
+#if !defined(_MASK_AND_SHIFT_)
+#define _MASK_AND_SHIFT_
+static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+#endif
+
+static 
+void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits, 
+				      T fmin, T zscale, T * restrict fpdata)
+{
+  /* code from wgrib routine BDS_unpack */
+  const unsigned char *bits = igrib;
+  long i;
+  int n_bits = NumBits;
+  int c_bits, j_bits;
+  double jj;
+
+  /* older unoptimized code, not often used */
+  c_bits = 8;
+  for ( i = 0; i < jlend; i++ )
+    {
+      jj = 0.0;
+      j_bits = n_bits;
+      while (c_bits <= j_bits)
+	{
+	  if (c_bits == 8)
+	    {
+	      jj = jj * 256.0  + (double) (*bits++);
+	      j_bits -= 8;
+	    }
+	  else
+	    {
+	      jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
+	      bits++;
+	      j_bits -= c_bits;
+	      c_bits = 8;
+	    }
+	}
+
+      if (j_bits)
+	{
+	  c_bits -= j_bits;
+	  jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+	}
+      
+      fpdata[i] = fmin + zscale*jj;
+    }
+} 
+
+static 
+void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits, 
+			      T fmin, T zscale, T *restrict fpdata)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_decode, end_decode;
+#endif
+
+  long i;
+  T dval;
+#if defined (VECTORCODE)
+  GRIBPACK *lgrib = NULL;
+
+  if ( numBits%8 == 0 )
+    {
+      long jlenc = jlend * numBits / 8;
+      if ( jlenc > 0 ) 
+	{
+	  lgrib = (GRIBPACK*) malloc(jlenc*sizeof(GRIBPACK));
+	  if ( lgrib == NULL ) SysError("No Memory!");
+
+	  (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
+	}
+    }
+
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)lgrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[2*i  ] <<  8) +  (int)lgrib[2*i+1]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)lgrib[3*i  ] << 16) + ((int)lgrib[3*i+1] <<  8) +
+	  	 (int)lgrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)lgrib[4*i  ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+		((unsigned int)lgrib[4*i+2] <<  8) +  (unsigned int)lgrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+
+  if ( lgrib ) free(lgrib);
+
+#else
+  if ( numBits ==  0 )
+    {
+      for ( i = 0; i < jlend; i++ )
+	fpdata[i] = fmin;
+    }
+  else if ( numBits ==  8 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (int)igrib[i];
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 16 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(6, "unpack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_decode = mach_absolute_time();
+#endif
+      
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+	  printf("AVX selected ...\n");
+	  avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#elif defined _ENABLE_SSE4_1
+	  printf("SSE4 selected ...\n");
+	  sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
+#else
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+#endif
+	}
+      else
+	{
+	  for ( i = 0; i < jlend; i++ )
+	    {
+	      dval = (((int)igrib[2*i  ] <<  8) |  (int)igrib[2*i+1]);
+	      fpdata[i] = fmin + zscale * dval;
+	    }
+	}
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_decode = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_decode = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(6);
+#endif
+    }
+  else if ( numBits == 24 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((int)igrib[3*i  ] << 16) + ((int)igrib[3*i+1] <<  8) +
+		 (int)igrib[3*i+2]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits == 32 )
+    for ( i = 0; i < jlend; i++ )
+      {
+	dval = (((unsigned int)igrib[4*i  ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+		((unsigned int)igrib[4*i+2] <<  8) +  (unsigned int)igrib[4*i+3]);
+	fpdata[i] = fmin + zscale * dval;
+      }
+  else if ( numBits <= 25 )
+    {
+      TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else if ( numBits > 25 && numBits < 32 )
+    {
+      TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
+    }
+#endif
+}
+
+#endif /* T */
+
+
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
+
+static 
+int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
+{
+  /* int imisng = 0; */
+  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
+  int  locnv = 0, locnl;
+  int  jlenl;
+  long i;
+  int iexp, imant;
+  int ipvpl, ipl;
+  int gdsLen = 0;
+#if defined (VECTORCODE)
+  unsigned char *igrib;
+  GRIBPACK *lgrib = NULL;
+  size_t lGribLen = 0;
+#endif
+
+  *numGridVals = 0;
+
+  memset(isec2, 0, 22*sizeof(int));
+
+  gdsLen = GDS_Len;
+
+  ipvpl = GDS_PVPL;
+  if ( ipvpl == 0 ) ipvpl = 0xFF;
+
+  if ( ipvpl != 0xFF )
+    { /* Either vct or reduced grid */
+      if ( GDS_NV != 0 )
+	{ /* we have vct */
+	  VertCoorTab = TRUE;
+	  ipl =  4*GDS_NV + ipvpl - 1;
+	  if ( ipl < gdsLen )
+	    {
+	      ReducedGrid = TRUE;
+	    }
+	}
+      else
+	{
+	  VertCoorTab = FALSE;
+	  ReducedGrid = TRUE;
+	}
+      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
+    }
+ 
+  if ( ISEC0_GRIB_Version == 0 )
+    {
+      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
+      else                   VertCoorTab = FALSE;
+    }
+  
+  if ( ReducedGrid )
+    {
+      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      jlenl = (gdsLen - locnl)  >> 1;
+      if ( jlenl == GDS_NumLat )
+	{
+	  *numGridVals = 0;
+	  ISEC2_Reduced = TRUE;
+	  for ( i = 0; i < jlenl; i++ )
+	    {
+	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
+	      *numGridVals += ISEC2_RowLon(i);
+	    }
+	}
+      else
+	{
+	  ReducedGrid = FALSE;
+	}
+    }
+
+  ISEC2_GridType = GDS_GridType;
+
+  /*
+     Gaussian grid definition.
+  */
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      ISEC2_NumLat    = GDS_NumLat;
+      if ( ! ReducedGrid )
+	{
+	  ISEC2_NumLon = GDS_NumLon;
+	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+	}
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_LastLat   = GDS_LastLat;
+      ISEC2_LastLon   = GDS_LastLon;
+      ISEC2_LonIncr   = GDS_LonIncr;
+
+      ISEC2_NumPar    = GDS_NumPar;
+      ISEC2_ScanFlag  = GDS_ScanFlag;
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  ISEC2_LatSP     = GDS_LatSP;
+	  ISEC2_LonSP     = GDS_LonSP;
+	  FSEC2_RotAngle  = GDS_RotAngle;
+	}
+      /*
+	if ( Lons != Longitudes || Lats != Latitudes )
+	Error("Latitude/Longitude Conflict");
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+    {
+      ISEC2_NumLon    = GDS_NumLon;
+      ISEC2_NumLat    = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
+      ISEC2_Lambert_dx    = GDS_Lambert_dx;
+      ISEC2_Lambert_dy    = GDS_Lambert_dy;
+      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
+      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
+      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
+      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
+      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
+      ISEC2_ScanFlag      = GDS_ScanFlag;
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
+    {
+      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
+      ISEC2_PentaK  = GDS_PentaK;
+      ISEC2_PentaM  = GDS_PentaM;
+      ISEC2_RepType = GDS_RepType;
+      ISEC2_RepMode = GDS_RepMode;
+      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
+      isec2[ 6] = 0;
+      isec2[ 7] = 0;
+      isec2[ 8] = 0;
+      isec2[ 9] = 0;
+      isec2[10] = 0;
+      /*
+      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+    {
+      ISEC2_GME_NI2    = GDS_GME_NI2;
+      ISEC2_GME_NI3    = GDS_GME_NI3;
+      ISEC2_GME_ND     = GDS_GME_ND;
+      ISEC2_GME_NI     = GDS_GME_NI;
+      ISEC2_GME_AFlag  = GDS_GME_AFlag;
+      ISEC2_GME_LatPP  = GDS_GME_LatPP;
+      ISEC2_GME_LonPP  = GDS_GME_LonPP;
+      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
+      ISEC2_GME_BFlag  = GDS_GME_BFlag;
+      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
+      /*
+      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else
+    {
+      ISEC2_NumLon = GDS_NumLon;
+      ISEC2_NumLat = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      Message("Gridtype %d unsupported", ISEC2_GridType);
+    }
+
+  /*    vertical coordinate parameters for hybrid levels.     */
+  /*    get number of vertical coordinate parameters, if any. */
+
+  ISEC2_NumVCP = 0;
+
+  isec2[17] = 0;
+  isec2[18] = 0;
+
+  if ( VertCoorTab == TRUE )
+    {
+      if ( ISEC0_GRIB_Version  == 0 )
+	{
+	  locnv = 32;
+	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
+	}
+      else
+	{
+	  locnv = GDS_PVPL - 1;
+	  ISEC2_NumVCP = GDS_NV;
+	}
+#if defined (SX)
+      lGribLen = 4*ISEC2_NumVCP;	      
+      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
+
+      igrib = &gds[locnv];
+      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (lgrib[4*i  ]);
+	  imant  =((lgrib[4*i+1]) << 16) +
+	          ((lgrib[4*i+2]) <<  8) +
+	           (lgrib[4*i+3]);
+	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+	}
+
+      free(lgrib);
+#else
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (gds[locnv+4*i  ]);
+	  imant  =((gds[locnv+4*i+1]) << 16) +
+	          ((gds[locnv+4*i+2]) <<  8) +
+	           (gds[locnv+4*i+3]);
+	  fsec2[10+i] = decfp2(iexp,imant);
+	}
+#endif
+    }
+
+  return (gdsLen);
+}
+
+static
+int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4, 
+			  T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
+{
+  unsigned char *igrib;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int lcompress;
+  int jup, kup, mup;
+  int locnd;
+  long jlend;
+  long i;
+  int bds_flag, jscale, imiss;
+  int bds_ubits;
+  int ioff = 0;
+  int iexp, imant;
+  int zoff;
+  int bds_head = 11;
+  double zscale = 0.;
+  T fmin = 0.;
+  T *fpdata = fsec4;
+  int bdsLen;
+  extern int CGRIBEX_Fix_ZSE;
+
+  *iret = 0;
+  igrib = bds;
+
+  memset(isec4, 0, 42*sizeof(int));
+
+  /* get length of binary data block. */
+
+  bdsLen = BDS_Len;
+  /*
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
+
+  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
+
+  bds_flag = BDS_Flag;
+
+  /* 0------- grid point           */
+  /* 1------- spherical harmonics  */
+
+  lspherc = bds_flag >> 7;
+
+  if ( lspherc ) isec4[2] = 128;
+  else           isec4[2] = 0;
+
+  /* -0------  simple packing */
+  /* -1------ complex packing */
+
+  lcomplex = (bds_flag >> 6)&1;
+
+  if ( lcomplex ) isec4[3] = 64;
+  else            isec4[3] =  0;
+
+  /* ---0---- No additional flags */
+  /* ---1---- No additional flags */
+
+  lcompress = (bds_flag >> 4)&1; /* compress */
+
+  if ( lcompress )
+    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
+  else
+    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+
+  /* ----++++ number of unused bits at end of section) */
+
+  bds_ubits = bds_flag & 0xF;
+  
+  /* scale factor (2 bytes) */;
+
+  jscale = BDS_BinScale;
+
+  /* check for missing data indicators. */
+
+  iexp  = bds[ 6];
+  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
+
+  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
+
+  /* convert reference value and scale factor. */
+
+  if ( ! (dfunc == 'J') )
+    if ( imiss == 0 )
+      {
+	fmin = BDS_RefValue;
+	
+	if ( jscale < 0 )
+	  zscale = 1.0/intpow2(-jscale);
+	else
+	  zscale = intpow2(jscale);
+      }
+
+  /* get number of bits in each data value. */
+
+  ISEC4_NumBits = BDS_NumBits;
+
+  /* octet number of start of packed data */
+  /* calculated from start of block 4 - 1 */
+
+  locnd = zoff + bds_head;
+
+  /* if data is in spherical harmonic form, distinguish   */
+  /* between simple/complex packing (lcomplex = 0/1)      */
+
+  if ( lspherc )
+    {
+      if ( !lcomplex )
+	{
+	  /*    no unpacked binary data present */
+
+	  jup = kup = mup = 0;
+
+	  /*    octet number of start of packed data */
+	  /*    calculated from start of block 4 - 1 */
+
+	  ioff   = 1;
+	  locnd += 4*ioff;  /* RealCoef */
+
+	  /*    get real (0,0) coefficient in grib format and     */
+	  /*    convert to floating point.                        */
+
+	  if ( dfunc != 'J' )
+	    {
+	      if ( imiss ) *fpdata++ = 0.0;
+	      else         *fpdata++ = BDS_RealCoef;
+	    }
+	}
+      else /* complex packed spherical harmonics */
+	{
+	  isec4[15] = BDS_PackData;
+	  /*    scaling factor */
+	  isec4[16] = BDS_Power;
+
+	  /*    pentagonal resolution parameters of the */
+	  /*    unpacked section of data field          */
+
+	  jup = bds[zoff+15];
+	  kup = bds[zoff+16];
+	  mup = bds[zoff+17];
+
+	  isec4[zoff+17] = jup;
+	  isec4[zoff+18] = kup;
+	  isec4[zoff+19] = mup;
+
+	  /*    unpacked binary data */
+
+	  locnd += 4; /* 2 + power */
+	  locnd += 3; /* j, k, m   */
+	  ioff   = (jup+1)*(jup+2);
+
+	  if ( dfunc != 'J' )
+	    for ( i = 0; i < ioff; i++ )
+	      {
+		if ( imiss )
+		  *fpdata++ = 0.0;
+		else
+		  {
+		    iexp   = (bds[locnd+4*i  ]);
+		    imant  =((bds[locnd+4*i+1]) << 16) +
+		            ((bds[locnd+4*i+2]) <<  8) +
+		             (bds[locnd+4*i+3]);
+
+		    *fpdata++ = decfp2(iexp,imant);
+		  }
+	      }
+	  
+	  locnd += 4*ioff;  /* RealCoef */
+	}
+    }
+  else
+    {
+      if ( lcomplex )
+	{
+	  *iret = 1999;
+	  gprintf(__func__, " Second order packed grids unsupported!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+    }
+
+  /* Decode data values to floating point and store in fsec4.  */
+  /* First calculate the number of data values.                */
+  /* Take into account that spherical harmonics can be packed  */
+  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
+
+  jlend = bdsLen - locnd;
+
+  if ( ISEC4_NumBits == 0 )
+    {
+      if ( jlend > 1 )
+	{
+	  *iret = 2001;
+	  gprintf(__func__, " Number of bits per data value = 0!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      if ( numGridVals == 0 )
+	{
+	  *iret = 2002;
+	  gprintf(__func__, " Constant field unsupported for this grid type!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      jlend = numGridVals;
+      jlend -= ioff;
+    }
+  else
+    {
+      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
+    }
+
+  ISEC4_NumValues        = jlend + ioff;
+  ISEC4_NumNonMissValues = 0;
+
+  if ( lcompress )
+    {
+      size_t len;
+
+      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
+	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+      else
+        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+
+      ISEC4_NumValues = len*8/ISEC4_NumBits;
+
+      if ( lspherc )
+	{
+	  if ( lcomplex )
+	    ISEC4_NumValues += ioff;
+	  else
+	    ISEC4_NumValues++;
+	}
+    }
+
+  if ( dfunc == 'J' ) return (bdsLen);
+
+  /* check length of output array. */
+  
+  if ( ISEC4_NumValues > fsec4len )
+    {
+      *iret = 710;
+      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
+      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
+      gprintf(__func__, " Return code =  %d", *iret);
+      return (0);
+    }
+
+  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+  else
+    {
+      igrib += locnd;
+
+      TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
+    }
+
+  if ( lspherc && lcomplex )
+    {
+      int pcStart, pcScale;
+      pcStart = isec4[19];
+      pcScale = isec4[16];
+      TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
+      TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
+    }
+
+  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
+    if ( lspherc && !lcomplex )
+      {
+        /* 20100705: Fix ZeroShiftError - Edi Kirk */
+	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
+	  {
+	    T zserr = fsec4[1];
+	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+	  }
+      }
+
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double)-decscale);
+      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+    }
+
+  return (bdsLen);
+}
+
+
+void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
+			     int kleng, int *kword, int dfunc, int *iret)
+{
+  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
+  int gribLen = 0;
+  int gdsIncluded = FALSE;
+  int bmsIncluded = FALSE;
+  int bitmapSize = 0;
+  int imaskSize = 0;
+  int ldebug = FALSE;
+  int llarge = FALSE, l_iorj = FALSE;
+  int lsect2 = FALSE, lsect3 = FALSE;
+  int numGridVals = 0;
+  static int lmissvalinfo = 1;
+
+  UNUSED(kleng);
+
+  *iret = 0;
+
+  grsdef();
+
+  ISEC2_Reduced = FALSE;
+
+  /*
+    ----------------------------------------------------------------
+    IS Indicator Section (Section 0)
+    ----------------------------------------------------------------
+  */
+  is = (unsigned char *) &kgrib[0];
+
+  isLen = decodeIS(is, isec0, iret);
+
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( ISEC0_GRIB_Len < 0 )
+    {
+      if ( ldebug )
+	gprintf(__func__, "Special case, negative length multiplied by -120");
+      llarge = TRUE;
+      ISEC0_GRIB_Len *= (-120);
+    }
+  /*
+    When decoding or calculating length, previous editions
+    of the GRIB code must be taken into account.
+
+    In the table below, covering sections 0 and 1 of the GRIB
+    code, octet numbering is from the beginning of the GRIB
+    message;
+    * indicates that the value is not available in the code edition;
+    R indicates reserved, should be set to 0;
+    Experimental edition is considered as edition -1.
+
+    GRIB code edition -1 has fixed length of 20 octets for
+    section 1, the length not included in the message.
+    GRIB code edition 0 has fixed length of 24 octets for
+    section 1, the length being included in the message.
+    GRIB code edition 1 can have different lengths for section
+    1, the minimum being 28 octets, length being included in
+    the message.
+
+                                         Octet numbers for code
+                                                  editions
+
+                 Contents.                   -1      0      1
+                 ---------                ----------------------
+       Letters GRIB                          1-4    1-4    1-4
+       Total length of GRIB message.          *      *     5-7
+       GRIB code edition number               *      *      8
+       Length of Section 1.                   *     5-7    9-11
+       Reserved octet (R).                    *      8(R)   *
+       Version no. of Code Table 2.           *      *     12
+       Identification of centre.              5      9     13
+       Generating process.                    6     10     14
+       Grid definition .                      7     11     15
+       Flag (Code Table 1).                   8     12     16
+       Indicator of parameter.                9     13     17
+       Indicator of type of level.           10     14     18
+       Height, pressure etc of levels.      11-12  15-16  19-20
+       Year of century.                      13     17     21
+       Month.                                14     18     22
+       Day.                                  15     19     23
+       Hour.                                 16     20     24
+       Minute.                               17     21     25
+       Indicator of unit of time.            18     22     26
+       P1 - Period of time.                  19     23     27
+       P2 - Period of time                  20(R)   24     28
+       or reserved octet (R).
+       Time range indicator.                21(R)   25     29
+       or reserved octet (R).
+       Number included in average.       22-23(R)  26-27  30-31
+       or reserved octet (R).
+       Number missing from average.         24(R)  28(R)   32
+       or reserved octet (R).
+       Century of data.                       *      *     33
+       Designates sub-centre if not 0.        *      *     34
+       Decimal scale factor.                  *      *    35-36
+       Reserved. Set to 0.                    *      *    37-48
+       (Need not be present)
+       For originating centre use only.       *      *    49-nn
+       (Need not be present)
+
+    Identify which GRIB code edition is being decoded.
+
+    In GRIB edition 1, the edition number is in octet 8.
+    In GRIB edition 0, octet 8 is reserved and set to 0.
+    In GRIB edition -1, octet 8 is a flag field and can have a
+    a valid value of 0, 1, 2 or 3.
+
+    However, GRIB edition number 0 has a fixed
+    length of 24, included in the message, for section 1, so
+    if the value extracted from octets 5-7 is 24 and that from
+    octet 8 is 0, it is safe to assume edition 0 of the code.
+
+  */
+  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
+    {
+      /*
+	Set length of GRIB message to missing data value.
+      */
+      ISEC0_GRIB_Len = 0;
+    }
+  /*
+    If Grib Edition 1 and only length is required, go to section 9.
+  */
+  if ( dfunc == 'L' ) goto LABEL900;
+
+  /*
+    ----------------------------------------------------------------
+    PDS Product Definition Section (Section 1)
+    ----------------------------------------------------------------
+  */ 
+  pds = is + isLen;
+
+  pdsLen = decodePDS(pds, isec0, isec1);
+
+  /*
+    ----------------------------------------------------------------
+    GDS Grid Description Section (Section 2)
+    ----------------------------------------------------------------
+  */
+  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
+
+  if ( gdsIncluded )
+    {
+      gds = is + isLen + pdsLen;
+
+      gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+
+  isec3[0] = 0;
+  if ( bmsIncluded )
+    {
+      bms = is + isLen + pdsLen + gdsLen;
+
+      bmsLen = BMS_Len;
+      imaskSize = (bmsLen - 6)<<3;
+      bitmapSize = imaskSize - BMS_UnusedBits;
+      /*
+      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
+      */
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BDS Binary Data Section (Section 4)
+    ----------------------------------------------------------------
+  */
+  bds = is + isLen + pdsLen + gdsLen + bmsLen;
+
+  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
+
+  bdsLen = TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, 
+				 fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
+
+  if ( *iret != 0 ) return;
+
+  ISEC4_NumNonMissValues = ISEC4_NumValues;
+
+  if ( bitmapSize > 0 )
+    {
+      if ( dfunc != 'L' && dfunc != 'J' )
+	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
+	  {
+	    lmissvalinfo = 0;
+	    FSEC3_MissVal = GRIB_MISSVAL;
+	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
+	  }
+
+      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
+      ISEC4_NumValues        = bitmapSize;
+
+      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
+	{
+	  long i, j;
+	  GRIBPACK *pbitmap;
+	  GRIBPACK bitmap;
+	  GRIBPACK *imask;
+
+	  /*
+	  unsigned char *bitmap;
+	  bitmap = BMS_Bitmap;
+	  j = ISEC4_NumNonMissValues;
+	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+	    {
+	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
+		fsec4[i] = fsec4[--j];
+	      else
+		fsec4[i] = FSEC3_MissVal;
+	    }
+	  */
+
+	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
+
+#if defined (VECTORCODE)
+	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
+	  pbitmap = imask;
+#else
+	  pbitmap = BMS_Bitmap;
+#endif
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	  for ( i = imaskSize/8-1; i >= 0; i-- )
+	    {
+	      bitmap = pbitmap[i];
+	      imask[i*8+0] = 1 & (bitmap >> 7);
+	      imask[i*8+1] = 1 & (bitmap >> 6);
+	      imask[i*8+2] = 1 & (bitmap >> 5);
+	      imask[i*8+3] = 1 & (bitmap >> 4);
+	      imask[i*8+4] = 1 & (bitmap >> 3);
+	      imask[i*8+5] = 1 & (bitmap >> 2);
+	      imask[i*8+6] = 1 & (bitmap >> 1);
+	      imask[i*8+7] = 1 & (bitmap);
+	    }
+
+	  j = 0;
+	  for ( i = 0; i < ISEC4_NumValues; i++ )
+	    if ( imask[i] ) j++;
+
+	  if ( ISEC4_NumNonMissValues != j )
+	    {
+	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
+		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
+			j, ISEC4_NumNonMissValues);
+
+	      ISEC4_NumNonMissValues = j;
+	    }
+
+	  if ( dfunc != 'J' )
+	    {
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
+	    }
+
+	  free(imask);
+	}
+    }
+
+  if ( ISEC2_Reduced )
+    {
+      int nlon, nlat;
+      int lsect3, lperio = 1, lveggy;
+      int ilat;
+      int nvalues = 0;
+      int dlon;
+
+      nlat = ISEC2_NumLat;
+      nlon = ISEC2_RowLonPtr[0];
+      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+      for ( ilat = 1; ilat < nlat; ++ilat )
+	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
+
+      dlon = ISEC2_LastLon-ISEC2_FirstLon;
+      if ( dlon < 0 ) dlon += 360000;
+	  
+      if ( nvalues != ISEC4_NumValues )
+	{
+	  *iret = -801;
+	}
+      //printf("nlat %d  nlon %d \n", nlat, nlon);
+      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
+
+      if ( dfunc == 'R' && *iret == -801 )
+	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
+		ISEC4_NumValues, nvalues);
+      
+      if ( dfunc == 'R' && *iret != -801 )
+	{
+	  ISEC2_Reduced = 0;
+	  ISEC2_NumLon = nlon;
+	  ISEC4_NumValues = nlon*nlat;
+
+	  lsect3 = bitmapSize > 0;
+	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
+	          ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
+	           (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+	
+	  (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
+	      
+	  if ( bitmapSize > 0 )
+	    {
+	      long i;
+	      int j = 0;
+	      
+	      for ( i = 0; i < ISEC4_NumValues; i++ )
+		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
+		  
+	      ISEC4_NumNonMissValues = j;
+	    }
+	}
+    }
+
+
+  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
+  esLen = 4;
+
+  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+
+  if ( ISEC0_GRIB_Len )
+    if ( ISEC0_GRIB_Len < gribLen )
+      Warning("Length of GRIB message is inconsistent (grib_message_size=7867 < grib_record_size=9718)!", ISEC0_GRIB_Len, gribLen);
+
+  ISEC0_GRIB_Len = gribLen;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+
+  /*
+    ----------------------------------------------------------------
+    Section 9 . Abort/return to calling routine.
+    ----------------------------------------------------------------
+  */
+ LABEL900:;
+
+  if ( ldebug )
+    {
+      gprintf(__func__, "Section 9.");
+      gprintf(__func__, "Output values set -");
+
+      gribPrintSec0(isec0);
+      gribPrintSec1(isec0, isec1);
+      /*
+	Print section 2 if present.
+      */
+      if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
+
+      if ( ! l_iorj )
+	{
+	  /*
+	    Print section 3 if present.
+	  */
+	  if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
+
+	  TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
+	  /*
+	    Special print for 2D spectra wave field real values in
+	    section 4
+	  */
+	  if ( (isec1[ 0] ==  140) && 
+	       (isec1[ 1] ==   98) && 
+	       (isec1[23] ==    1) && 
+	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
+	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
+	    gribPrintSec4Wave(isec4);
+	}
+    }
+}
+
+#endif /* T */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+static 
+int TEMPLATE(decodeGDS,T)(unsigned char  *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
+{
+  /* int imisng = 0; */
+  int  ReducedGrid = FALSE, VertCoorTab = FALSE;
+  int  locnv = 0, locnl;
+  int  jlenl;
+  long i;
+  int iexp, imant;
+  int ipvpl, ipl;
+  int gdsLen = 0;
+#if defined (VECTORCODE)
+  unsigned char *igrib;
+  GRIBPACK *lgrib = NULL;
+  size_t lGribLen = 0;
+#endif
+
+  *numGridVals = 0;
+
+  memset(isec2, 0, 22*sizeof(int));
+
+  gdsLen = GDS_Len;
+
+  ipvpl = GDS_PVPL;
+  if ( ipvpl == 0 ) ipvpl = 0xFF;
+
+  if ( ipvpl != 0xFF )
+    { /* Either vct or reduced grid */
+      if ( GDS_NV != 0 )
+	{ /* we have vct */
+	  VertCoorTab = TRUE;
+	  ipl =  4*GDS_NV + ipvpl - 1;
+	  if ( ipl < gdsLen )
+	    {
+	      ReducedGrid = TRUE;
+	    }
+	}
+      else
+	{
+	  VertCoorTab = FALSE;
+	  ReducedGrid = TRUE;
+	}
+      /*	  ReducedGrid = (gdsLen - 32 - 4*GDS_NV); */
+    }
+ 
+  if ( ISEC0_GRIB_Version == 0 )
+    {
+      if ((gdsLen - 32) > 0) VertCoorTab = TRUE;
+      else                   VertCoorTab = FALSE;
+    }
+  
+  if ( ReducedGrid )
+    {
+      locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
+      jlenl = (gdsLen - locnl)  >> 1;
+      if ( jlenl == GDS_NumLat )
+	{
+	  *numGridVals = 0;
+	  ISEC2_Reduced = TRUE;
+	  for ( i = 0; i < jlenl; i++ )
+	    {
+	      ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
+	      *numGridVals += ISEC2_RowLon(i);
+	    }
+	}
+      else
+	{
+	  ReducedGrid = FALSE;
+	}
+    }
+
+  ISEC2_GridType = GDS_GridType;
+
+  /*
+     Gaussian grid definition.
+  */
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+       ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+       ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      ISEC2_NumLat    = GDS_NumLat;
+      if ( ! ReducedGrid )
+	{
+	  ISEC2_NumLon = GDS_NumLon;
+	  *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+	}
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_LastLat   = GDS_LastLat;
+      ISEC2_LastLon   = GDS_LastLon;
+      ISEC2_LonIncr   = GDS_LonIncr;
+
+      ISEC2_NumPar    = GDS_NumPar;
+      ISEC2_ScanFlag  = GDS_ScanFlag;
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  ISEC2_LatSP     = GDS_LatSP;
+	  ISEC2_LonSP     = GDS_LonSP;
+	  FSEC2_RotAngle  = GDS_RotAngle;
+	}
+      /*
+	if ( Lons != Longitudes || Lats != Latitudes )
+	Error("Latitude/Longitude Conflict");
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN     ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON     ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
+    {
+      /*
+      iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
+    {
+      ISEC2_NumLon    = GDS_NumLon;
+      ISEC2_NumLat    = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      ISEC2_FirstLat  = GDS_FirstLat;
+      ISEC2_FirstLon  = GDS_FirstLon;
+      ISEC2_ResFlag   = GDS_ResFlag;
+      ISEC2_Lambert_Lov   = GDS_Lambert_Lov;
+      ISEC2_Lambert_dx    = GDS_Lambert_dx;
+      ISEC2_Lambert_dy    = GDS_Lambert_dy;
+      ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
+      ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
+      ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
+      ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
+      ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
+      ISEC2_ScanFlag      = GDS_ScanFlag;
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
+    {
+      ISEC2_PentaJ  = GDS_PentaJ; /* Truncation */
+      ISEC2_PentaK  = GDS_PentaK;
+      ISEC2_PentaM  = GDS_PentaM;
+      ISEC2_RepType = GDS_RepType;
+      ISEC2_RepMode = GDS_RepMode;
+      *numGridVals  = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
+      isec2[ 6] = 0;
+      isec2[ 7] = 0;
+      isec2[ 8] = 0;
+      isec2[ 9] = 0;
+      isec2[10] = 0;
+      /*
+      iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
+    {
+      ISEC2_GME_NI2    = GDS_GME_NI2;
+      ISEC2_GME_NI3    = GDS_GME_NI3;
+      ISEC2_GME_ND     = GDS_GME_ND;
+      ISEC2_GME_NI     = GDS_GME_NI;
+      ISEC2_GME_AFlag  = GDS_GME_AFlag;
+      ISEC2_GME_LatPP  = GDS_GME_LatPP;
+      ISEC2_GME_LonPP  = GDS_GME_LonPP;
+      ISEC2_GME_LonMPL = GDS_GME_LonMPL;
+      ISEC2_GME_BFlag  = GDS_GME_BFlag;
+      *numGridVals  = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
+      /*
+      iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
+      */
+    }
+  else
+    {
+      ISEC2_NumLon = GDS_NumLon;
+      ISEC2_NumLat = GDS_NumLat;
+      *numGridVals  = ISEC2_NumLon*ISEC2_NumLat;
+      Message("Gridtype %d unsupported", ISEC2_GridType);
+    }
+
+  /*    vertical coordinate parameters for hybrid levels.     */
+  /*    get number of vertical coordinate parameters, if any. */
+
+  ISEC2_NumVCP = 0;
+
+  isec2[17] = 0;
+  isec2[18] = 0;
+
+  if ( VertCoorTab == TRUE )
+    {
+      if ( ISEC0_GRIB_Version  == 0 )
+	{
+	  locnv = 32;
+	  ISEC2_NumVCP = (gdsLen - 32) >> 2;
+	}
+      else
+	{
+	  locnv = GDS_PVPL - 1;
+	  ISEC2_NumVCP = GDS_NV;
+	}
+#if defined (SX)
+      lGribLen = 4*ISEC2_NumVCP;	      
+      lgrib    = (GRIBPACK*) malloc(lGribLen*sizeof(GRIBPACK));
+
+      igrib = &gds[locnv];
+      if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (lgrib[4*i  ]);
+	  imant  =((lgrib[4*i+1]) << 16) +
+	          ((lgrib[4*i+2]) <<  8) +
+	           (lgrib[4*i+3]);
+	  fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+	}
+
+      free(lgrib);
+#else
+      for ( i = 0; i < ISEC2_NumVCP; i++ )
+	{
+	  iexp   = (gds[locnv+4*i  ]);
+	  imant  =((gds[locnv+4*i+1]) << 16) +
+	          ((gds[locnv+4*i+2]) <<  8) +
+	           (gds[locnv+4*i+3]);
+	  fsec2[10+i] = decfp2(iexp,imant);
+	}
+#endif
+    }
+
+  return (gdsLen);
+}
+
+static
+int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4, 
+			  T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
+{
+  unsigned char *igrib;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int lcompress;
+  int jup, kup, mup;
+  int locnd;
+  long jlend;
+  long i;
+  int bds_flag, jscale, imiss;
+  int bds_ubits;
+  int ioff = 0;
+  int iexp, imant;
+  int zoff;
+  int bds_head = 11;
+  double zscale = 0.;
+  T fmin = 0.;
+  T *fpdata = fsec4;
+  int bdsLen;
+  extern int CGRIBEX_Fix_ZSE;
+
+  *iret = 0;
+  igrib = bds;
+
+  memset(isec4, 0, 42*sizeof(int));
+
+  /* get length of binary data block. */
+
+  bdsLen = BDS_Len;
+  /*
+    If a very large product, the section 4 length field holds
+    the number of bytes in the product after section 4 upto
+    the end of the padding bytes.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( llarge ) bdsLen = bdsLenIn - bdsLen;
+
+  /* 4 bit flag / 4 bit count of unused bits at end of block octet. */
+
+  bds_flag = BDS_Flag;
+
+  /* 0------- grid point           */
+  /* 1------- spherical harmonics  */
+
+  lspherc = bds_flag >> 7;
+
+  if ( lspherc ) isec4[2] = 128;
+  else           isec4[2] = 0;
+
+  /* -0------  simple packing */
+  /* -1------ complex packing */
+
+  lcomplex = (bds_flag >> 6)&1;
+
+  if ( lcomplex ) isec4[3] = 64;
+  else            isec4[3] =  0;
+
+  /* ---0---- No additional flags */
+  /* ---1---- No additional flags */
+
+  lcompress = (bds_flag >> 4)&1; /* compress */
+
+  if ( lcompress )
+    { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
+  else
+    { isec4[5] =  0; isec4[6] = 0;     zoff =  0; }
+
+  /* ----++++ number of unused bits at end of section) */
+
+  bds_ubits = bds_flag & 0xF;
+  
+  /* scale factor (2 bytes) */;
+
+  jscale = BDS_BinScale;
+
+  /* check for missing data indicators. */
+
+  iexp  = bds[ 6];
+  imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
+
+  imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
+
+  /* convert reference value and scale factor. */
+
+  if ( ! (dfunc == 'J') )
+    if ( imiss == 0 )
+      {
+	fmin = BDS_RefValue;
+	
+	if ( jscale < 0 )
+	  zscale = 1.0/intpow2(-jscale);
+	else
+	  zscale = intpow2(jscale);
+      }
+
+  /* get number of bits in each data value. */
+
+  ISEC4_NumBits = BDS_NumBits;
+
+  /* octet number of start of packed data */
+  /* calculated from start of block 4 - 1 */
+
+  locnd = zoff + bds_head;
+
+  /* if data is in spherical harmonic form, distinguish   */
+  /* between simple/complex packing (lcomplex = 0/1)      */
+
+  if ( lspherc )
+    {
+      if ( !lcomplex )
+	{
+	  /*    no unpacked binary data present */
+
+	  jup = kup = mup = 0;
+
+	  /*    octet number of start of packed data */
+	  /*    calculated from start of block 4 - 1 */
+
+	  ioff   = 1;
+	  locnd += 4*ioff;  /* RealCoef */
+
+	  /*    get real (0,0) coefficient in grib format and     */
+	  /*    convert to floating point.                        */
+
+	  if ( dfunc != 'J' )
+	    {
+	      if ( imiss ) *fpdata++ = 0.0;
+	      else         *fpdata++ = BDS_RealCoef;
+	    }
+	}
+      else /* complex packed spherical harmonics */
+	{
+	  isec4[15] = BDS_PackData;
+	  /*    scaling factor */
+	  isec4[16] = BDS_Power;
+
+	  /*    pentagonal resolution parameters of the */
+	  /*    unpacked section of data field          */
+
+	  jup = bds[zoff+15];
+	  kup = bds[zoff+16];
+	  mup = bds[zoff+17];
+
+	  isec4[zoff+17] = jup;
+	  isec4[zoff+18] = kup;
+	  isec4[zoff+19] = mup;
+
+	  /*    unpacked binary data */
+
+	  locnd += 4; /* 2 + power */
+	  locnd += 3; /* j, k, m   */
+	  ioff   = (jup+1)*(jup+2);
+
+	  if ( dfunc != 'J' )
+	    for ( i = 0; i < ioff; i++ )
+	      {
+		if ( imiss )
+		  *fpdata++ = 0.0;
+		else
+		  {
+		    iexp   = (bds[locnd+4*i  ]);
+		    imant  =((bds[locnd+4*i+1]) << 16) +
+		            ((bds[locnd+4*i+2]) <<  8) +
+		             (bds[locnd+4*i+3]);
+
+		    *fpdata++ = decfp2(iexp,imant);
+		  }
+	      }
+	  
+	  locnd += 4*ioff;  /* RealCoef */
+	}
+    }
+  else
+    {
+      if ( lcomplex )
+	{
+	  *iret = 1999;
+	  gprintf(__func__, " Second order packed grids unsupported!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+    }
+
+  /* Decode data values to floating point and store in fsec4.  */
+  /* First calculate the number of data values.                */
+  /* Take into account that spherical harmonics can be packed  */
+  /* simple (lcomplex = 0) or complex (lcomplex = 1)           */
+
+  jlend = bdsLen - locnd;
+
+  if ( ISEC4_NumBits == 0 )
+    {
+      if ( jlend > 1 )
+	{
+	  *iret = 2001;
+	  gprintf(__func__, " Number of bits per data value = 0!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      if ( numGridVals == 0 )
+	{
+	  *iret = 2002;
+	  gprintf(__func__, " Constant field unsupported for this grid type!");
+	  gprintf(__func__, " Return code =  %d", *iret);
+	  return (0);
+	}
+
+      jlend = numGridVals;
+      jlend -= ioff;
+    }
+  else
+    {
+      jlend = (jlend*8 - bds_ubits) / ISEC4_NumBits;
+    }
+
+  ISEC4_NumValues        = jlend + ioff;
+  ISEC4_NumNonMissValues = 0;
+
+  if ( lcompress )
+    {
+      size_t len;
+
+      if ( gribrec_len(bds[14], bds[15], bds[16]) > JP23SET )
+	len = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
+      else
+        len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+
+      ISEC4_NumValues = len*8/ISEC4_NumBits;
+
+      if ( lspherc )
+	{
+	  if ( lcomplex )
+	    ISEC4_NumValues += ioff;
+	  else
+	    ISEC4_NumValues++;
+	}
+    }
+
+  if ( dfunc == 'J' ) return (bdsLen);
+
+  /* check length of output array. */
+  
+  if ( ISEC4_NumValues > fsec4len )
+    {
+      *iret = 710;
+      gprintf(__func__, " Output array too small. Length = %d", fsec4len);
+      gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
+      gprintf(__func__, " Return code =  %d", *iret);
+      return (0);
+    }
+
+  if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+  else
+    {
+      igrib += locnd;
+
+      TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
+    }
+
+  if ( lspherc && lcomplex )
+    {
+      int pcStart, pcScale;
+      pcStart = isec4[19];
+      pcScale = isec4[16];
+      TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
+      TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
+    }
+
+  if ( CGRIBEX_Fix_ZSE )  /* Fix ZeroShiftError of simple packed spherical harmonics */
+    if ( lspherc && !lcomplex )
+      {
+        /* 20100705: Fix ZeroShiftError - Edi Kirk */
+	if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
+	  {
+	    T zserr = fsec4[1];
+	    for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+	  }
+      }
+
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double)-decscale);
+      for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+    }
+
+  return (bdsLen);
+}
+
+
+void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
+			     int kleng, int *kword, int dfunc, int *iret)
+{
+  UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
+  int gribLen = 0;
+  int gdsIncluded = FALSE;
+  int bmsIncluded = FALSE;
+  int bitmapSize = 0;
+  int imaskSize = 0;
+  int ldebug = FALSE;
+  int llarge = FALSE, l_iorj = FALSE;
+  int lsect2 = FALSE, lsect3 = FALSE;
+  int numGridVals = 0;
+  static int lmissvalinfo = 1;
+
+  UNUSED(kleng);
+
+  *iret = 0;
+
+  grsdef();
+
+  ISEC2_Reduced = FALSE;
+
+  /*
+    ----------------------------------------------------------------
+    IS Indicator Section (Section 0)
+    ----------------------------------------------------------------
+  */
+  is = (unsigned char *) &kgrib[0];
+
+  isLen = decodeIS(is, isec0, iret);
+
+  /*
+    If count is negative, have to rescale by factor of -120.
+    This is a fixup to get round the restriction on product lengths
+    due to the count being only 24 bits. It is only possible because
+    the (default) rounding for GRIB products is 120 bytes.
+  */
+  if ( ISEC0_GRIB_Len < 0 )
+    {
+      if ( ldebug )
+	gprintf(__func__, "Special case, negative length multiplied by -120");
+      llarge = TRUE;
+      ISEC0_GRIB_Len *= (-120);
+    }
+  /*
+    When decoding or calculating length, previous editions
+    of the GRIB code must be taken into account.
+
+    In the table below, covering sections 0 and 1 of the GRIB
+    code, octet numbering is from the beginning of the GRIB
+    message;
+    * indicates that the value is not available in the code edition;
+    R indicates reserved, should be set to 0;
+    Experimental edition is considered as edition -1.
+
+    GRIB code edition -1 has fixed length of 20 octets for
+    section 1, the length not included in the message.
+    GRIB code edition 0 has fixed length of 24 octets for
+    section 1, the length being included in the message.
+    GRIB code edition 1 can have different lengths for section
+    1, the minimum being 28 octets, length being included in
+    the message.
+
+                                         Octet numbers for code
+                                                  editions
+
+                 Contents.                   -1      0      1
+                 ---------                ----------------------
+       Letters GRIB                          1-4    1-4    1-4
+       Total length of GRIB message.          *      *     5-7
+       GRIB code edition number               *      *      8
+       Length of Section 1.                   *     5-7    9-11
+       Reserved octet (R).                    *      8(R)   *
+       Version no. of Code Table 2.           *      *     12
+       Identification of centre.              5      9     13
+       Generating process.                    6     10     14
+       Grid definition .                      7     11     15
+       Flag (Code Table 1).                   8     12     16
+       Indicator of parameter.                9     13     17
+       Indicator of type of level.           10     14     18
+       Height, pressure etc of levels.      11-12  15-16  19-20
+       Year of century.                      13     17     21
+       Month.                                14     18     22
+       Day.                                  15     19     23
+       Hour.                                 16     20     24
+       Minute.                               17     21     25
+       Indicator of unit of time.            18     22     26
+       P1 - Period of time.                  19     23     27
+       P2 - Period of time                  20(R)   24     28
+       or reserved octet (R).
+       Time range indicator.                21(R)   25     29
+       or reserved octet (R).
+       Number included in average.       22-23(R)  26-27  30-31
+       or reserved octet (R).
+       Number missing from average.         24(R)  28(R)   32
+       or reserved octet (R).
+       Century of data.                       *      *     33
+       Designates sub-centre if not 0.        *      *     34
+       Decimal scale factor.                  *      *    35-36
+       Reserved. Set to 0.                    *      *    37-48
+       (Need not be present)
+       For originating centre use only.       *      *    49-nn
+       (Need not be present)
+
+    Identify which GRIB code edition is being decoded.
+
+    In GRIB edition 1, the edition number is in octet 8.
+    In GRIB edition 0, octet 8 is reserved and set to 0.
+    In GRIB edition -1, octet 8 is a flag field and can have a
+    a valid value of 0, 1, 2 or 3.
+
+    However, GRIB edition number 0 has a fixed
+    length of 24, included in the message, for section 1, so
+    if the value extracted from octets 5-7 is 24 and that from
+    octet 8 is 0, it is safe to assume edition 0 of the code.
+
+  */
+  if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 )
+    {
+      /*
+	Set length of GRIB message to missing data value.
+      */
+      ISEC0_GRIB_Len = 0;
+    }
+  /*
+    If Grib Edition 1 and only length is required, go to section 9.
+  */
+  if ( dfunc == 'L' ) goto LABEL900;
+
+  /*
+    ----------------------------------------------------------------
+    PDS Product Definition Section (Section 1)
+    ----------------------------------------------------------------
+  */ 
+  pds = is + isLen;
+
+  pdsLen = decodePDS(pds, isec0, isec1);
+
+  /*
+    ----------------------------------------------------------------
+    GDS Grid Description Section (Section 2)
+    ----------------------------------------------------------------
+  */
+  gdsIncluded = ISEC1_Sec2Or3Flag & 128;
+
+  if ( gdsIncluded )
+    {
+      gds = is + isLen + pdsLen;
+
+      gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
+
+  isec3[0] = 0;
+  if ( bmsIncluded )
+    {
+      bms = is + isLen + pdsLen + gdsLen;
+
+      bmsLen = BMS_Len;
+      imaskSize = (bmsLen - 6)<<3;
+      bitmapSize = imaskSize - BMS_UnusedBits;
+      /*
+      fprintf(stderr," bitmapSize = %d %d %d\n", bitmapSize, imaskSize, BMS_UnusedBits);
+      */
+    }
+
+  /*
+    ----------------------------------------------------------------
+    BDS Binary Data Section (Section 4)
+    ----------------------------------------------------------------
+  */
+  bds = is + isLen + pdsLen + gdsLen + bmsLen;
+
+  bdsLen = ISEC0_GRIB_Len - (isLen + pdsLen + gdsLen + bmsLen);
+
+  bdsLen = TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, 
+				 fsec4, fsec4len, dfunc, bdsLen, numGridVals, llarge, iret);
+
+  if ( *iret != 0 ) return;
+
+  ISEC4_NumNonMissValues = ISEC4_NumValues;
+
+  if ( bitmapSize > 0 )
+    {
+      if ( dfunc != 'L' && dfunc != 'J' )
+	if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
+	  {
+	    lmissvalinfo = 0;
+	    FSEC3_MissVal = GRIB_MISSVAL;
+	    Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
+	  }
+
+      /* ISEC4_NumNonMissValues = ISEC4_NumValues; */
+      ISEC4_NumValues        = bitmapSize;
+
+      if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
+	{
+	  long i, j;
+	  GRIBPACK *pbitmap;
+	  GRIBPACK bitmap;
+	  GRIBPACK *imask;
+
+	  /*
+	  unsigned char *bitmap;
+	  bitmap = BMS_Bitmap;
+	  j = ISEC4_NumNonMissValues;
+	  for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+	    {
+	      if ( (bitmap[i/8]>>(7-(i&7)))&1 )
+		fsec4[i] = fsec4[--j];
+	      else
+		fsec4[i] = FSEC3_MissVal;
+	    }
+	  */
 
+	  imask = (GRIBPACK*) malloc(imaskSize*sizeof(GRIBPACK));
 
-void gribSetCalendar(int calendar)
-{
-  grib_calendar = calendar;
-}
+#if defined (VECTORCODE)
+	  (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
+	  pbitmap = imask;
+#else
+	  pbitmap = BMS_Bitmap;
+#endif
 
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	  for ( i = imaskSize/8-1; i >= 0; i-- )
+	    {
+	      bitmap = pbitmap[i];
+	      imask[i*8+0] = 1 & (bitmap >> 7);
+	      imask[i*8+1] = 1 & (bitmap >> 6);
+	      imask[i*8+2] = 1 & (bitmap >> 5);
+	      imask[i*8+3] = 1 & (bitmap >> 4);
+	      imask[i*8+4] = 1 & (bitmap >> 3);
+	      imask[i*8+5] = 1 & (bitmap >> 2);
+	      imask[i*8+6] = 1 & (bitmap >> 1);
+	      imask[i*8+7] = 1 & (bitmap);
+	    }
+
+	  j = 0;
+	  for ( i = 0; i < ISEC4_NumValues; i++ )
+	    if ( imask[i] ) j++;
+
+	  if ( ISEC4_NumNonMissValues != j )
+	    {
+	      if ( dfunc != 'J' && ISEC4_NumBits != 0 )
+		Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!",
+			j, ISEC4_NumNonMissValues);
+
+	      ISEC4_NumNonMissValues = j;
+	    }
+
+	  if ( dfunc != 'J' )
+	    {
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+	      for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+		fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
+	    }
+
+	  free(imask);
+	}
+    }
+
+  if ( ISEC2_Reduced )
+    {
+      int nlon, nlat;
+      int lsect3, lperio = 1, lveggy;
+      int ilat;
+      int nvalues = 0;
+      int dlon;
+
+      nlat = ISEC2_NumLat;
+      nlon = ISEC2_RowLonPtr[0];
+      for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+      for ( ilat = 1; ilat < nlat; ++ilat )
+	if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
+
+      dlon = ISEC2_LastLon-ISEC2_FirstLon;
+      if ( dlon < 0 ) dlon += 360000;
+	  
+      if ( nvalues != ISEC4_NumValues )
+	{
+	  *iret = -801;
+	}
+      //printf("nlat %d  nlon %d \n", nlat, nlon);
+      //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
+
+      if ( dfunc == 'R' && *iret == -801 )
+	gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
+		ISEC4_NumValues, nvalues);
+      
+      if ( dfunc == 'R' && *iret != -801 )
+	{
+	  ISEC2_Reduced = 0;
+	  ISEC2_NumLon = nlon;
+	  ISEC4_NumValues = nlon*nlat;
+
+	  lsect3 = bitmapSize > 0;
+	  lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) && 
+	          ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) || 
+	           (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+	
+	  (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
+	      
+	  if ( bitmapSize > 0 )
+	    {
+	      long i;
+	      int j = 0;
+	      
+	      for ( i = 0; i < ISEC4_NumValues; i++ )
+		if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
+		  
+	      ISEC4_NumNonMissValues = j;
+	    }
+	}
+    }
+
+
+  if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
+  esLen = 4;
+
+  gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+
+  if ( ISEC0_GRIB_Len )
+    if ( ISEC0_GRIB_Len < gribLen )
+      Warning("Length of GRIB message is inconsistent (grib_message_size=7867 < grib_record_size=9718)!", ISEC0_GRIB_Len, gribLen);
+
+  ISEC0_GRIB_Len = gribLen;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
 
-void grsdef(void)
-{
-  /*
-C---->
-C**** GRSDEF - Initial (default) setting of common area variables
-C              for GRIBEX package.
-C
-C     Purpose.
-C     --------
-C
-C     Sets initial values for common area variables for all
-C     routines of GRIBEX package, if not already done.
-C
-C**   Interface.
-C     ----------
-C
-C     CALL GRSDEF
-C
-C     Input Parameters.
-C     -----------------
-C
-C     None.
-C
-C     Output Parameters.
-C     ------------------
-C
-C     None.
-C
-C     Method.
-C     -------
-C
-C     Self-explanatory.
-C
-C     Externals.
-C     ----------
-C
-C     None.
-C
-C     Reference.
-C     ----------
-C
-C     See subroutine GRIBEX.
-C
-C     Comments.
-C     ---------
-C
-C     None
-C
-C     Author.
-C     -------
-C
-C     J. Clochard, Meteo France, for ECMWF - March 1998.
-C
-C     Modifications.
-C     --------------
-C
-C     J. Clochard, Meteo France, for ECMWF - June 1999.
-C     Add variable NSUBCE.
-C     Use a static variable to determine if initialisation has already
-C     been done. NUSER removed .
-C     Reverse defaults for NEXT2O and NLOC2O, for consistency with
-C     version 13.023 of software .
-C
-  */
   /*
-C     ----------------------------------------------------------------
-C*    Section 0 . Definition of variables.
-C     ----------------------------------------------------------------
+    ----------------------------------------------------------------
+    Section 9 . Abort/return to calling routine.
+    ----------------------------------------------------------------
   */
-  char *envString;
-  char *env_stream;
-  static int lfirst = TRUE;
-  extern int CGRIBEX_Const;
+ LABEL900:;
+
+  if ( ldebug )
+    {
+      gprintf(__func__, "Section 9.");
+      gprintf(__func__, "Output values set -");
+
+      gribPrintSec0(isec0);
+      gribPrintSec1(isec0, isec1);
+      /*
+	Print section 2 if present.
+      */
+      if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
+
+      if ( ! l_iorj )
+	{
+	  /*
+	    Print section 3 if present.
+	  */
+	  if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
+
+	  TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
+	  /*
+	    Special print for 2D spectra wave field real values in
+	    section 4
+	  */
+	  if ( (isec1[ 0] ==  140) && 
+	       (isec1[ 1] ==   98) && 
+	       (isec1[23] ==    1) && 
+	       ((isec1[39] == 1045) || (isec1[39] == 1081))  && 
+	       ((isec1[ 5] ==  250) || (isec1[ 5] ==  251)) )
+	    gribPrintSec4Wave(isec4);
+	}
+    }
+}
+
+#endif /* T */
+
+/* GRIB block 0 - indicator block */
+static
+void encodeIS(GRIBPACK *lGrib, long *gribLen)
+{
+  long z = *gribLen;
+
+  lGrib[0] = 'G';
+  lGrib[1] = 'R';
+  lGrib[2] = 'I';
+  lGrib[3] = 'B';
+
+  /* 
+   * lGrib[4]-lGrib[6] contains full length of grib record. 
+   * included before finished CODEGB
+   */
 
-  if ( ! lfirst ) return;
+  z = 7;   
+  Put1Byte(1); /* grib version */
+  z = 8;
 
-  /*
-    ----------------------------------------------------------------
-    Section 1 . Set values, conditionally.
-    ----------------------------------------------------------------
-  */
-  /*
-    Common area variables have not been set. Set them.
-    
-    User supplied reference value.
-  */
-  fref   = 0.0;
-  /*
-    Reference value supplied by user flag. Set to off.
-  */
-  nfref  = 0;
-  /*
-    User supplied maximum value.
-  */
-  fmaxval   = 0.0;
-  /*
-    Maximum value supplied by user flag. Set to off.
-  */
-  nfmaxval  = 0;
-  /*
-    Set rounding to 120 bytes on.
-  */
-  nrnd   = 1;
-  /*
-    Set GRIB calendar.
-  */
-  if ( grib_calendar == -1 )
+  *gribLen = z;
+}
+
+/* GRIB block 5 - end block */
+static
+void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
+{
+  long z = *gribLen;
+
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
+  lGrib[z++] = '7';
+
+  if ( z > JP23SET )
     {
-      grib_calendar = CALENDAR_PROLEPTIC;
-  
-      envString = getenv("GRIB_CALENDAR");
-      if ( envString )
+      long itemp;
+      long bdslen = z - 4;
+      /*
+      fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET);
+      exit(1);
+      */
+      /*
+	If a very large product, the section 4 length field holds
+	the number of bytes in the product after section 4 upto
+	the end of the padding bytes.
+	This is a fixup to get round the restriction on product lengths
+	due to the count being only 24 bits. It is only possible because
+	the (default) rounding for GRIB products is 120 bytes.
+      */
+      while ( z%120 ) lGrib[z++] = 0;
+
+      if ( z > JP23SET*120 )
 	{
-	  if      ( strncmp(envString, "standard", 8) == 0 )
-	    grib_calendar = CALENDAR_STANDARD;
-	  else if ( strncmp(envString, "proleptic", 9) == 0 )
-	    grib_calendar = CALENDAR_PROLEPTIC;
-	  else if ( strncmp(envString, "360days", 7) == 0 )
-	    grib_calendar = CALENDAR_360DAYS;
-	  else if ( strncmp(envString, "365days", 7) == 0 )
-	    grib_calendar = CALENDAR_365DAYS;
-	  else if ( strncmp(envString, "366days", 7) == 0 )
-	    grib_calendar = CALENDAR_366DAYS;
-	  else if ( strncmp(envString, "none", 4) == 0 )
-	    grib_calendar = CALENDAR_NONE;
+	  fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET*120);
+	  exit(1);
 	}
+
+      itemp = z / (-120);
+      itemp = JP23SET - itemp + 1;
+
+      lGrib[4] = itemp >> 16;
+      lGrib[5] = itemp >>  8;
+      lGrib[6] = itemp;
+
+      bdslen = z - bdslen;
+      lGrib[bdsstart  ] = bdslen >> 16;
+      lGrib[bdsstart+1] = bdslen >>  8;
+      lGrib[bdsstart+2] = bdslen;
     }
-  /*
-    Set debug print off.
-  */
-  ndbg   = 0;
-  
-  envString = getenv("GRIBEX_DEBUG");
-  if ( envString != NULL )
-    {
-      if ( !strncmp(envString, "ON", 2) )
-        ndbg = 1;
-      else if( *envString == '1')
-        ndbg = 1;
-      else if( *envString == '2')
-        ndbg = 2;
-      else
-        ndbg = 0;
-    }
-  /*
-    Set GRIBEX compatibility mode.
-  */
-  envString = getenv("GRIB_GRIBEX_MODE_ON");
-  if ( envString != NULL )
+  else
     {
-      if ( atoi(envString) == 1 ) CGRIBEX_Const = 0;
-    }
+      lGrib[4] = z >> 16;
+      lGrib[5] = z >>  8;
+      lGrib[6] = z;
 
-  /*
-    Set GRIB value checking on.
-  */
-  nvck   = 1;
-  
-  envString = getenv("GRIBEX_CHECK");
-  if ( envString )
-    {
-      if ( !strncmp(envString, "OFF", 3) )
-        nvck = 0;
-      else
-        nvck = 1;
+      while ( z%8 ) lGrib[z++] = 0;
     }
-  /*
-    See if output stream needs changing
-  */
-  grprsm = stdout;
-  env_stream = getenv("GRPRS_STREAM");
-  if ( env_stream )
+
+  *gribLen = z;
+}
+
+/* GRIB block 1 - product definition block. */
+
+#define DWD_extension_253_len 38
+#define DWD_extension_254_len 26
+#define ECMWF_extension_1_len 24
+#define MPIM_extension_1_len  18
+
+static
+long getLocalExtLen(int *isec1)
+{
+  long extlen = 0;
+
+  if ( ISEC1_LocalFLag )
     {
-      if ( isdigit((int) env_stream[0]) )
-	{
-	  int unit;
-	  unit = atoi(env_stream);
-	  if ( unit < 1 || unit > 99 )
-	    Warning("Invalid number for GRPRS_STREAM: %d", unit);
-	  else if ( unit == 2 )
-	    grprsm = stderr;
-	  else if ( unit == 6 )
-	    grprsm = stdout;
-	  else
-	    {
-	      char filename[] = "unit.00";
-	      sprintf(filename, "%2.2d", unit);
-	      grprsm = fopen(filename, "w");
-	      if ( ! grprsm )
-		SysError("GRPRS_STREAM = %d", unit);
-	    }
-	}
-      else
+      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
 	{
-	  if ( env_stream[0] )
-	    {
-	      grprsm = fopen(env_stream, "w");
-	      if ( ! grprsm )
-		SysError("GRPRS_STREAM = %s", env_stream);
-	    }
+	  if      ( isec1[36] == 254 ) extlen = DWD_extension_254_len;
+	  else if ( isec1[36] == 253 ) extlen = DWD_extension_253_len;
 	}
+      else if ( ISEC1_CenterID == 98 )
+        {
+	  if ( isec1[36] == 1 )   extlen = ECMWF_extension_1_len;
+        }
+      else if ( ISEC1_CenterID == 252 )
+        {
+	  if ( isec1[36] == 1 ) extlen = MPIM_extension_1_len;
+        }
     }
-  /*
-    Set P factor switch to default, user supplies the P factor.
-  */
-  nonoff = 0;
-  /*
-    Set abort flag to NO abort
-  */
-  noabort = 1;
-  /*
-    Mark common area values set by user.
-  */
-  lfirst = FALSE;
-  /*
-    Exhaustive use of all possible second-order packing methods
-    for HOPER='K'. Set to off.
-  */
-  num2ok  = 0;
-  /*
-    Use of extended second-order packing methods for grid-point
-    encoding (HOPER='C' and 'K'). Set to on.
-  */
-  next2o  = 1;
-  /*
-    Use of non-local second-order packing methods for grid-point
-    encoding (HOPER='C' and 'K'). Set to on.
-  */
-  nloc2o  = 1;
-  /*
-    Use of (all valid) sub-centre values for ECMWF fields encoding .
-    encoding. Set to off.
-  */
-  nsubce  = 0;
+
+  return (extlen);
+}
+
+static
+long getPdsLen(int *isec1)
+{
+  long pdslen = 28;
+
+  pdslen += getLocalExtLen(isec1);
+
+  return (pdslen);
+}
+
+static
+void encodePDS_DWD_local_Extension_254(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  int isvn;
+  long localextlen, i;
+  long z = *zs;
+
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-2; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+
+  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
+  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
+
+  *zs = z;
 }
 
-/* pack 8-bit bytes from 64-bit words to a packed buffer */
-/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (unsigned char) up[i]; */
+static
+void encodePDS_DWD_local_Extension_253(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc)
+  localextlen = DWD_extension_254_len;
+  for ( i = 0; i < localextlen-2; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+
+  isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier    */
+  Put2Byte(isvn);             /* DWD run type (0=main, 2=ass, 3=test) */
+  Put1Byte(isec1[50]);        /* 55 User id, specified by table       */
+  Put2Byte(isec1[51]);        /* 56 Experiment identifier             */
+  Put2Byte(isec1[52]);        /* 58 Ensemble identification by table  */
+  Put2Byte(isec1[53]);        /* 60 Number of ensemble members        */
+  Put2Byte(isec1[54]);        /* 62 Actual number of ensemble member  */
+  Put1Byte(isec1[55]);        /* 64 Model major version number        */ 
+  Put1Byte(isec1[56]);        /* 65 Model minor version number        */ 
+  Put1Byte(0);                /* 66 Blank for even buffer length      */
+
+  *zs = z;
+}
+
+static
+void encodePDS_ECMWF_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
 {
-#if defined (CRAY)
-  (void) _pack(up, cp, bc, tc);
-#else
-  U_BYTEORDER;
-  unsigned char *cp0;
-  unsigned INT64 upi, *up0, *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
-  long head, trail, inner, i, j;
-  long ipack = sizeof(INT64);
-  
-  /* Bytes until first word boundary in destination buffer */
+  // int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-12; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+                              /* 12 bytes explicitly encoded below:         */
+  Put1Byte(isec1[36]);        /* ECMWF local GRIB use definition identifier */
+                              /*    1=MARS labelling or ensemble fcst. data */
+  Put1Byte(isec1[37]);        /* Class                                      */
+  Put1Byte(isec1[38]);        /* Type                                       */
+  Put2Byte(isec1[39]);        /* Stream                                     */
 
-  inner = bc - head;
+  /* Version number or experiment identifier    */
+  Put1Byte(((unsigned char*) &isec1[40])[0]);
+  Put1Byte(((unsigned char*) &isec1[40])[1]);
+  Put1Byte(((unsigned char*) &isec1[40])[2]);
+  Put1Byte(((unsigned char*) &isec1[40])[3]);
 
-  /* Trailing bytes which do not make a full word */
+  Put1Byte(isec1[41]);        /* Ensemble forecast number                   */
+  Put1Byte(isec1[42]);        /* Total number of forecasts in ensemble      */
+  Put1Byte(0);                /* (Spare)                                    */
 
-  trail = inner & (ipack-1);
+  *zs = z;
+}
 
-  /* Number of bytes/words to be processed in fast loop */
+static
+void encodePDS_MPIM_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
+{
+  // int isvn;
+  long localextlen, i;
+  long z = *zs;
 
-  inner -= trail;
-  inner /= ipack;
+  localextlen = getLocalExtLen(isec1);
+  for ( i = 0; i < localextlen-6; i++ )
+    {
+      Put1Byte(isec1[24+i]);
+    }
+                              /* 6 bytes explicitly encoded below:          */
+  Put1Byte(isec1[36]);        /* MPIM local GRIB use definition identifier  */
+                              /*    (extension identifier)                  */
+  Put1Byte(isec1[37]);        /* type of ensemble forecast                  */
+  Put2Byte(isec1[38]);        /* individual ensemble member                 */
+  Put2Byte(isec1[39]);        /* number of forecasts in ensemble            */
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
-  ip4 = ip0 + 4;
-  ip5 = ip0 + 5;
-  ip6 = ip0 + 6;
-  ip7 = ip0 + 7;
+  *zs = z;
+}
 
-  up0 = (unsigned INT64 *) (cp + head);
+/* GRIB BLOCK 1 - PRODUCT DESCRIPTION SECTION */
+static
+void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
+{
+  GRIBPACK *lGrib = lpds;
+  long z = 0;
+  int ival, century, year;
 
-  /* Here we should process any bytes until the first word boundary 
-   * of our destination buffer 
-   * That code is missing so far  because our output buffer is 
-   * word aligned by FORTRAN 
-   */
+  century = ISEC1_Century;
+  year    = ISEC1_Year;
 
-  j = 0;
+  if ( century < 0 )
+    {
+      century = -century;
+      year    = -year;
+    }
 
-  if ( IS_BIGENDIAN() )
+  Put3Byte(pdsLen);               /*  0 Length of Block 1        */
+  Put1Byte(ISEC1_CodeTable);      /*  3 Local table number       */
+  Put1Byte(ISEC1_CenterID);       /*  4 Identification of centre */
+  Put1Byte(ISEC1_ModelID);        /*  5 Identification of model  */
+  Put1Byte(ISEC1_GridDefinition); /*  6 Grid definition          */
+  Put1Byte(ISEC1_Sec2Or3Flag);    /*  7 Block 2 included         */
+  Put1Byte(ISEC1_Parameter);      /*  8 Parameter Code           */
+  Put1Byte(ISEC1_LevelType);      /*  9 Type of level            */
+  if ( (ISEC1_LevelType !=  20) &&
+       (ISEC1_LevelType != GRIB1_LTYPE_99)         &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC)   &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE)   &&
+       (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT)     &&
+       (ISEC1_LevelType != GRIB1_LTYPE_SIGMA)      &&
+       (ISEC1_LevelType != GRIB1_LTYPE_HYBRID)     &&
+       (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH)  &&
+       (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
+       (ISEC1_LevelType != 115) &&
+       (ISEC1_LevelType != 117) &&
+       (ISEC1_LevelType != 125) &&
+       (ISEC1_LevelType != 127) &&
+       (ISEC1_LevelType != 160) &&
+       (ISEC1_LevelType != 210) )
     {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  upi =             (   ip0[j]          << 56 ) 
-	                 |  ( ( ip1[j] & 0xFF ) << 48 )
-	                 |  ( ( ip2[j] & 0xFF ) << 40 )
-	                 |  ( ( ip3[j] & 0xFF ) << 32 )
-	                 |  ( ( ip4[j] & 0xFF ) << 24 ) ;
-	  up0[i] = upi   |  ( ( ip5[j] & 0xFF ) << 16 )
-	                 |  ( ( ip6[j] & 0xFF ) <<  8 )
-	                 |    ( ip7[j] & 0xFF ) ;
-	  j += ipack;
-	}
+      Put1Byte(ISEC1_Level1);
+      Put1Byte(ISEC1_Level2);
     }
   else
     {
-      for ( i = 0 ; i < inner ; i++ )
-	{
-	  upi =             (   ip7[j]          << 56 ) 
-	                 |  ( ( ip6[j] & 0xFF ) << 48 )
-                         |  ( ( ip5[j] & 0xFF ) << 40 )
-                         |  ( ( ip4[j] & 0xFF ) << 32 )
-                         |  ( ( ip3[j] & 0xFF ) << 24 ) ;
-	  up0[i] = upi   |  ( ( ip2[j] & 0xFF ) << 16 )
-                         |  ( ( ip1[j] & 0xFF ) <<  8 )
-                         |    ( ip0[j] & 0xFF ) ;
-	  j += ipack;
-	}
+      Put2Byte(ISEC1_Level1);     /* 10 Level                    */    
     }
 
-  cp0 = (unsigned char *) ( up0 + inner );
-  if ( trail > 0 )
+  Put1Int(year);                  /* 12 Year of Century          */
+  Put1Byte(ISEC1_Month);          /* 13 Month                    */
+  Put1Byte(ISEC1_Day);            /* 14 Day                      */
+  Put1Byte(ISEC1_Hour);           /* 15 Hour                     */
+  Put1Byte(ISEC1_Minute);         /* 16 Minute                   */
+
+  Put1Byte(ISEC1_TimeUnit);       /* 17 Time unit                */
+  if ( ISEC1_TimeRange == 10 )
     {
-      up0[inner] = 0;
-      for ( i = 0 ; i < trail ; i ++ )
-	{
-	  *cp0 = (unsigned char) ip0[ipack*inner+i];
-	  cp0++;
-	}
+      Put1Byte(ISEC1_TimePeriod1);
+      Put1Byte(ISEC1_TimePeriod2);
+    }
+  else if ( ISEC1_TimeRange == 113 || ISEC1_TimeRange ==   0 )
+    {
+      Put1Byte(ISEC1_TimePeriod1);
+      Put1Byte(0);
+    }
+  else if ( ISEC1_TimeRange ==   5 || ISEC1_TimeRange ==   4 || 
+	    ISEC1_TimeRange ==   3 || ISEC1_TimeRange ==   2 )
+    {
+      Put1Byte(0);
+      Put1Byte(ISEC1_TimePeriod2);
+    }
+  else
+    {
+      Put1Byte(0);
+      Put1Byte(0); 
     }
+  Put1Byte(ISEC1_TimeRange);      /* 20 Timerange flag           */
+  Put2Byte(ISEC1_AvgNum);         /* 21 Average                  */
 
-  if ( tc != -1 )
+  Put1Byte(ISEC1_AvgMiss);        /* 23 Missing from averages    */
+  Put1Byte(century);              /* 24 Century                  */
+  Put1Byte(ISEC1_SubCenterID);    /* 25 Subcenter                */
+  Put2Byte(ISEC1_DecScaleFactor); /* 26 Decimal scale factor     */
+
+  if ( ISEC1_LocalFLag )
     {
-      bc++;
-      *cp0 = (unsigned char) tc;
+      if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
+	{
+	  if      ( isec1[36] == 254 ) encodePDS_DWD_local_Extension_254(lGrib, &z, isec1);
+	  else if ( isec1[36] == 253 ) encodePDS_DWD_local_Extension_253(lGrib, &z, isec1);
+	}
+      else if ( ISEC1_CenterID == 98 )
+	{
+	  if ( isec1[36] == 1 ) encodePDS_ECMWF_local_Extension_1(lGrib, &z, isec1);
+	}
+      else if ( ISEC1_CenterID == 252 )
+	{
+	  if ( isec1[36] == 1 ) encodePDS_MPIM_local_Extension_1(lGrib, &z, isec1);
+	}
+      else
+	{
+	  long i, localextlen;
+	  localextlen = getLocalExtLen(isec1);
+	  for ( i = 0; i < localextlen; i++ )
+	    {
+	      Put1Byte(isec1[24+i]);
+	    }
+	}
     }
-#endif
-  return (bc);
 }
 
-/* unpack 8-bit bytes from a packed buffer with 64-bit words */
-/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT64) cp[i]; */
-
-long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc)
-{
-  U_BYTEORDER;
-  const unsigned char *cp0;
-  unsigned INT64 *up0;
-  unsigned INT64 *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
-  long head, trail, inner, i, j;
-  long offset;
-  long ipack = sizeof(INT64);
-
-  /* Bytes until first word boundary in source buffer */
-
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
-  if ( head > bc ) head = bc;
-
-  inner = bc - head;
-
-  /* Trailing bytes which do not make a full word */
- 
-  trail = inner & (ipack-1);
- 
-  /* Number of bytes/words to be processed in fast loop */
-
-  inner -= trail;
-  inner /= ipack;
+int  BitsPerInt = (int) (sizeof(int) * 8);
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
-  ip4 = ip0 + 4;
-  ip5 = ip0 + 5;
-  ip6 = ip0 + 6;
-  ip7 = ip0 + 7;
 
-  up0 = (unsigned INT64 *) (cp + head);
 
-  /* Process any bytes until the first word boundary 
-   * of our source buffer 
-   */
-  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT64) cp[i];
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
 
-  j = 0;
+static
+void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
+				     const T *data, T zref, T factor, size_t *gz)
+{
+  size_t i, z = *gz;
+  unsigned int ival;
+  int cbits, jbits;
+  unsigned int c;
+  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+    
+  /* code from gribw routine flist2bitstream */
 
-  if ( IS_BIGENDIAN() )
+  cbits = 8;
+  c = 0;
+  for ( i = packStart; i < datasize; i++ )
     {
-#if defined (CRAY)
-#pragma _CRI ivdep
-#endif
-#if defined (SX)
-#pragma vdir nodep
-#endif
-#ifdef __uxpch__
-#pragma loop novrec
-#endif
-      for ( i = 0 ; i < inner ; i++ )
+      /* note float -> unsigned int .. truncate */
+      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+      /*
+	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
+	if ( ival < 0 ) ival = 0;
+      */
+      jbits = numBits;
+      while ( cbits <= jbits ) 
 	{
-	  ip0[j] = (up0[i] >> 56) & 0xFF;
-	  ip1[j] = (up0[i] >> 48) & 0xFF;
-	  ip2[j] = (up0[i] >> 40) & 0xFF;
-	  ip3[j] = (up0[i] >> 32) & 0xFF;
-	  ip4[j] = (up0[i] >> 24) & 0xFF;
-	  ip5[j] = (up0[i] >> 16) & 0xFF;
-	  ip6[j] = (up0[i] >>  8) & 0xFF;
-	  ip7[j] = (up0[i])       & 0xFF;
-
-	  j += ipack;
+	  if ( cbits == 8 )
+	    {
+	      jbits -= 8;
+	      lGrib[z++] = (ival >> jbits) & 0xFF;
+	    }
+	  else
+	    {
+	      jbits -= cbits;
+	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+	      cbits = 8;
+	      c = 0;
+	    }
 	}
-    }
-  else
-    {
-      for ( i = 0 ; i < inner ; i++ )
+      /* now jbits < cbits */
+      if ( jbits )
 	{
-	  ip7[j] = (up0[i] >> 56) & 0xFF;
-	  ip6[j] = (up0[i] >> 48) & 0xFF;
-	  ip5[j] = (up0[i] >> 40) & 0xFF;
-	  ip4[j] = (up0[i] >> 32) & 0xFF;
-	  ip3[j] = (up0[i] >> 24) & 0xFF;
-	  ip2[j] = (up0[i] >> 16) & 0xFF;
-	  ip1[j] = (up0[i] >>  8) & 0xFF;
-	  ip0[j] = (up0[i])       & 0xFF;
-
-	  j += ipack;
+	  c = (c << jbits) + (ival & mask[jbits]);
+	  cbits -= jbits;
 	}
     }
+  if ( cbits != 8 ) lGrib[z++] = c << cbits;
 
-  if ( trail > 0 )
-    {
-      offset = head + ipack*inner;
-      cp0 = cp + offset;
-      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT64) cp0[i];
-    }
-  /*
-  if ( tc != -1 ) {
-    bc++;
-    *cp0 = (unsigned char) tc;
-  }
-  */
-  return (bc);
+  *gz = z;
 }
 
-/* pack 8-bit bytes from 32-bit words to a packed buffer */
-/* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (char) up[i]; */
-
-#if  defined  (INT32)
-long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+				    const T *restrict data, T zref, T factor, size_t *gz)
 {
-  U_BYTEORDER;
-  unsigned char *cp0;
-  unsigned INT32 *up0, *ip0, *ip1, *ip2, *ip3;
-  long head, trail, inner, i, j;
-  long ipack = sizeof(INT32);
-  
-  /* Bytes until first word boundary in destination buffer */
+  size_t i, z = *gz;
+  uint16_t ui16;
+  T tmp;
 
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; i++ )
+    {
+      tmp = ((data[i] - zref) * factor + 0.5);
+      ui16 = (uint16_t) tmp;
+      lGrib[z  ] = ui16 >>  8;
+      lGrib[z+1] = ui16;
+      z += 2;
+    }
 
-  inner = bc - head;
+  *gz = z;
+}
 
-  /* Trailing bytes which do not make a full word */
+static
+void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize, 
+			      GRIBPACK *restrict lGrib,
+			      const T *restrict data, 
+			      T zref, T factor, size_t *gz)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_minmax, end_minmax;
+#endif
 
-  trail = inner & (ipack-1);
+  uint32_t ui32;
+  size_t i, z = *gz;
+  T tmp;
 
-  /* Number of bytes/words to be processed in fast loop */
+  data += packStart;
+  datasize -= packStart;
 
-  inner -= trail;
-  inner /= ipack;
+  if      ( numBits ==  8 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit base");
+#endif
 
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+	  lGrib[z  ] = (uint16_t) tmp;
+          z++;
+	}
 
-  up0 = (unsigned INT32 *) (cp + head);
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
+    }
+  else if ( numBits == 16 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_minmax = mach_absolute_time();
+#endif
 
-  /* Here we should process any bytes until the first word boundary 
-   * of our destination buffer 
-   * That code is missing so far  because our output buffer is 
-   * word aligned by FORTRAN 
-   */
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+          avx_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#elif defined _ENABLE_SSE4_1
+          sse41_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#else
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+#endif
+        }
+      else
+        {
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+        }
 
-  j = 0;
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_minmax = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
+    }
+  else if ( numBits == 24 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit base");
+#endif
 
-  if ( IS_BIGENDIAN() )
-    {
-#if defined (CRAY)
+#if   defined (CRAY)
 #pragma _CRI ivdep
-#endif
-#if defined (SX)
+#elif defined (SX)
 #pragma vdir nodep
-#endif
-#ifdef __uxpch__
+#elif defined (__uxp__)
 #pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
 #endif
-      for ( i = 0 ; i < inner ; i++ )
+      for ( i = 0; i < datasize; i++ )
 	{
-	  up0[i] =          (   ip0[j]          << 24 ) 
-	                 |  ( ( ip1[j] & 0xFF ) << 16 )
-	                 |  ( ( ip2[j] & 0xFF ) <<  8 )
-	                 |    ( ip3[j] & 0xFF ) ;
-	  j += ipack;
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 16;
+          lGrib[z+1] =  ui32 >>  8;
+          lGrib[z+2] =  ui32;
+          z += 3;
 	}
+
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
     }
-  else
+  else if ( numBits == 32 )
     {
-      for ( i = 0 ; i < inner ; i++ )
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit base");
+#endif
+
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
 	{
-	  up0[i] =          (   ip3[j]          << 24 ) 
-	                 |  ( ( ip2[j] & 0xFF ) << 16 )
-                         |  ( ( ip1[j] & 0xFF ) <<  8 )
-                         |    ( ip0[j] & 0xFF ) ;
-	  j += ipack;
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 24;
+          lGrib[z+1] =  ui32 >> 16;
+          lGrib[z+2] =  ui32 >>  8;
+          lGrib[z+3] =  ui32;
+          z += 4;
 	}
-    }
 
-  cp0 = (unsigned char *) ( up0 + inner );
-  if ( trail > 0 )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
+    }
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      up0[inner] = 0;
-      for ( i = 0 ; i < trail ; i ++ )
-	{
-	  *cp0 = (unsigned char) ip0[ipack*inner+i];
-	  cp0++;
-	}
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-
-  if ( tc != -1 )
+  else if ( numBits == 0 )
     {
-      bc++;
-      *cp0 = (unsigned char) tc;
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  return (bc);
+  *gz = z;
 }
-#endif
 
-/* unpack 8-bit bytes from a packed buffer with 32-bit words */
-/* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT32) cp[i]; */
-
-#if  defined  (INT32)
-long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
+static
+void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize, 
+				       GRIBPACK *restrict lGrib,
+				       const T *restrict data, 
+				       T zref, T factor, size_t *gz)
 {
   U_BYTEORDER;
-  const unsigned char *cp0;
-  unsigned INT32 *up0;
-  unsigned INT32 *ip0, *ip1, *ip2, *ip3;
-  long head, trail, inner, i, j;
-  long offset;
-  long ipack = sizeof(INT32);
-
-  /* Bytes until first word boundary in source buffer */
-
-  head = ( (long) cp ) & (ipack-1);
-  if ( head != 0 ) head = ipack - head;
-  if ( head > bc ) head = bc;
-
-  inner = bc - head;
-
-  /* Trailing bytes which do not make a full word */
- 
-  trail = inner & (ipack-1);
- 
-  /* Number of bytes/words to be processed in fast loop */
-
-  inner -= trail;
-  inner /= ipack;
-
-  ip0 = up + head;
-  ip1 = ip0 + 1;
-  ip2 = ip0 + 2;
-  ip3 = ip0 + 3;
+  size_t i, j, z = *gz;
+#ifdef _ARCH_PWR6
+#define __UNROLL_DEPTH_2 8
+#else
+#define __UNROLL_DEPTH_2 8
+#endif
+  size_t residual;
+  size_t ofs;
+  T dval[__UNROLL_DEPTH_2];
+  unsigned long ival;
 
-  up0 = (unsigned INT32 *) (cp + head);
+  data += packStart;
+  datasize -= packStart;
+  residual =  datasize % __UNROLL_DEPTH_2;
+  ofs = datasize - residual;
 
-  /* Process any bytes until the first word boundary 
-   * of our source buffer 
-   */
-  for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT32) cp[i];
+  // reducing FP operations to single FMA is slowing down on pwr6 ...
 
-  j = 0;
+  if      ( numBits ==  8 )
+    {
+      unsigned char *cgrib = (unsigned char *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      *cgrib++ =  (unsigned long) dval[j];
+	    }
+	  z += __UNROLL_DEPTH_2;
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  *cgrib++ = (unsigned long) dval[j];
+	}
+      z += residual;
 
-  if ( IS_BIGENDIAN() )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
+    }
+  else if ( numBits == 16 )
     {
-#if defined (CRAY)
-#pragma _CRI ivdep
+      unsigned short *sgrib = (unsigned short *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit unrolled");
 #endif
-#if defined (SX)
-#pragma vdir nodep
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *sgrib++ = (unsigned long) dval[j];
+		}
+	      z += 2*__UNROLL_DEPTH_2;
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] = ival >>  8;
+		  lGrib[z+1] = ival;
+		  z += 2;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *sgrib++ = (unsigned long) dval[j];
+	    }
+	  z += 2*residual;
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] = ival >>  8;
+	      lGrib[z+1] = ival;
+	      z += 2;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
 #endif
-#ifdef __uxpch__
-#pragma loop novrec
+    }
+  else if ( numBits == 24 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit unrolled");
 #endif
-      for ( i = 0 ; i < inner ; i++ )
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
 	{
-	  ip0[j] = (up0[i] >> 24) & 0xFF;
-	  ip1[j] = (up0[i] >> 16) & 0xFF;
-	  ip2[j] = (up0[i] >>  8) & 0xFF;
-	  ip3[j] = (up0[i])       & 0xFF;
-
-	  j += ipack;
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 16;
+	      lGrib[z+1] =  ival >>  8;
+	      lGrib[z+2] =  ival;
+	      z += 3;
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  ival = (unsigned long) dval[j];
+	  lGrib[z  ] =  ival >> 16;
+	  lGrib[z+1] =  ival >>  8;
+	  lGrib[z+2] =  ival;
+	  z += 3;
 	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
     }
-  else
+  else if ( numBits == 32 )
     {
-      for ( i = 0 ; i < inner ; i++ )
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit unrolled");
+#endif
+      unsigned int *igrib = (unsigned int *) (lGrib + z);
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
 	{
-	  ip3[j] = (up0[i] >> 24) & 0xFF;
-	  ip2[j] = (up0[i] >> 16) & 0xFF;
-	  ip1[j] = (up0[i] >>  8) & 0xFF;
-	  ip0[j] = (up0[i])       & 0xFF;
-
-	  j += ipack;
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *igrib = (unsigned long) dval[j];
+		  igrib++;
+		  z += 4;
+		}
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] =  ival >> 24;
+		  lGrib[z+1] =  ival >> 16;
+		  lGrib[z+2] =  ival >>  8;
+		  lGrib[z+3] =  ival;
+		  z += 4;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *igrib = (unsigned long) dval[j];
+	      igrib++;
+	      z += 4;
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 24;
+	      lGrib[z+1] =  ival >> 16;
+	      lGrib[z+2] =  ival >>  8;
+	      lGrib[z+3] =  ival;
+	      z += 4;
+	    }
 	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
     }
-
-  if ( trail > 0 )
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      offset = head + ipack*inner;
-      cp0 = cp + offset;
-      for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT32) cp0[i];
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-  /*
-  if ( tc != -1 ) {
-    bc++;
-    *cp0 = (unsigned char) tc;
-  }
-  */
-
-  return (bc);
-}
-#endif
-#include <stdio.h>
-
-void prtbin(int kin, int knbit, int *kout, int *kerr)
-{
-  /*
-
-    Produces a decimal number with ones and zeroes
-    corresponding to the ones and zeroes of the input
-    binary number.
-    eg input number 1011 binary, output number 1011 decimal.
-
-
-    Input Parameters:
-    
-       kin   - Integer variable containing binary number.
-
-       knbit - Number of bits in binary number.
-
-    Output Parameters:
-
-       kout  - Integer variable containing decimal value
-               with ones and zeroes corresponding to those of
-	       the input binary number.
-
-       kerr  - 0, If no error.
-               1, Number of bits in binary number exceeds
-	          maximum allowed or is less than 1.
-
-
-    Converted from EMOS routine PRTBIN.
-
-       Uwe Schulzweida   MPIfM   01/04/2001
-
-  */
-  int idec;
-  int ik;
-  int itemp;
-  int j;
-
-  /*
-    Check length of binary number to ensure decimal number
-    generated will fit in the computer word - in this case will
-    it fit in a Cray 48 bit integer?
-  */
-  if ( knbit < 1 || knbit > 14 )
+  else if ( numBits == 0 )
     {
-      *kerr = 1;
-      printf(" prtbin : Error in binary number length - %3d bits.\n", knbit);
-      return;
     }
   else
-    *kerr = 0;
-  /*
-    -----------------------------------------------------------------
-    Section 1. Generate required number.
-    -----------------------------------------------------------------
-  */
-  *kout = 0;
-  ik    = kin;
-  idec  = 1;
-
-  for ( j = 0; j < knbit; j++ )
     {
-      itemp = ik - ( (ik/2)*2 );
-      *kout = (*kout) + itemp * idec;
-      ik    = ik / 2;
-      idec  = idec * 10;
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  return;
+  *gz = z;
+#undef __UNROLL_DEPTH_2
 }
 
+#endif /* T */
 
-void ref2ibm(double *pref, int kbits)
-{
-  /*
-
-    Purpose:
-    --------
-
-    Code and check reference value in IBM format
-
-    Input Parameters:
-    -----------------
-
-    pref       - Reference value
-    kbits      - Number of bits per computer word.
-
-    Output Parameters:
-    ------------------
-
-    pref       - Reference value
-
-    Method:
-    -------
-
-    Codes in IBM format, then decides to ensure that reference 
-    value used for packing is not different from that stored
-    because of packing differences.
-
-    Externals.
-    ----------
-
-    confp3    - Encode into IBM floating point format.
-    decfp2    - Decode from IBM floating point format.
-
-    Reference:
-    ----------
-
-    None.
-
-    Comments:
-    --------
-
-    None.
-
-    Author:
-    -------
-
-    J.D.Chambers     ECMWF      17:05:94
-
-    Modifications:
-    --------------
-
-    Uwe Schulzweida   MPIfM   01/04/2001
-
-    Convert to C from EMOS library version 130
-
-  */
-
-  static int itrnd;
-  static int kexp, kmant;
-  static double ztemp, zdumm;
-  extern int CGRIBEX_Debug;
-
-  /* ----------------------------------------------------------------- */
-  /*   Section 1. Convert to and from IBM format.                      */
-  /* ----------------------------------------------------------------- */
-
-  /*  Convert floating point reference value to IBM representation. */
-
-  itrnd = 1;
-  zdumm = ztemp = *pref;
-  confp3(zdumm, &kexp, &kmant, kbits, itrnd);
-
-  if ( kexp == 0 && kmant == 0 ) return;
-
-  /*  Set reference value to that actually stored in the GRIB code. */
-
-  *pref = decfp2(kexp, kmant);
-
-  /*  If the nearest number which can be represented in */
-  /*  GRIB format is greater than the reference value,  */
-  /*  find the nearest number in GRIB format lower      */
-  /*  than the reference value.                         */
-
-  if ( ztemp < *pref )
-    {
-      /*  Convert floating point to GRIB representation */
-      /*  using truncation to ensure that the converted */
-      /*  number is smaller than the original one.      */
-
-      itrnd = 0;
-      zdumm = *pref = ztemp;
-      confp3(zdumm, &kexp, &kmant, kbits, itrnd);
-
-      /*  Set reference value to that stored in the GRIB code. */
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
 
-      *pref = decfp2(kexp, kmant);
+static
+void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
+				     const T *data, T zref, T factor, size_t *gz)
+{
+  size_t i, z = *gz;
+  unsigned int ival;
+  int cbits, jbits;
+  unsigned int c;
+  static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
+    
+  /* code from gribw routine flist2bitstream */
 
-      if ( ztemp < *pref )
+  cbits = 8;
+  c = 0;
+  for ( i = packStart; i < datasize; i++ )
+    {
+      /* note float -> unsigned int .. truncate */
+      ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+      /*
+	if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
+	if ( ival < 0 ) ival = 0;
+      */
+      jbits = numBits;
+      while ( cbits <= jbits ) 
 	{
-	  if ( CGRIBEX_Debug )
+	  if ( cbits == 8 )
 	    {
-	      Message("Reference value error.");
-	      Message("Notify Met.Applications Section.");
-	      Message("ZTEMP = ", ztemp);
-	      Message("PREF = ", pref);
+	      jbits -= 8;
+	      lGrib[z++] = (ival >> jbits) & 0xFF;
 	    }
-	  *pref = ztemp;
+	  else
+	    {
+	      jbits -= cbits;
+	      lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+	      cbits = 8;
+	      c = 0;
+	    }
+	}
+      /* now jbits < cbits */
+      if ( jbits )
+	{
+	  c = (c << jbits) + (ival & mask[jbits]);
+	  cbits -= jbits;
 	}
     }
+  if ( cbits != 8 ) lGrib[z++] = c << cbits;
 
-  return;
-} /* ref2ibm */
-#include <string.h>
-
-
-int correct_bdslen(int bdslen, long recsize, long gribpos)
-{
-  /*
-    If a very large product, the section 4 length field holds
-    the number of bytes in the product after section 4 upto
-    the end of the padding bytes.
-    This is a fixup to get round the restriction on product lengths
-    due to the count being only 24 bits. It is only possible because
-    the (default) rounding for GRIB products is 120 bytes.
-  */
-  if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
-  return (bdslen);
+  *gz = z;
 }
 
-
-int grib1Sections(unsigned char *gribbuffer, long bufsize, unsigned char **pdsp,
-		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp)
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+				    const T *restrict data, T zref, T factor, size_t *gz)
 {
-  unsigned char *pds, *gds, *bms, *bds;
-  unsigned char *bufpointer, *is, *section;
-  int gribversion, grib1offset;
-  long gribsize = 0, recsize;
-  int bdslen;
+  size_t i, z = *gz;
+  uint16_t ui16;
+  T tmp;
 
-  section = gribbuffer;
-  is = gribbuffer;
-  if ( ! GRIB_START(section) )
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+  for ( i = 0; i < datasize; i++ )
     {
-      fprintf(stderr, "Wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
+      tmp = ((data[i] - zref) * factor + 0.5);
+      ui16 = (uint16_t) tmp;
+      lGrib[z  ] = ui16 >>  8;
+      lGrib[z+1] = ui16;
+      z += 2;
     }
 
-  recsize = gribrec_len(section[4], section[5], section[6]);
+  *gz = z;
+}
 
-  gribversion = GRIB_EDITION(section);
-  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
+static
+void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize, 
+			      GRIBPACK *restrict lGrib,
+			      const T *restrict data, 
+			      T zref, T factor, size_t *gz)
+{
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER 
+  uint64_t start_minmax, end_minmax;
+#endif
 
-  if ( gribversion == 1 )
-    grib1offset = 4;
-  else
-    grib1offset = 0;
+  uint32_t ui32;
+  size_t i, z = *gz;
+  T tmp;
 
-  pds = is + 4 + grib1offset;
-  bufpointer = pds + PDS_Len;
-  gribsize += 4 + grib1offset + PDS_Len;
+  data += packStart;
+  datasize -= packStart;
 
-  if ( PDS_HAS_GDS )
+  if      ( numBits ==  8 )
     {
-      gds = bufpointer;
-      bufpointer += GDS_Len;
-      gribsize += GDS_Len;
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit base");
+#endif
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+	  lGrib[z  ] = (uint16_t) tmp;
+          z++;
+	}
+
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
     }
-  else
+  else if ( numBits == 16 )
     {
-      gds = NULL;
-    }
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit base");
+#elif defined _GET_X86_COUNTER 
+      start_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      start_minmax = mach_absolute_time();
+#endif
 
-  if ( PDS_HAS_BMS )
-    {
-      bms = bufpointer;
-      bufpointer += BMS_Len;
-      gribsize += BMS_Len;
+      if ( sizeof(T) == sizeof(double) )
+      	{ 
+#if defined _ENABLE_AVX
+          avx_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#elif defined _ENABLE_SSE4_1
+          sse41_encode_array_2byte_double(datasize, lGrib, data, zref, factor, &z);
+#else
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+#endif
+        }
+      else
+        {
+          TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
+        }
+
+#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
+#if defined _GET_X86_COUNTER 
+      end_minmax = _rdtsc();
+#elif defined _GET_MACH_COUNTER 
+      end_minmax = mach_absolute_time();
+#endif
+#if defined _ENABLE_AVX
+      printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#elif defined _ENABLE_SSE4_1
+      printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#else
+      printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
+#endif  
+#endif
+      
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
     }
-  else
+  else if ( numBits == 24 )
     {
-      bms = NULL;
-    }
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit base");
+#endif
 
-  bds = bufpointer;
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, gribsize);
-  bufpointer += bdslen;
-  gribsize += bdslen;
-  gribsize += 4;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 16;
+          lGrib[z+1] =  ui32 >>  8;
+          lGrib[z+2] =  ui32;
+          z += 3;
+	}
 
-  if ( gribsize > bufsize )
-    {
-      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", bufsize, gribsize);
-      return (1);
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
     }
+  else if ( numBits == 32 )
+    {
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit base");
+#endif
 
-  *pdsp = pds;
-  *gdsp = gds;
-  *bmsp = bms;
-  *bdsp = bds;
+#if   defined (CRAY)
+#pragma _CRI ivdep
+#elif defined (SX)
+#pragma vdir nodep
+#elif defined (__uxp__)
+#pragma loop novrec
+#elif defined (__ICC)
+#pragma ivdep
+#endif
+      for ( i = 0; i < datasize; i++ )
+	{
+	  tmp = ((data[i] - zref) * factor + 0.5);
+          ui32 = (uint32_t) tmp;
+          lGrib[z  ] =  ui32 >> 24;
+          lGrib[z+1] =  ui32 >> 16;
+          lGrib[z+2] =  ui32 >>  8;
+          lGrib[z+3] =  ui32;
+          z += 4;
+	}
 
-  /* end section - "7777" in ascii */
-  if ( !GRIB_FIN(bufpointer) )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
+    }
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
-      return (-2);
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
+    }
+  else if ( numBits == 0 )
+    {
+    }
+  else
+    {
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  return (0);
+  *gz = z;
 }
 
-
-int grib2Sections(unsigned char *gribbuffer, long bufsize, unsigned char **idsp,
-		  unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
-		  unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp)
+static
+void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize, 
+				       GRIBPACK *restrict lGrib,
+				       const T *restrict data, 
+				       T zref, T factor, size_t *gz)
 {
-  unsigned char *section;
-  long sec_len;
-  int sec_num;
-  int gribversion;
-  int i, msec;
-  long gribsize;
-  long grib_len = 0;
+  U_BYTEORDER;
+  size_t i, j, z = *gz;
+#ifdef _ARCH_PWR6
+#define __UNROLL_DEPTH_2 8
+#else
+#define __UNROLL_DEPTH_2 8
+#endif
+  size_t residual;
+  size_t ofs;
+  T dval[__UNROLL_DEPTH_2];
+  unsigned long ival;
 
-  *idsp = NULL;
-  *lusp = NULL;
-  *gdsp = NULL;
-  *pdsp = NULL;
-  *drsp = NULL;
-  *bmsp = NULL;
-  *bdsp = NULL;
+  data += packStart;
+  datasize -= packStart;
+  residual =  datasize % __UNROLL_DEPTH_2;
+  ofs = datasize - residual;
 
-  section = gribbuffer;
-  sec_len = 16;
+  // reducing FP operations to single FMA is slowing down on pwr6 ...
 
-  if ( !GRIB_START(section) )
+  if      ( numBits ==  8 )
     {
-      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
-    }
+      unsigned char *cgrib = (unsigned char *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(2, "pack 8 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      *cgrib++ =  (unsigned long) dval[j];
+	    }
+	  z += __UNROLL_DEPTH_2;
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  *cgrib++ = (unsigned long) dval[j];
+	}
+      z += residual;
 
-  gribversion = GRIB_EDITION(section);
-  if ( gribversion != 2 )
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(2);
+#endif
+    }
+  else if ( numBits == 16 )
     {
-      fprintf(stderr, "wrong GRIB version %d\n", gribversion);
-      return (-1);      
+      unsigned short *sgrib = (unsigned short *) (lGrib + z);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(3, "pack 16 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *sgrib++ = (unsigned long) dval[j];
+		}
+	      z += 2*__UNROLL_DEPTH_2;
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] = ival >>  8;
+		  lGrib[z+1] = ival;
+		  z += 2;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *sgrib++ = (unsigned long) dval[j];
+	    }
+	  z += 2*residual;
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] = ival >>  8;
+	      lGrib[z+1] = ival;
+	      z += 2;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(3);
+#endif
     }
-
-  gribsize = 0;
-  for ( i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | section[8+i];
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 1 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "ids %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 1 )
+  else if ( numBits == 24 )
     {
-      fprintf(stderr, "Unexpected section1 number %d\n", sec_num);
-      return (-1);
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(4, "pack 24 bit unrolled");
+#endif
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 16;
+	      lGrib[z+1] =  ival >>  8;
+	      lGrib[z+2] =  ival;
+	      z += 3;
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  ival = (unsigned long) dval[j];
+	  lGrib[z  ] =  ival >> 16;
+	  lGrib[z+1] =  ival >>  8;
+	  lGrib[z+2] =  ival;
+	  z += 3;
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(4);
+#endif
     }
-
-  *idsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 2 and 3 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "lus %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num == 2 )
+  else if ( numBits == 32 )
     {
-      *lusp = section;
-
-      grib_len += sec_len;
-      section  += sec_len;
-
-      /* section 3 */
-      sec_len = GRIB2_SECLEN(section);
-      sec_num = GRIB2_SECNUM(section);
-      //fprintf(stderr, "gds %d %ld\n", sec_num, sec_len);
-
-      *gdsp = section;
+#ifdef _GET_IBM_COUNTER 
+      hpmStart(5, "pack 32 bit unrolled");
+#endif
+      unsigned int *igrib = (unsigned int *) (lGrib + z);
+      for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 ) 
+	{
+	  for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+	    {
+	      dval[j] = ((data[i+j] - zref) * factor + 0.5);
+	    }
+	  if ( IS_BIGENDIAN() )
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  *igrib = (unsigned long) dval[j];
+		  igrib++;
+		  z += 4;
+		}
+	    }
+	  else
+	    {
+	      for (j = 0; j < __UNROLL_DEPTH_2; j++) 
+		{
+		  ival = (unsigned long) dval[j];
+		  lGrib[z  ] =  ival >> 24;
+		  lGrib[z+1] =  ival >> 16;
+		  lGrib[z+2] =  ival >>  8;
+		  lGrib[z+3] =  ival;
+		  z += 4;
+		}
+	    }
+	}
+      for (j = 0; j < residual; j++) 
+	{
+	  dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+	}
+      if ( IS_BIGENDIAN() )
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      *igrib = (unsigned long) dval[j];
+	      igrib++;
+	      z += 4;
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < residual; j++) 
+	    {
+	      ival = (unsigned long) dval[j];
+	      lGrib[z  ] =  ival >> 24;
+	      lGrib[z+1] =  ival >> 16;
+	      lGrib[z+2] =  ival >>  8;
+	      lGrib[z+3] =  ival;
+	      z += 4;
+	    }
+	}
+#ifdef _GET_IBM_COUNTER 
+      hpmStop(5);
+#endif
     }
-  else if ( sec_num == 3 )
+  else if ( numBits > 0 && numBits <= 32 )
     {
-      *gdsp = section;
+      TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
     }
-  else
+  else if ( numBits == 0 )
     {
-      fprintf(stderr, "Unexpected section3 number %d\n", sec_num);
-      return (-1);
     }
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 4 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "pds %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 4 )
+  else
     {
-      fprintf(stderr, "Unexpected section4 number %d\n", sec_num);
-      return (-1);
+      Error("Unimplemented packing factor %d!", numBits);
     }
 
-  *pdsp = section;
-
-  grib_len += sec_len;
-  section  += sec_len;
-
-  /* section 5 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "drs %d %ld\n", sec_num, sec_len);
-
-  if ( sec_num != 5 )
-    {
-      fprintf(stderr, "Unexpected section5 number %d\n", sec_num);
-      return (-1);
-    }
+  *gz = z;
+#undef __UNROLL_DEPTH_2
+}
 
-  *drsp = section;
+#endif /* T */
 
-  grib_len += sec_len;
-  section  += sec_len;
 
-  /* section 6 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "bms %d %ld\n", sec_num, sec_len);
+#ifdef T
+#undef T
+#endif
+#define T double
+#ifdef T
 
-  if ( sec_num != 6 )
-    {
-      fprintf(stderr, "Unexpected section6 number %d\n", sec_num);
-      return (-1);
-    }
+/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
+static
+void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
+{
+  long z = *gribLen;
+  int exponent, mantissa;
+  long i;
+  int ival;
+  int pvoffset = 0xFF;
+  int gdslen = 32;
+  unsigned lonIncr, latIncr;
 
-  *bmsp = section;
+  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
 
-  grib_len += sec_len;
-  section  += sec_len;
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
 
-  /* section 7 */
-  sec_len = GRIB2_SECLEN(section);
-  sec_num = GRIB2_SECNUM(section);
-  //fprintf(stderr, "bds %d %ld\n", sec_num, sec_len);
+  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
 
-  if ( sec_num != 7 )
-    {
-      fprintf(stderr, "Unexpected section7 number %d\n", sec_num);
-      return (-1);
-    }
+  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
 
-  *bdsp = section;
+  gdslen += ISEC2_NumVCP * 4;
 
-  grib_len += sec_len;
-  section  += sec_len;
+  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
+  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
+  Put1Byte(pvoffset);           /*  4    PV */
+  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
 
-  /* skip multi GRIB sections */
-  msec = 1;
-  while ( !GRIB_FIN(section) )
+  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
     {
-      sec_len = GRIB2_SECLEN(section);
-      sec_num = GRIB2_SECNUM(section);
-
-      if ( sec_num < 1 || sec_num > 7 ) break;
-
-      if ( sec_num == 7 )
-	fprintf(stderr, "Skipped unsupported multi GRIB section %d!\n", ++msec);
-
-      if ( (grib_len + sec_len) > gribsize ) break;
-
-      grib_len += sec_len;
-      section  += sec_len;
+      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
+      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
+      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
+      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
+      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
+      PutnZero(18);             /* 14-31 reserved                 */
     }
-
-  /* end section - "7777" in ASCII */
-  if ( !GRIB_FIN(section) )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-2);
+      Put2Byte(ISEC2_GME_NI2);
+      Put2Byte(ISEC2_GME_NI3);
+      Put3Byte(ISEC2_GME_ND);
+      Put3Byte(ISEC2_GME_NI);
+      Put1Byte(ISEC2_GME_AFlag);
+      Put3Int(ISEC2_GME_LatPP);
+      Put3Int(ISEC2_GME_LonPP);
+      Put3Int(ISEC2_GME_LonMPL);
+      Put1Byte(ISEC2_GME_BFlag);
+      PutnZero(5);
     }
-
-  return (0);
-}
-
-
-int gribGinfo(off_t recpos, long recsize, unsigned char *gribbuffer,
-	      int *intnum, float *fltnum, off_t *bignum)
-{
-  unsigned char *pds, *gds, *bms, *bds;
-  unsigned char *bufpointer, *is, *section;
-  int gribversion, grib1offset;
-  long gribsize = 0;
-  off_t dpos, bpos = 0;
-  int bdslen;
-  float bsf;
-
-  section = gribbuffer;
-  is = gribbuffer;
-  if ( ! GRIB_START(section) )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
     {
-      fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
-	      section[0], section[1], section[2], section[3]);
-      return (-1);
-    }
-
-  gribversion = GRIB_EDITION(section);
-  if ( GRIB1_SECLEN(section) == 24 && gribversion == 0 ) gribversion = 0;
-
-  if ( gribversion == 1 )
-    grib1offset = 4;
-  else
-    grib1offset = 0;
-
-  pds = is + 4 + grib1offset;
-  bufpointer = pds + PDS_Len;
-  gribsize += 4 + grib1offset + PDS_Len;
+      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
 
-  if ( PDS_HAS_GDS )
-    {
-      gds = bufpointer;
-      bufpointer += GDS_Len;
-      gribsize += GDS_Len;
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
+      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
+      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
+      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
+      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
+      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
+      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
+      PutnZero(2);                     /* 34-41 */
     }
-  else
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
     {
-      gds = NULL;
-    }
+      int numlon;
+      if ( ISEC2_Reduced )
+	numlon = 0xFFFF;
+      else
+	numlon = ISEC2_NumLon;
 
-  if ( PDS_HAS_BMS )
-    {
-      bms = bufpointer;
-      bufpointer += BMS_Len;
+      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
 
-      bpos = recpos + gribsize + 6;
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_LastLat);
+      Put3Int(ISEC2_LastLon);
+      if ( ISEC2_ResFlag == 0 )
+	{
+	  lonIncr = 0xFFFF;
+	  latIncr = 0xFFFF;
+	}
+      else
+	{
+	  lonIncr = ISEC2_LonIncr;
+	  latIncr = ISEC2_LatIncr;
+	}
+      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
+      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
+	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
+      else
+	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
 
-      gribsize += BMS_Len;
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      PutnZero(4);                     /* 28-31 reserved                 */
+
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+	{
+	  Put3Int(ISEC2_LatSP);
+	  Put3Int(ISEC2_LonSP);
+	  Put1Real((double)(FSEC2_RotAngle));
+	}
     }
   else
     {
-      bms = NULL;
-    }
-
-  bds = bufpointer;
-
-  dpos = recpos + gribsize + 11;
-
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
-  bufpointer += bdslen;
-  gribsize += bdslen;
-  gribsize += 4;
-
-  if ( gribsize > recsize )
-    {
-      fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", recsize, gribsize);
-      return (1);
+      Error("Unsupported grid type %d", ISEC2_GridType);
     }
 
-  /* end section - "7777" in ascii */
-  if ( !GRIB_FIN(bufpointer) )
+#if defined (SX)
+#pragma vdir novector     /* vectorization gives wrong results on NEC */
+#endif
+  for ( i = 0; i < ISEC2_NumVCP; ++i )
     {
-      fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
-	      bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
+      Put1Real((double)(fsec2[10+i]));
     }
 
-  bsf = BDS_BinScale;
-  if ( bsf > 32767 ) bsf = 32768-bsf;
-  bsf = pow(2.0,(double)bsf);
-
-  bignum[0] = dpos;
-  if ( bms ) bignum[1] = bpos;
-  else       bignum[1] = -999;
-  intnum[0] = BDS_NumBits;
+  if ( ISEC2_Reduced )
+    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
 
-  /*  fltnum[0] = 1.0; */
-  fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
-  fltnum[1] = bsf;
-  fltnum[2] = BDS_RefValue;
-  /*
-  printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
-  printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
-  */
-  return (0);
+  *gribLen = z;
 }
 
-
-void grib1PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
+/* GRIB BLOCK 3 - BIT MAP SECTION */
+static
+void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
 {
-  static int header = 1;
-  int GridType, level, nerr;
-  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-  int bdslen;
+  GRIBPACK *bitmap;
+  long bitmapSize;
+  long imaskSize;
+  long i;
+  long bmsLen, bmsUnusedBits;
+  long fsec4size;
+  long z = *gribLen;
+#if defined (VECTORCODE)
+  unsigned int *imask;
+#endif
+  static int lmissvalinfo = 1;
+  /*  unsigned int c, imask; */
 
-  if ( header )
+  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
     {
-      fprintf(stdout, 
-      "  Rec : Off Position   Size : V PDS  GDS    BMS    BDS : Code Level :  LType GType: CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      lmissvalinfo = 0;
+      Message("Missing value = NaN is unsupported!");
     }
 
-  is = gribbuffer;
+  bitmapSize = ISEC4_NumValues;
+  imaskSize = ((bitmapSize+7)>>3)<<3;
+  bitmap = &lGrib[z+6];
+  fsec4size = 0;
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+#if defined (VECTORCODE)
+  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
+  memset(imask, 0, imaskSize*sizeof(int));
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
-      return;
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  imask[i] = 1;
+	}
     }
 
-  if ( gds == NULL )
-    GridType = -1;
-  else
-    GridType = GDS_GridType;
-
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else if ( PDS_LevelType == 109 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < imaskSize/8; i++ )
+    {
+      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
+	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
+	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
+	          (imask[i*8+6] << 1) | (imask[i*8+7]);
+    }
 
-  bdslen = BDS_Len;
-  bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
+  free(imask);
+#else
+  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
 
-  if ( ((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130) )
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      int s1, s2;
-      s1 = gribrec_len(bds[14], bds[15], bds[16]);
-      s2 = gribrec_len(gribbuffer[4], gribbuffer[5], gribbuffer[6]);
-      cr = ((double)s1)/s2;
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  bitmap[i/8] |= 1<<(7-(i&7));
+	}
     }
+#endif
 
-  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d%4d%5d%7d%7d : %3d%7d : %5d %5d %6.4g\n",
-	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
-	  PDS_Len, GDS_Len, BMS_Len, bdslen,
-	  PDS_Parameter, level, PDS_LevelType, GridType, cr);
+  bmsLen = imaskSize/8 + 6;
+  bmsUnusedBits = imaskSize - bitmapSize;
+
+  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
+  Put1Byte(bmsUnusedBits);
+  Put2Byte(0);
+
+  *gribLen += bmsLen;
+
+  *datasize = fsec4size;
 }
 
 
-void grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
+/* GRIB BLOCK 4 - BINARY DATA SECTION */
+static
+int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
+			  long *datstart, long *datsize, int code)
 {
-  static int header = 1;
-  int nerr;
-  unsigned char *is  = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  unsigned char *ids = NULL, *lus = NULL, *drs = NULL;
-  long ids_len = 0, lus_len = 0, gds_len = 0, pds_len = 0, drs_len = 0, bms_len = 0, bds_len = 0;
-  int gridtype, paramnum, level1type /*, level2type*/;
-  int level1 /*, level1sf*/;
-  /* int level2, level2sf; */
-  double cr = 1;
+  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
+  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
 
-  if ( header )
+  size_t z = *gribLen;
+  long i, jloop;
+  int numBits;
+  int ival;
+  int blockLength, PackStart = 0, Flag = 0;
+  int binscale = 0;
+  int nbpv;
+  int bds_head = 11;
+  int bds_ext = 0;
+  /* ibits = BitsPerInt; */
+  unsigned int max_nbpv_pow2;
+  int exponent, mantissa;
+  int unused_bits = 0;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int isubset = 0, itemp = 0, itrunc = 0;
+  T factor = 1, fmin, fmax;
+  double zref;
+  double range, rangec;
+  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
+                                /*        of floating point numbers - needed   */
+		                /*        on some platforms (eg vpp700, linux) */
+  extern const double _pow2tab[158];
+  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
+
+  if ( isec2 )
     {
-      fprintf(stdout, 
-      "  Rec : Off Position   Size : V IDS LUS GDS PDS  DRS    BMS    BDS : Code Level :  LType GType: CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
-    }
+      /* If section 2 is present, it says if data is spherical harmonic */
 
-  is = gribbuffer;
+      if ( isec2[0] == 50 || isec2[0] == 60 || 
+	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
 
-  nerr = grib2Sections(gribbuffer, recsize, &ids, &lus, &gds, &pds, &drs, &bms, &bds);
-  if ( nerr )
+      if ( lspherc )
+	isec4[2] = 128;
+      else
+	isec4[2] = 0;
+    }
+  else
     {
-      fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
-      return;
+      /* Section 4 says if it's spherical harmonic data.. */
+
+      lspherc = ( isec4[2] == 128 );
     }
 
-  if ( ids ) ids_len = GRIB2_SECLEN(ids);
-  if ( lus ) lus_len = GRIB2_SECLEN(lus);
-  if ( gds ) gds_len = GRIB2_SECLEN(gds);
-  if ( pds ) pds_len = GRIB2_SECLEN(pds);
-  if ( drs ) drs_len = GRIB2_SECLEN(drs);
-  if ( bms ) bms_len = GRIB2_SECLEN(bms);
-  if ( bds ) bds_len = GRIB2_SECLEN(bds);
+  /* Complex packing supported for spherical harmonics. */
 
-  /*
-  if ( (BDS_Flag >> 4)&1 && BDS_Z == 128 )
-    {
-      int s1, s2;
-      s1 = ((int) ((bds[14]<<16)+(bds[15]<<8)+bds[16]));
-      s2 = ((int) ((gribbuffer[4]<<16)+(gribbuffer[5]<<8)+gribbuffer[6]));
-      cr = ((double)s1)/s2;
-    }
-  */
-  gridtype   = GET_UINT2(gds[12],gds[13]);
-  paramnum   = GET_UINT1(pds[10]);
-  level1type = GET_UINT1(pds[22]);
-  /* level1sf   = GET_UINT1(pds[23]); */
-  level1     = GET_UINT4(pds[24],pds[25],pds[26],pds[27]);
-  /* level2type = GET_UINT1(pds[28]); */
-  /* level2sf   = GET_UINT1(pds[29]); */
-  /* level2     = GET_UINT4(pds[30],pds[31],pds[32],pds[33]); */
-  /*
-  printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
-  */
-  fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %3d%7d : %5d %5d %6.4g\n",
-	  nrec, offset, recpos, recsize, GRIB_EDITION(is),
-	  ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len,
-	  paramnum, level1, level1type, gridtype, cr);
-}
+  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+             ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
+  /* Check input specification is consistent */
 
-void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  if ( lcomplex && isec2 )
+    {
+      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+	}
+      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+        }
+      else if ( lcomplex )
+	{
+	  /*
+	    Truncation of full spectrum, which is supposed triangular,
+	    has to be diagnosed. Define also sub-set truncation.
+	  */
+	  isubset = isec4[17];
+	  /* When encoding, use the total number of data. */
+	  itemp   = isec4[0];
+	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
+	}
+    }
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double) decscale);
+      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
+    }
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
-  else if ( gribversion == 2 )
-    grib2PrintALL(nrec, offset, recpos, recsize, gribbuffer);
-  else
+  if ( lspherc )
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, offset, recpos, recsize, gribversion); 
+      if ( lcomplex )
+	{
+	  int jup, ioff;
+	  jup  = isubset;
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	  PackStart = ioff;
+	  Flag = 192;
+	}
+      else
+	{
+	  bds_ext = 4;
+	  PackStart = 1;
+	  Flag = 128;
+	}
     }
-}
 
+  *datstart = bds_head + bds_ext;
 
-void grib1PrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int century, subcenter, decimalscale, nerr;
-  int fc_num = 0;
-  int year = 0, date;
+  nbpv = numBits = ISEC4_NumBits;
 
-  if ( header )
+  if ( lspherc && lcomplex )
     {
-      fprintf(stdout, 
-      "  Rec : PDS Tab Cen Sub Ver Grid Code LTyp Level1 Level2    Date  Time P1 P2 TU TR NAVE Scale FCnum CT\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      int pcStart, pcScale;
+      pcStart = isubset;
+      pcScale = isec4[16];
+      TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
+      TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
     }
 
-  is = gribbuffer;
+  fmin = fmax = data[PackStart];
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+  TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-  switch(GRIB_EDITION(is))
-    {   
-    case 0:
-      year                = GET_UINT1(pds[12]);
-      century             = 1;
-      subcenter           = 0;
-      decimalscale        = 0;
-      break;
-    case 1:
-      year                = PDS_Year;
-      century             = PDS_Century;
-      subcenter           = PDS_Subcenter;
-      decimalscale        = PDS_DecimalScale;
-      break;
-    default:
-      fprintf(stderr, "Grib version %d not supported!", GRIB_EDITION(is));
-      exit(EXIT_FAILURE);
-    }
+  zref = (double)fmin;
 
-  if ( PDS_Len > 28 )
-    if ( PDS_CenterID    == 98 || PDS_Subcenter == 98 ||
-	(PDS_CenterID    ==  7 && PDS_Subcenter == 98) )
-      if ( pds[40] == 1 )
-	fc_num = GET_UINT1(pds[49]);
 
-  if ( year < 0 )
-    {
-      date = (-year)*10000+PDS_Month*100+PDS_Day;
-      century = -century;
-    }
-  else
+  if ( CGRIBEX_Const && !lspherc )
     {
-      date =    year*10000+PDS_Month*100+PDS_Day;
+      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
     }
-      
-  fprintf(stdout, "%5d :%4d%4d%4d%4d%4d %4d %4d%4d%7d%7d %8d%6d%3d%3d%3d%3d%5d%6d%5d%4d\n", nrec,
-	  PDS_Len,  PDS_CodeTable,   PDS_CenterID, subcenter, PDS_ModelID,
-	  PDS_GridDefinition, PDS_Parameter, PDS_LevelType, PDS_Level1, PDS_Level2,
-	  date, PDS_Time, PDS_TimePeriod1, PDS_TimePeriod2, PDS_TimeUnit, PDS_TimeRange,
-	  PDS_AvgNum, decimalscale, fc_num, century);
-}
 
 
-void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+  if ( (blockLength%2) == 1 ) blockLength++;
+
+  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+
+  Flag += unused_bits;
 
-  gribversion = gribVersion(gribbuffer, recsize);
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
   /*
-  else if ( gribversion == 2 )
-    grib2PrintPDS(nrec, recpos, recsize, gribbuffer);
+    Adjust number of bits per value if full integer length to
+    avoid hitting most significant bit (sign bit).
+  */
+  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
+  /*
+    Calculate the binary scaling factor to spread the range of
+    values over the number of bits per value.
+    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
+    as a guideline).           
+  */
+  range = fabs(fmax - fmin);
+
+  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  /*
+    Have to allow tolerance in comparisons on some platforms
+    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
+    to avoid clipping ranges which are a power of 2.
   */
+  if ( range <= jpepsln )
+    {
+      binscale = 0;
+    }
+  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
+    {
+      binscale = 0;
+    }
+  else if ( fabs(range-1.0) <= jpepsln )
+    {
+      binscale = 1 - nbpv;
+    }
+  else if ( range > 1.0 )
+    {
+      rangec = range + jpepsln;
+      for ( jloop = 1; jloop < 128; jloop++ )
+	{
+	  if ( _pow2tab[jloop] > rangec ) break;
+	}
+      if ( jloop == 128 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = jloop - nbpv;
+	}
+    }
   else
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
+      rangec = range - jpepsln;
+      for ( jloop = 1; jloop < 127; jloop++ )
+	{
+	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
+	}
+      if ( jloop == 127 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = 1 - jloop - nbpv;
+	}
     }
-}
 
+  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
+  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
 
-void grib1PrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-
-  if ( header )
+  if ( binscale != 0 )
     {
-      fprintf(stdout, 
-      "  Rec : GDS  NV PVPL Typ : xsize ysize   Lat1   Lon1   Lat2   Lon2    dx    dy\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      if ( binscale < 0 )
+	{
+	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
+	}
+      else
+	{
+	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+	}
+
+      if ( binscale < 0 ) factor =     intpow2(-binscale);
+      else                factor = 1.0/intpow2( binscale);
     }
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  ref2ibm(&zref, BitsPerInt);
+
+  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
+  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
+  if ( binscale < 0 ) binscale = 32768 - binscale;
+  Put2Byte(binscale);         /*  4-5 Scale factor             */
+  Put1Real(zref);             /*  6-9 Reference value          */
+  Put1Byte(nbpv);             /*   10 Packing size             */
+
+  if ( lspherc )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
+      if ( lcomplex )
+	{
+	  int jup = isubset;
+	  int ioff = z + bds_ext;
+	  if ( ioff > 0xFFFF ) ioff = 0;
+	  Put2Byte(ioff);
+	  Put2Int(isec4[16]);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
+	}
+      else
+	{
+	  Put1Real((double)(data[0]));
+	}
     }
 
-  if ( gds )
-    fprintf(stdout, "%5d :%4d%4d%4d %4d :%6d%6d%7d%7d%7d%7d%6d%6d\n", nrec,
-	    GDS_Len,  GDS_NV,   GDS_PVPL, GDS_GridType,
-	    GDS_NumLon,   GDS_NumLat,
-	    GDS_FirstLat, GDS_FirstLon,
-	    GDS_LastLat,  GDS_LastLon,
-	    GDS_LonIncr,  GDS_LatIncr);
-  else
-    fprintf(stdout, "%5d : Grid Description Section not defined\n", nrec);
-}
-
+  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
 
-void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+#if  defined  (_ARCH_PWR6)
+  TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#else
+  TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#endif
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
-  /*
-  else if ( gribversion == 2 )
-    grib2PrintGDS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
-    {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
-    }
+  *gribLen = z;
+
+  return (0);
 }
 
 
-void grib1PrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
+			     int kleng, int *kword, int efunc, int *kret)
 {
-  static int header = 1;
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+  long gribLen = 0; /* Counter of GRIB length for output */
+  long isLen, pdsLen;
+  GRIBPACK *lpds;
+  unsigned char *CGrib;
+  long fsec4size = 0;
+  int numBytes;
+  int bmsIncluded;
+  size_t len;
+  GRIBPACK *lGrib;
+  long datstart, datsize, bdsstart;
+  int status = 0;
 
-  if ( header )
-    {
-      fprintf(stdout, 
-      "  Rec : Code Level     BMS    Size\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
-    }
+  UNUSED(isec3);
+  UNUSED(efunc);
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+  grsdef();
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+  CGrib = (unsigned char *) kgrib;
 
-  if ( bms )
-    fprintf(stdout, "%5d :%4d%7d %7d %7d\n", nrec,
-	    PDS_Parameter, level,
-	    BMS_Len, BMS_BitmapSize);
-  else
-    fprintf(stdout, "%5d :%4d%7d Bit Map Section not defined\n", nrec,
-	    PDS_Parameter, level);
-}
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
 
+  /* set max header len */
+  len = 16384;
 
-void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int gribversion;
+  /* add data len */
+  numBytes = (ISEC4_NumBits+7)>>3;
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  len += numBytes*klenp;
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
+  /* add bitmap len */
+  if ( bmsIncluded ) len += (klenp+7)>>3;
+
+#if defined (VECTORCODE)
+  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
+  if ( lGrib == NULL ) SysError("No Memory!");
+#else
+  lGrib = CGrib;
+#endif
+
+  isLen = 8;
+  encodeIS(lGrib, &gribLen);
+  lpds = &lGrib[isLen];
+  pdsLen = getPdsLen(isec1);
+
+  encodePDS(lpds, pdsLen,  isec1);
+  gribLen += pdsLen;
   /*
-  else if ( gribversion == 2 )
-    grib2PrintBMS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
+  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
     {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
-    }
-}
+      static int lwarn_cplx = TRUE;
 
+      if ( lwarn_cplx )
+	Message("Complex packing of spectral data unsupported, using simple packing!");
 
-void grib1PrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  static int header = 1;
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-  double refval, scale;
+      isec2[5] = 1;
+      isec4[3] = 0;
 
-  if ( header )
+      lwarn_cplx = FALSE;
+    }
+  */
+  TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  if ( bmsIncluded )
     {
-      fprintf(stdout, 
-      "  Rec : Code Level     BDS Flag     Scale   RefValue Bits  CR\n");
-/*     ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
-      header = 0;
+      TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+    }
+  else
+    {
+      fsec4size = ISEC4_NumValues;
     }
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  bdsstart = gribLen;
+  status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
+				 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
+  if ( status )
     {
-      fprintf(stdout, "%5d : error\n", nrec);
+      *kret = status;
       return;
     }
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+  encodeES(lGrib, &gribLen, bdsstart);
 
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
-    {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
-    }
+  if ( (size_t) gribLen > kleng*sizeof(int) )
+    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
 
-  refval = BDS_RefValue;
+#if defined (VECTORCODE)
+  if ( (size_t) gribLen > len )
+    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
 
-  if ( BDS_BinScale < 0 )
-    scale = 1.0/pow(2.0, (double) -BDS_BinScale);
-  else
-    scale = pow(2.0, (double) BDS_BinScale);
+  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
 
-  if ( PDS_DecimalScale )
-    {
-      double decscale;
-      decscale = pow(10.0, (double)-PDS_DecimalScale);
-      refval *= decscale;
-      scale  *= decscale;
-    }
+  free(lGrib);
+#endif
+
+  ISEC0_GRIB_Len     = gribLen;
+  ISEC0_GRIB_Version = 1;
+
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
 
-  fprintf(stdout, "%5d :%4d%7d %7d %4d %8.5g %11.5g%4d %6.4g\n", nrec,
-	  PDS_Parameter, level,
-	  BDS_Len, BDS_Flag, scale, refval, BDS_NumBits, cr);
+  *kret = status;
 }
 
+#endif /* T */
 
-void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+/* GRIB BLOCK 2 - GRID DESCRIPTION SECTION */
+static
+void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
 {
-  int gribversion;
+  long z = *gribLen;
+  int exponent, mantissa;
+  long i;
+  int ival;
+  int pvoffset = 0xFF;
+  int gdslen = 32;
+  unsigned lonIncr, latIncr;
 
-  gribversion = gribVersion(gribbuffer, recsize);
+  if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
 
-  if ( gribversion == 0 || gribversion == 1 )
-    grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
-  /*
-  else if ( gribversion == 2 )
-    grib2PrintBDS(nrec, recpos, recsize, gribbuffer);
-  */
-  else
-    {
-      fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
-	      nrec, 0L, recpos, recsize, gribversion); 
-    }
-}
+  if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )  gdslen += 10;
 
+  if ( ISEC2_NumVCP || ISEC2_Reduced ) pvoffset = gdslen + 1;
 
-void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
-{
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
+  if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
-    }
+  gdslen += ISEC2_NumVCP * 4;
 
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
-  else
-    level = PDS_Level1;
+  Put3Byte(gdslen);             /*  0- 2 Length of Block 2 Byte 0 */
+  Put1Byte(ISEC2_NumVCP);       /*  3    NV */
+  Put1Byte(pvoffset);           /*  4    PV */
+  Put1Byte(ISEC2_GridType);     /*  5    LatLon=0 Gauss=4 Spectral=50 */
 
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
+  if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
     {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
+      Put2Byte(ISEC2_PentaJ);   /*  6- 7 Pentagonal resolution J  */
+      Put2Byte(ISEC2_PentaK);   /*  8- 9 Pentagonal resolution K  */
+      Put2Byte(ISEC2_PentaM);   /* 10-11 Pentagonal resolution M  */
+      Put1Byte(ISEC2_RepType);  /* 12    Representation type      */
+      Put1Byte(ISEC2_RepMode);  /* 13    Representation mode      */
+      PutnZero(18);             /* 14-31 reserved                 */
     }
-
-  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
     {
-      fprintf(stdout, "GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
+      Put2Byte(ISEC2_GME_NI2);
+      Put2Byte(ISEC2_GME_NI3);
+      Put3Byte(ISEC2_GME_ND);
+      Put3Byte(ISEC2_GME_NI);
+      Put1Byte(ISEC2_GME_AFlag);
+      Put3Int(ISEC2_GME_LatPP);
+      Put3Int(ISEC2_GME_LonPP);
+      Put3Int(ISEC2_GME_LonMPL);
+      Put1Byte(ISEC2_GME_BFlag);
+      PutnZero(5);
     }
-}
-
-
-static
-void repair1(unsigned char *gbuf, long gbufsize)
-{
-  long i;
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  /* int recLen; */
-  unsigned char *source;
-  size_t sourceLen;
-  int bds_len, bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress */;
-  int bds_head = 11;
-  int bds_ext = 0, bds_ubits;
-  int datstart = 0;
-  /* int llarge = FALSE; */
-
-  nerr = grib1Sections(gbuf, gbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
     {
-      fprintf(stdout, "grib1Sections error\n");
+      Put2Byte(ISEC2_NumLon);          /*  6- 7 Longitudes               */
+
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Latitudes                */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_Lambert_Lov);      /* 17-19 */
+      Put3Int(ISEC2_Lambert_dx);       /* 20-22 */
+      Put3Int(ISEC2_Lambert_dy);       /* 23-25 */
+      Put1Byte(ISEC2_Lambert_ProjFlag);/* 26    Projection flag          */
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      Put3Int(ISEC2_Lambert_LatS1);    /* 28-30 */  
+      Put3Int(ISEC2_Lambert_LatS2);    /* 31-33 */
+      Put3Int(ISEC2_Lambert_LatSP);    /* 34-36 */  
+      Put3Int(ISEC2_Lambert_LonSP);    /* 37-39 */
+      PutnZero(2);                     /* 34-41 */
     }
+  else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON    ||
+	    ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN  ||
+	    ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+    {
+      int numlon;
+      if ( ISEC2_Reduced )
+	numlon = 0xFFFF;
+      else
+	numlon = ISEC2_NumLon;
 
-  /* recLen = gribrec_len(gbuf[4], gbuf[5], gbuf[6]); */
-  /* if ( recLen > JP23SET ) llarge = TRUE; */
-
-  bds_len   = BDS_Len;
-  bds_nbits = BDS_NumBits;
-  bds_flag  = BDS_Flag;
-  bds_ubits = bds_flag & 15;
-  lspherc   =  bds_flag >> 7;
-  lcomplex  = (bds_flag >> 6)&1;
-  /* lcompress = (bds_flag >> 4)&1; */
+      Put2Byte(numlon);                /*  6- 7 Number of Longitudes     */
 
-  if ( lspherc )
-    {
-      if ( lcomplex  )
+      Put2Byte(ISEC2_NumLat);          /*  8- 9 Number of Latitudes      */
+      Put3Int(ISEC2_FirstLat);
+      Put3Int(ISEC2_FirstLon);
+      Put1Byte(ISEC2_ResFlag);         /* 16    Resolution flag          */
+      Put3Int(ISEC2_LastLat);
+      Put3Int(ISEC2_LastLon);
+      if ( ISEC2_ResFlag == 0 )
 	{
-	  int jup, ioff;
-	  jup  = bds[15];
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
+	  lonIncr = 0xFFFF;
+	  latIncr = 0xFFFF;
 	}
       else
 	{
-	  bds_ext = 4;
+	  lonIncr = ISEC2_LonIncr;
+	  latIncr = ISEC2_LatIncr;
 	}
-    }
-
-  datstart = bds_head + bds_ext;
-
-  source = bds + datstart;
+      Put2Byte(lonIncr);               /* 23-24 i - direction increment  */
+      if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
+	Put2Byte(ISEC2_NumPar);        /* 25-26 Latitudes Pole->Equator  */
+      else
+	Put2Byte(latIncr);             /* 25-26 j - direction increment  */
 
-  sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+      Put1Byte(ISEC2_ScanFlag);        /* 27    Scanning mode            */
+      PutnZero(4);                     /* 28-31 reserved                 */
 
-  if ( bds_nbits == 24 )
-    {
-      long nelem;
-      unsigned char *pbuf;
-      nelem = sourceLen/3;
-      pbuf = (unsigned char*) malloc(sourceLen);
-      for ( i = 0; i < nelem; i++ )
+      if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
 	{
-	  pbuf[3*i  ] = source[        i];
-	  pbuf[3*i+1] = source[  nelem+i];
-	  pbuf[3*i+2] = source[2*nelem+i];
+	  Put3Int(ISEC2_LatSP);
+	  Put3Int(ISEC2_LonSP);
+	  Put1Real((double)(FSEC2_RotAngle));
 	}
-      memcpy(source, pbuf, sourceLen);
-      free(pbuf);
-    }
-}
-
-
-void gribRepair1(int nrec, long recsize, unsigned char *gribbuffer)
-{
-  int level, nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  double cr = 1;
-
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "%5d : error\n", nrec);
-      return;
     }
-
-  if ( PDS_LevelType == 100 )
-    level = PDS_Level * 100;
-  else if ( PDS_LevelType == 99 )
-    level = PDS_Level;
   else
-    level = PDS_Level1;
-
-  if ( ((BDS_Flag >> 4)&1) && BDS_Z == 128 )
     {
-      int s1, s2;
-      s1 = ((int) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
-      s2 = ((int) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
-      cr = ((double)s1)/s2;
+      Error("Unsupported grid type %d", ISEC2_GridType);
     }
 
-  if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
+#if defined (SX)
+#pragma vdir novector     /* vectorization gives wrong results on NEC */
+#endif
+  for ( i = 0; i < ISEC2_NumVCP; ++i )
     {
-      fprintf(stdout, "Repair GRIB record %5d : code = %4d   level = %7d\n", nrec, PDS_Parameter, level);
-      repair1(gribbuffer, recsize);
+      Put1Real((double)(fsec2[10+i]));
     }
-}
-#include <stdio.h>
-#include <string.h>
 
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
+  if ( ISEC2_Reduced )
+    for ( i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_RowLon(i));
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
-#if defined(__cplusplus)
-extern "C" {
-#endif
-#if defined (HAVE_LIBAEC)
-#  include <libaec.h>
-#else
-#  include <szlib.h>
-#endif
-#if defined (__cplusplus)
+  *gribLen = z;
 }
-#endif
-
-#if defined (HAVE_LIBAEC)
-#  define AEC_FLAGS           (AEC_DATA_MSB | AEC_DATA_PREPROCESS)
-#else
-#  define OPTIONS_MASK        (SZ_RAW_OPTION_MASK | SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK)
-#endif
-
-#  define PIXELS_PER_BLOCK    (8)
-#  define PIXELS_PER_SCANLINE (PIXELS_PER_BLOCK*128)
-
-#  define MIN_COMPRESS        (0.95)
-#  define MIN_SIZE            (256)
-#endif
 
-#define  Z_SZIP  128
-#define  Z_AEC   130
-
-
-#define SetLen3(var, offset, value) ((var[offset+0] = 0xFF & (value >> 16)), \
-				     (var[offset+1] = 0xFF & (value >>  8)), \
-				     (var[offset+2] = 0xFF & (value      )))
-#define SetLen4(var, offset, value) ((var[offset+0] = 0xFF & (value >> 24)), \
-				     (var[offset+1] = 0xFF & (value >> 16)), \
-				     (var[offset+2] = 0xFF & (value >>  8)), \
-				     (var[offset+3] = 0xFF & (value      )))
-
-
-int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
+/* GRIB BLOCK 3 - BIT MAP SECTION */
+static
+void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
 {
-  /* urecsize : uncompressed record size  */
-  int compress = 0;
-  int nerr;
-  /* int  bds_len, bds_nbits, lspherc, lcomplex; */
-  int bds_flag, lcompress;
-  long gribsize = 0;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int gribversion;
-
-  gribversion = gribVersion(gribbuffer, recsize);
-
-  if ( gribversion == 2 ) return (compress);
+  GRIBPACK *bitmap;
+  long bitmapSize;
+  long imaskSize;
+  long i;
+  long bmsLen, bmsUnusedBits;
+  long fsec4size;
+  long z = *gribLen;
+#if defined (VECTORCODE)
+  unsigned int *imask;
+#endif
+  static int lmissvalinfo = 1;
+  /*  unsigned int c, imask; */
 
-  nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
     {
-      fprintf(stdout, "grib1Sections error\n");
-      return (compress);
+      lmissvalinfo = 0;
+      Message("Missing value = NaN is unsupported!");
     }
 
-  /* bds_len   = BDS_Len; */
-  /* bds_nbits = BDS_NumBits; */
-  bds_flag  = BDS_Flag;
-  /* lspherc   =  bds_flag >> 7; */
-  /* lcomplex  = (bds_flag >> 6)&1; */
-  lcompress = (bds_flag >> 4)&1;
+  bitmapSize = ISEC4_NumValues;
+  imaskSize = ((bitmapSize+7)>>3)<<3;
+  bitmap = &lGrib[z+6];
+  fsec4size = 0;
 
-  *urecsize = 0;
-  if ( lcompress )
+#if defined (VECTORCODE)
+  imask = (unsigned int*) malloc(imaskSize*sizeof(unsigned int));
+  memset(imask, 0, imaskSize*sizeof(int));
+
+#if defined (CRAY)
+#pragma _CRI ivdep
+#endif
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      compress = BDS_Z;
-      if ( compress == Z_SZIP || compress == Z_AEC )
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
 	{
-	  gribsize = gribrec_len(bds[14], bds[15], bds[16]);
+	  data[fsec4size++] = data[i];
+	  imask[i] = 1;
 	}
     }
 
-  *urecsize = gribsize;
-
-  return (compress);
-}
-
-
-int  gribZip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
-{
-  int nerr;
-  int gribLen;
-  int rec_len;
-  int llarge = FALSE;
-#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
-  static int libszwarn = 1;
+#if defined (CRAY)
+#pragma _CRI ivdep
 #endif
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-
-  gribLen = gribrec_len(dbuf[4], dbuf[5], dbuf[6]);
-  if ( gribLen > JP23SET ) llarge = TRUE;
+#if defined (SX)
+#pragma vdir nodep
+#endif
+#ifdef __uxpch__
+#pragma loop novrec
+#endif
+  for ( i = 0; i < imaskSize/8; i++ )
+    {
+      bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
+	          (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
+	          (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
+	          (imask[i*8+6] << 1) | (imask[i*8+7]);
+    }
 
-  rec_len = gribLen;
+  free(imask);
+#else
+  for ( i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
 
-  nerr = grib1Sections(dbuf, dbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  for ( i = 0; i < bitmapSize; i++ )
     {
-      fprintf(stdout, "grib1Sections error!\n");
-      return (rec_len);
+      if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
+	{
+	  data[fsec4size++] = data[i];
+	  bitmap[i/8] |= 1<<(7-(i&7));
+	}
     }
+#endif
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
+  bmsLen = imaskSize/8 + 6;
+  bmsUnusedBits = imaskSize - bitmapSize;
 
-  {
-    long i;
-    int bdsLen;
-    int gribLenOld = 0;
-    int status;
-    size_t datstart, datsize;
-#if defined (HAVE_LIBAEC)
-    struct aec_stream strm;
-#else
-    SZ_com_t sz_param;          /* szip parameter block */
-#endif
-    unsigned char *dest, *source;
-    size_t destLen, sourceLen;
-    int bits_per_sample;
-    int bds_len, bds_nbits, bds_flag, lspherc, lcomplex,/* lcompress,*/ bds_ubits;
-    int bds_head = 11;
-    int bds_ext = 0;
-    int bds_zoffset, bds_zstart;
-    unsigned char *pbuf = NULL;
+  Put3Byte(bmsLen);   /*  0- 2 Length of Block 3 Byte 0 */
+  Put1Byte(bmsUnusedBits);
+  Put2Byte(0);
 
-    bds_zstart  = 14;
-    bds_zoffset = 12;
-    if ( llarge ) bds_zoffset += 2;
+  *gribLen += bmsLen;
 
-    bds_len   = BDS_Len;
-    bds_len   = correct_bdslen(bds_len, gribLen, bds-dbuf);
-    bds_nbits = BDS_NumBits;
-    bds_flag  = BDS_Flag;
-    bds_ubits = bds_flag & 15;
-    lspherc   =  bds_flag >> 7;
-    lcomplex  = (bds_flag >> 6)&1;
-    /* lcompress = (bds_flag >> 4)&1; */
-    
-    if ( bds_nbits != 8 && bds_nbits != 16 && bds_nbits != 24 && bds_nbits != 32 )
-      {
-	static int linfo = 1;
-	if ( linfo && bds_nbits != 0 )
-	  {
-	    linfo = 0;
-	    fprintf(stderr, "GRIB szip only supports 8, 16, 24 and 32 bit data!\n");
-	  }
-	return (rec_len);
-      }
+  *datasize = fsec4size;
+}
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      bits_per_sample    = 8;
-    else
-#endif
-      bits_per_sample    = bds_nbits;
 
-#if defined (HAVE_LIBAEC)
-    strm.bits_per_sample = bits_per_sample;
-    strm.block_size      = PIXELS_PER_BLOCK;
-    strm.rsi             = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
-    strm.flags           = AEC_FLAGS;
-    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
-#else
-    sz_param.options_mask        = OPTIONS_MASK;
-    sz_param.bits_per_pixel      = bits_per_sample;
-    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
-    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
-#endif
+/* GRIB BLOCK 4 - BINARY DATA SECTION */
+static
+int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
+			  long *datstart, long *datsize, int code)
+{
+  /* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
+  /* Uwe Schulzweida,  6/05/2003 : Copy result to fpval to prevent integer overflow */
 
-    if ( lspherc )
-      {
-	if ( lcomplex  )
-	  {
-	    int jup, ioff;
-	    jup  = bds[15];
-	    ioff = (jup+1)*(jup+2);
-	    bds_ext = 4 + 3 + 4*ioff;
-	  }
-	else
-	  {
-	    bds_ext = 4;
-	  }
-      }
+  size_t z = *gribLen;
+  long i, jloop;
+  int numBits;
+  int ival;
+  int blockLength, PackStart = 0, Flag = 0;
+  int binscale = 0;
+  int nbpv;
+  int bds_head = 11;
+  int bds_ext = 0;
+  /* ibits = BitsPerInt; */
+  unsigned int max_nbpv_pow2;
+  int exponent, mantissa;
+  int unused_bits = 0;
+  int lspherc = FALSE, lcomplex = FALSE;
+  int isubset = 0, itemp = 0, itrunc = 0;
+  T factor = 1, fmin, fmax;
+  double zref;
+  double range, rangec;
+  double jpepsln = 1.0e-12;     /* -----> tolerance used to check equality     */
+                                /*        of floating point numbers - needed   */
+		                /*        on some platforms (eg vpp700, linux) */
+  extern const double _pow2tab[158];
+  extern int CGRIBEX_Const;         /* 1: Don't pack constant fields on regular grids */
 
-    datstart = bds_head + bds_ext;
+  if ( isec2 )
+    {
+      /* If section 2 is present, it says if data is spherical harmonic */
 
-    datsize = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+      if ( isec2[0] == 50 || isec2[0] == 60 || 
+	   isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
 
-    if ( datsize < MIN_SIZE ) return (rec_len);
-    /*
-    fprintf(stderr, "%d %d %d %d\n", bds_len, datstart, bds_len - datstart, datsize);
-    */
-    sourceLen = datsize;
-    destLen   = sbufsize;
-    
-    source = bds + datstart;
-    dest = sbuf;
+      if ( lspherc )
+	isec4[2] = 128;
+      else
+	isec4[2] = 0;
+    }
+  else
+    {
+      /* Section 4 says if it's spherical harmonic data.. */
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      {
-	long nelem;
-	nelem = sourceLen/3;
-	pbuf = (unsigned char*) malloc(sourceLen);
-	for ( i = 0; i < nelem; i++ )
-	  {
-	    pbuf[        i] = source[3*i  ];
-	    pbuf[  nelem+i] = source[3*i+1];
-	    pbuf[2*nelem+i] = source[3*i+2];
-	  }
-	source = pbuf;
-      }
-#endif
+      lspherc = ( isec4[2] == 128 );
+    }
 
-#if defined (HAVE_LIBAEC)
-    strm.next_in = source;
-    strm.avail_in = sourceLen;
-    strm.next_out = dest;
-    strm.avail_out = destLen;
+  /* Complex packing supported for spherical harmonics. */
 
-    status = aec_buffer_encode(&strm);
-    if ( status != AEC_OK )
-      {
-       	if ( status != AEC_DATA_ERROR )
-	  Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
+  lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
+             ( lspherc && isec2 && ( isec2[5] == 2 ) );
 
-    destLen = strm.total_out;
-#else
-    status = SZ_BufftoBuffCompress(dest, &destLen, source, sourceLen, &sz_param);
-    if ( status != SZ_OK )
-      {
-	if ( status == SZ_NO_ENCODER_ERROR )
-	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_PARAM_ERROR )
-	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_MEM_ERROR )
-	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_OUTBUFF_FULL )
-	  /*Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2)*/;
-	else
-	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
-#endif
-    
-    if ( pbuf ) free(pbuf);
-    /*
-    fprintf(stderr, "sourceLen, destLen %d %d\n", sourceLen, destLen);
-    */
-    if ( destLen < MIN_COMPRESS*sourceLen )
-      {
-	source = bds + datstart + bds_zoffset;
-	memcpy(source, dest, destLen);
-	
-	/* ----++++ number of unused bits at end of section) */
+  /* Check input specification is consistent */
 
-	BDS_Flag -= bds_ubits;
-    
-	gribLenOld = gribLen;
+  if ( lcomplex && isec2 )
+    {
+      if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+	}
+      else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
+	{
+	  gprintf(__func__, "  COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
+	  gprintf(__func__, "  COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
+	  return (807);
+        }
+      else if ( lcomplex )
+	{
+	  /*
+	    Truncation of full spectrum, which is supposed triangular,
+	    has to be diagnosed. Define also sub-set truncation.
+	  */
+	  isubset = isec4[17];
+	  /* When encoding, use the total number of data. */
+	  itemp   = isec4[0];
+	  itrunc  = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
+	}
+    }
 
-	if ( bds_ext )
-	  for ( i = bds_ext-1; i >= 0; --i )
-	    bds[bds_zoffset+bds_head+i] = bds[bds_head+i];
+  if ( decscale )
+    {
+      T scale = (T) pow(10.0, (double) decscale);
+      for ( i = 0; i < datasize; ++i ) data[i] *= scale;
+    }
+
+  if ( lspherc )
+    {
+      if ( lcomplex )
+	{
+	  int jup, ioff;
+	  jup  = isubset;
+	  ioff = (jup+1)*(jup+2);
+	  bds_ext = 4 + 3 + 4*ioff;
+	  PackStart = ioff;
+	  Flag = 192;
+	}
+      else
+	{
+	  bds_ext = 4;
+	  PackStart = 1;
+	  Flag = 128;
+	}
+    }
 
-	/*
-	fprintf(stderr, "destLen, datsize, datstart %d %d %d\n", destLen, datsize, datstart);
-	*/
-	/*	memcpy(bds + datstart + bds_zoffset, source, destLen); */
-	/*
-	  fprintf(stderr, "z>>> %d %d %d %d <<<\n", (int) bds[0+datstart+bds_zoffset],
-	    (int)bds[1+datstart+bds_zoffset], (int)bds[2+datstart+bds_zoffset], (int)bds[3+datstart+bds_zoffset]);
-	*/
-	if ( llarge )
-	  {
-	    if ( gribLenOld%120 )
-	      {
-		fprintf(stderr, "Internal problem, record length not multiple of 120!");
-		while ( gribLenOld%120 ) gribLenOld++;
-	      }
-	    gribLenOld = gribLenOld / (-120);
-	    gribLenOld = JP23SET - gribLenOld + 1;
+  *datstart = bds_head + bds_ext;
 
-	    SetLen3(bds, bds_zstart, gribLenOld);
-	    SetLen4(bds, bds_zstart+3, sourceLen);
-	    SetLen4(bds, bds_zstart+7, destLen);
-	  }
-	else
-	  {
-	    SetLen3(bds, bds_zstart, gribLenOld);
-	    SetLen3(bds, bds_zstart+3, sourceLen);
-	    SetLen3(bds, bds_zstart+6, destLen);
-	  }
+  nbpv = numBits = ISEC4_NumBits;
 
-	bdsLen = datstart + bds_zoffset + destLen;
+  if ( lspherc && lcomplex )
+    {
+      int pcStart, pcScale;
+      pcStart = isubset;
+      pcScale = isec4[16];
+      TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
+      TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+    }
 
-	bds[11] = 0;
-	bds[12] = 0;
-#if defined (HAVE_LIBAEC)
-	BDS_Z   = Z_AEC;
-#else
-	BDS_Z   = Z_SZIP;
-#endif
+  fmin = fmax = data[PackStart];
 
-	BDS_Flag += 16;
-	if ( (bdsLen%2) == 1 )
-	  {
-	    BDS_Flag += 8;
-	    bds[bdsLen++] = 0;
-	  }
+  TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
 
-	SetLen3(bds, 0, bdsLen);
+  zref = (double)fmin;
 
-	gribLen = (bds - dbuf) + bdsLen;
 
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
-	dbuf[gribLen++] = '7';
+  if ( CGRIBEX_Const && !lspherc )
+    {
+      if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
+    }
 
-	if ( llarge )
-	  {
-	    long itemp;
-	    long bdslen = gribLen - 4;
 
-	    /*
-	      If a very large product, the section 4 length field holds
-	      the number of bytes in the product after section 4 upto
-	      the end of the padding bytes.
-	      This is a fixup to get round the restriction on product lengths
-	      due to the count being only 24 bits. It is only possible because
-	      the (default) rounding for GRIB products is 120 bytes.
-	    */
-	    while ( gribLen%120 ) dbuf[gribLen++] = 0;
+  blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+  if ( (blockLength%2) == 1 ) blockLength++;
 
-	    itemp = gribLen / (-120);
-	    itemp = JP23SET - itemp + 1;
+  unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
 
-	    SetLen3(dbuf, 4, itemp);
+  Flag += unused_bits;
 
-	    bdslen = gribLen - bdslen;
 
-	    SetLen3(bds, 0, bdslen);
-	  }
-	else
-	  {
-	    SetLen3(dbuf, 4, gribLen);
-	  }
-      }
-    else
-      {
-      }
-    /*
-    fprintf(stderr, "%3d %3d griblen in %6d  out %6d  CR %g   slen %6d dlen %6d  CR %g\n",
-	    PDS_Parameter, PDS_Level1, gribLenOld, gribLen,
-	    ((double)gribLenOld)/gribLen, sourceLen, destLen,
-	    ((double)sourceLen)/destLen);
-    */
-  }
+  /*
+    Adjust number of bits per value if full integer length to
+    avoid hitting most significant bit (sign bit).
+  */
+  /* if( nbpv == ibits ) nbpv = nbpv - 1; */
+  /*
+    Calculate the binary scaling factor to spread the range of
+    values over the number of bits per value.
+    Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floats
+    as a guideline).           
+  */
+  range = fabs(fmax - fmin);
 
-#else
-  if ( libszwarn )
+  if ( fabs(fmin) < FLT_MIN ) fmin = 0;
+  /*
+    Have to allow tolerance in comparisons on some platforms
+    (eg vpp700 and linux), such as 0.9999999999999999 = 1.0,
+    to avoid clipping ranges which are a power of 2.
+  */
+  if ( range <= jpepsln )
     {
-      Warning("Compression disabled, szlib or libaec not available!");
-      libszwarn = 0;
+      binscale = 0;
+    }
+  else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
+    {
+      binscale = 0;
+    }
+  else if ( fabs(range-1.0) <= jpepsln )
+    {
+      binscale = 1 - nbpv;
+    }
+  else if ( range > 1.0 )
+    {
+      rangec = range + jpepsln;
+      for ( jloop = 1; jloop < 128; jloop++ )
+	{
+	  if ( _pow2tab[jloop] > rangec ) break;
+	}
+      if ( jloop == 128 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = jloop - nbpv;
+	}
     }
-#endif
-
-  if ( llarge )
-    while ( gribLen%120 ) dbuf[gribLen++] = 0;
   else
-    while ( gribLen & 7 ) dbuf[gribLen++] = 0;
+    {
+      rangec = range - jpepsln;
+      for ( jloop = 1; jloop < 127; jloop++ )
+	{
+	  if ( 1.0/_pow2tab[jloop] < rangec ) break;
+	}
+      if ( jloop == 127 )
+	{
+	  gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+	  gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+	  return (707);
+	}
+      else
+	{
+	  binscale = 1 - jloop - nbpv;
+	}
+    }
 
-  rec_len = gribLen;
+  //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
+  max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
 
-  return (rec_len);
-}
+  if ( binscale != 0 )
+    {
+      if ( binscale < 0 )
+	{
+	  if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
+	}
+      else
+	{
+	  if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
+	}
 
+      if ( binscale < 0 ) factor =     intpow2(-binscale);
+      else                factor = 1.0/intpow2( binscale);
+    }
 
-int  gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
-{
-#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
-  static int libszwarn = 1;
-#endif
-  int nerr;
-  unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
-  int bdsLen, recLen, gribLen = 0;
-  unsigned char *dest, *source;
-  size_t destLen, sourceLen;
-  int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
-  int bds_head = 11;
-  int bds_ext = 0;
-  int bds_zoffset, bds_zstart;
-  int datstart = 0;
-  int llarge = FALSE;
+  ref2ibm(&zref, BitsPerInt);
 
-  nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
+  Put3Byte(blockLength);      /*  0-2 Length of Block 4        */
+  Put1Byte(Flag);             /*  3   Flag & Unused bits       */
+  if ( binscale < 0 ) binscale = 32768 - binscale;
+  Put2Byte(binscale);         /*  4-5 Scale factor             */
+  Put1Real(zref);             /*  6-9 Reference value          */
+  Put1Byte(nbpv);             /*   10 Packing size             */
+
+  if ( lspherc )
     {
-      fprintf(stdout, "grib1Sections error\n");
-      return (0);
+      if ( lcomplex )
+	{
+	  int jup = isubset;
+	  int ioff = z + bds_ext;
+	  if ( ioff > 0xFFFF ) ioff = 0;
+	  Put2Byte(ioff);
+	  Put2Int(isec4[16]);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  Put1Byte(jup);
+	  for ( i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
+	}
+      else
+	{
+	  Put1Real((double)(data[0]));
+	}
     }
 
-  bds_zstart = 14;
+  *datsize  = ((datasize-PackStart)*nbpv + 7)/8;
 
-  recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
-  if ( recLen > JP23SET ) llarge = TRUE;
+#if  defined  (_ARCH_PWR6)
+  TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#else
+  TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+#endif
 
-  bds_zoffset = 12;
-  if ( llarge ) bds_zoffset += 2;
+  if ( unused_bits >= 8 ) Put1Byte(0);  /*  Fillbyte                     */
+
+  *gribLen = z;
+
+  return (0);
+}
+
+
+void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
+			     T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
+			     int kleng, int *kword, int efunc, int *kret)
+{
+  long gribLen = 0; /* Counter of GRIB length for output */
+  long isLen, pdsLen;
+  GRIBPACK *lpds;
+  unsigned char *CGrib;
+  long fsec4size = 0;
+  int numBytes;
+  int bmsIncluded;
+  size_t len;
+  GRIBPACK *lGrib;
+  long datstart, datsize, bdsstart;
+  int status = 0;
 
-  /* bds_len   = BDS_Len; */
-  bds_nbits = BDS_NumBits;
-  bds_flag  = BDS_Flag;
-  lspherc   =  bds_flag >> 7;
-  lcomplex  = (bds_flag >> 6)&1;
-  /* lcompress = (bds_flag >> 4)&1; */
+  UNUSED(isec3);
+  UNUSED(efunc);
 
-  if ( lspherc )
-    {
-      if ( lcomplex  )
-	{
-	  int jup, ioff;
-	  jup  = bds[bds_zoffset+15];
-	  ioff = (jup+1)*(jup+2);
-	  bds_ext = 4 + 3 + 4*ioff;
-	}
-      else
-	{
-	  bds_ext = 4;
-	}
-    }
+  grsdef();
 
-  datstart = bds_head + bds_ext;
+  CGrib = (unsigned char *) kgrib;
 
-  source = bds + datstart + bds_zoffset;
-  if ( llarge )
-    sourceLen = ((size_t) ((bds[21]<<24)+(bds[22]<<16)+(bds[23]<<8)+bds[24]));
-  else
-    sourceLen = ((size_t) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
+  bmsIncluded = ISEC1_Sec2Or3Flag & 64;
 
-  nerr = grib1Sections(dbuf, sbufsize, &pds, &gds, &bms, &bds);
-  if ( nerr )
-    {
-      fprintf(stdout, "grib1Sections error\n");
-      return (0);
-    }
+  /* set max header len */
+  len = 16384;
 
-  dest = bds + datstart;
-   if ( llarge )
-    destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
-  else
-    destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
+  /* add data len */
+  numBytes = (ISEC4_NumBits+7)>>3;
 
-  BDS_Flag -= 16;
+  len += numBytes*klenp;
 
-  bdsLen = datstart + destLen;
+  /* add bitmap len */
+  if ( bmsIncluded ) len += (klenp+7)>>3;
 
-#if  defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
-  {
-    int status;
-    long i;
-    size_t tmpLen;
-    int bds_ubits;
-    int bits_per_sample;
-#if defined (HAVE_LIBAEC)
-    struct aec_stream strm;
+#if defined (VECTORCODE)
+  lGrib = (GRIBPACK*) malloc(len*sizeof(GRIBPACK));
+  if ( lGrib == NULL ) SysError("No Memory!");
 #else
-    SZ_com_t sz_param;          /* szip parameter block */
+  lGrib = CGrib;
 #endif
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      bits_per_sample    = 8;
-    else
-#endif
-      bits_per_sample    = bds_nbits;
+  isLen = 8;
+  encodeIS(lGrib, &gribLen);
+  lpds = &lGrib[isLen];
+  pdsLen = getPdsLen(isec1);
 
-#if defined (HAVE_LIBAEC)
-    strm.bits_per_sample         = bits_per_sample;
-    strm.block_size              = PIXELS_PER_BLOCK;
-    strm.rsi                     = PIXELS_PER_SCANLINE / PIXELS_PER_BLOCK;
-    strm.flags                   = AEC_FLAGS;
-    if ( bds_nbits == 24 ) strm.flags |= AEC_DATA_3BYTE; 
-#else
-    sz_param.options_mask        = OPTIONS_MASK;
-    sz_param.bits_per_pixel      = bits_per_sample;
-    sz_param.pixels_per_block    = PIXELS_PER_BLOCK;
-    sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
-#endif
+  encodePDS(lpds, pdsLen,  isec1);
+  gribLen += pdsLen;
+  /*
+  if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
+    {
+      static int lwarn_cplx = TRUE;
 
-    if ( bds_ext )
-      for ( i = 0; i < bds_ext; ++i )
-	bds[bds_head+i] = bds[bds_zoffset+bds_head+i];
+      if ( lwarn_cplx )
+	Message("Complex packing of spectral data unsupported, using simple packing!");
 
-    /*
-    fprintf(stderr, "gribUnzip: sourceLen %ld; destLen %ld\n", (long)sourceLen, (long)destLen);
-    fprintf(stderr, "gribUnzip: sourceOff %d; destOff %d\n", bds[12], bds[11]);
-    fprintf(stderr, "gribUnzip: reclen %d; bdslen %d\n", recLen, bdsLen);
-    */
+      isec2[5] = 1;
+      isec4[3] = 0;
 
-    tmpLen = destLen;
-#if defined (HAVE_LIBAEC)
-    strm.next_in   = source;
-    strm.avail_in  = sourceLen;
-    strm.next_out  = dest;
-    strm.avail_out = tmpLen;
+      lwarn_cplx = FALSE;
+    }
+  */
+  TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
+  /*
+    ----------------------------------------------------------------
+    BMS Bit-Map Section Section (Section 3)
+    ----------------------------------------------------------------
+  */ 
+  if ( bmsIncluded )
+    {
+      TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
+    }
+  else
+    {
+      fsec4size = ISEC4_NumValues;
+    }
 
-    status = aec_buffer_decode(&strm);
-    if ( status != AEC_OK )
-      Warning("AEC ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
+  bdsstart = gribLen;
+  status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
+				 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
+  if ( status )
+    {
+      *kret = status;
+      return;
+    }
 
-    tmpLen = strm.total_out;
-#else
-    status = SZ_BufftoBuffDecompress(dest, &tmpLen, source, sourceLen, &sz_param);
-    if ( status != SZ_OK )
-      {
-	if ( status == SZ_NO_ENCODER_ERROR )
-	  Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_PARAM_ERROR )
-	  Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_MEM_ERROR )
-	  Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else if ( status == SZ_OUTBUFF_FULL )
-	  Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2);
-	else
-	  Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
-      }
-#endif
-    /*
-    fprintf(stderr, "gribUnzip: sl = %ld  dl = %ld   tl = %ld\n",
-	    (long)sourceLen, (long)destLen,(long) tmpLen);
-    */
-    if ( tmpLen != destLen )
-      Warning("unzip size differ: code %3d level %3d  ibuflen %ld ubuflen %ld",
-	      PDS_Parameter, PDS_Level2, (long) destLen, (long) tmpLen);
+  encodeES(lGrib, &gribLen, bdsstart);
 
-#if defined (HAVE_LIBSZ)
-    if ( bds_nbits == 24 )
-      {
-	long nelem;
-	unsigned char *pbuf;
-	nelem = tmpLen/3;
-	pbuf = (unsigned char*) malloc(tmpLen);
-	for ( i = 0; i < nelem; i++ )
-	  {
-	    pbuf[3*i  ] = dest[        i];
-	    pbuf[3*i+1] = dest[  nelem+i];
-	    pbuf[3*i+2] = dest[2*nelem+i];
-	  }
-	memcpy(dest, pbuf, tmpLen);
-	free(pbuf);
-      }
-#endif
+  if ( (size_t) gribLen > kleng*sizeof(int) )
+    Error("kgrib buffer too small! kleng = %d  gribLen = %d", kleng, gribLen);
 
-    bds_ubits = BDS_Flag & 15;
-    BDS_Flag -= bds_ubits;
+#if defined (VECTORCODE)
+  if ( (size_t) gribLen > len )
+    Error("lGrib buffer too small! len = %d  gribLen = %d", len, gribLen);
 
-    if ( (bdsLen%2) == 1 )
-      {
-	BDS_Flag += 8;
-	bds[bdsLen++] = 0;
-      }
+  (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
 
-    SetLen3(bds, 0, bdsLen);
+  free(lGrib);
+#endif
 
-    gribLen = (bds - dbuf) + bdsLen;
-    
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
-    dbuf[gribLen++] = '7';
+  ISEC0_GRIB_Len     = gribLen;
+  ISEC0_GRIB_Version = 1;
 
-    if ( llarge )
-      {
-	long itemp;
-        bdsLen = gribLen - 4;
-	/*
-	  If a very large product, the section 4 length field holds
-	  the number of bytes in the product after section 4 upto
-	  the end of the padding bytes.
-	  This is a fixup to get round the restriction on product lengths
-	  due to the count being only 24 bits. It is only possible because
-	  the (default) rounding for GRIB products is 120 bytes.
-	*/
-	while ( gribLen%120 ) dbuf[gribLen++] = 0;
+  *kword = gribLen / sizeof(int);
+  if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
 
-	if ( gribLen != recLen )
-	  fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
-	
-	itemp = gribLen / (-120);
-	itemp = JP23SET - itemp + 1;
-	
-	SetLen3(dbuf, 4, itemp);
+  *kret = status;
+}
 
-	bdsLen = gribLen - bdsLen;
-	    
-	SetLen3(bds, 0, bdsLen);
-      }
-    else
-      {
-	SetLen3(dbuf, 4, recLen);
-      }
-    /*
-    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
-    */
-    if ( llarge )
-      while ( gribLen%120 ) dbuf[gribLen++] = 0;
-    else
-      while ( gribLen & 7 ) dbuf[gribLen++] = 0;
-    /*
-    fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
-    */
-  }
-#else
-  if ( libszwarn )
-    {
-      Warning("Decompression disabled, szlib or libaec not available!");
-      libszwarn = 0;
-    }
-#endif
+#endif /* T */
 
-  return (gribLen);
+void encode_dummy(void)
+{
+  (void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
+  (void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
 }
-static const char grb_libvers[] = "1.6.4" " of ""Jun 27 2014"" ""14:00:04";
+static const char grb_libvers[] = "1.7.0" " of ""Sep 30 2014"" ""13:27:33";
 const char *
 cgribexLibraryVersion(void)
 {
   return (grb_libvers);
 }
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic pop
+#endif
+
diff --git a/libcdi/src/cksum.c b/libcdi/src/cksum.c
index 77a2c60..32c3cc3 100644
--- a/libcdi/src/cksum.c
+++ b/libcdi/src/cksum.c
@@ -1,10 +1,15 @@
-#include <inttypes.h>
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
+#include <inttypes.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#ifdef WORDS_BIGENDIAN
+#include <limits.h>
+#endif
+
+#include "cksum.h"
 
 static const uint32_t crctab[] = {
   0x00000000,
@@ -71,18 +76,13 @@ memcrc(const unsigned char *b, size_t n)
  */
 
 
-  register uint32_t i, c, s = 0;
-
-
-  for (i = n; i > 0; --i) {
-    c = (uint32_t)(*b++);
-    s = (s << 8) ^ crctab[(s >> 24) ^ c];
-  }
+  uint32_t s = 0;
 
+  memcrc_r(&s, b, n);
 
   /* Extend with the length of the string. */
   while (n != 0) {
-    c = n & 0377;
+    register uint32_t c = n & 0377;
     n >>= 8;
     s = (s << 8) ^ crctab[(s >> 24) ^ c];
   }
@@ -100,11 +100,11 @@ memcrc_r(uint32_t *state, const unsigned char *block, size_t block_len)
  */
 
 
-  register uint32_t i, c, s = *state;
+  register uint32_t c, s = *state;
   register size_t n = block_len;
   register const unsigned char *b = block;
 
-  for (i = n; i > 0; --i) {
+  for (; n > 0; --n) {
     c = (uint32_t)(*b++);
     s = (s << 8) ^ crctab[(s >> 24) ^ c];
   }
@@ -172,7 +172,7 @@ uint32_t
 memcrc_finish(uint32_t *state, off_t total_size)
 {
   register uint32_t c, s = *state;
-  register off_t n = total_size;
+  register uint64_t n = (uint64_t)total_size;
 
   /* Extend with the length of the string. */
   while (n != 0) {
diff --git a/libcdi/src/cksum.h b/libcdi/src/cksum.h
index 69f404c..5601826 100644
--- a/libcdi/src/cksum.h
+++ b/libcdi/src/cksum.h
@@ -1,5 +1,5 @@
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#  include "config.h"
 #endif
 
 #include <inttypes.h>
diff --git a/libcdi/src/config.h.in b/libcdi/src/config.h.in
index fd911e3..249e423 100644
--- a/libcdi/src/config.h.in
+++ b/libcdi/src/config.h.in
@@ -23,6 +23,9 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* Define to 1 if you have the <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
 /* Define to 1 if you have the `getline' function. */
 #undef HAVE_GETLINE
 
@@ -128,12 +131,12 @@
 /* ScalES PPM C core library is available */
 #undef HAVE_PPM_CORE
 
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
 /* Define to 1 if you have the <pthread.h> header file. */
 #undef HAVE_PTHREAD_H
 
+/* Have PTHREAD_PRIO_INHERIT. */
+#undef HAVE_PTHREAD_PRIO_INHERIT
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
diff --git a/libcdi/src/dmemory.c b/libcdi/src/dmemory.c
index c5d3a54..89c9074 100644
--- a/libcdi/src/dmemory.c
+++ b/libcdi/src/dmemory.c
@@ -49,8 +49,8 @@ typedef struct
 }
 MemTable_t;
 
-static MemTable_t* memTable;
-static int     memTableSize  = 0;
+static MemTable_t *memTable;
+static size_t  memTableSize  = 0;
 static long    memAccess     = 0;
 
 static size_t  MemObjs       = 0;
@@ -130,23 +130,23 @@ void memListPrintEntry(int mtype, int item, size_t size, void *ptr,
 static
 void memListPrintTable(void)
 {
-  int memID, item, item1, item2 = 0;
+  int item, item1, item2 = 0;
 
   if ( MemObjs ) fprintf(stderr, "\nMemory table:\n");
 
   /* find maximum item */
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (size_t memID = 0; memID < memTableSize; memID++)
     if ( memTable[memID].item != UNDEFID )
       if ( memTable[memID].item > item2 ) item2 = memTable[memID].item;
 
   /* find minimum item */
   item1 = item2;
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (size_t memID = 0; memID < memTableSize; memID++)
     if ( memTable[memID].item != UNDEFID )
       if ( memTable[memID].item < item1 ) item1 = memTable[memID].item;
 
   for ( item = item1; item <= item2; item++ )
-    for ( memID = 0; memID < memTableSize; memID++ )
+    for (size_t memID = 0; memID < memTableSize; memID++)
       {
 	if ( memTable[memID].item == item )
 	  memListPrintEntry(memTable[memID].mtype, memTable[memID].item,
@@ -158,7 +158,7 @@ void memListPrintTable(void)
   if ( MemObjs )
     {
       fprintf(stderr, "  Memory access             : %6u\n", (unsigned) memAccess);
-      fprintf(stderr, "  Maximum objects           : %6u\n", (unsigned) memTableSize);
+      fprintf(stderr, "  Maximum objects           : %6zu\n", memTableSize);
       fprintf(stderr, "  Objects used              : %6u\n", (unsigned) MaxMemObjs);
       fprintf(stderr, "  Objects in use            : %6u\n", (unsigned) MemObjs);
       fprintf(stderr, "  Memory allocated          : ");
@@ -218,10 +218,10 @@ void memInit(void)
 static
 int memListDeleteEntry(void *ptr, size_t *size)
 {
-  int memID = 0;
   int item = UNDEFID;
+  size_t memID;
 
-  for ( memID = 0; memID < memTableSize; memID++ )
+  for (memID = 0; memID < memTableSize; memID++ )
     {
       if ( memTable[memID].item == UNDEFID ) continue;
       if ( memTable[memID].ptr == ptr ) break;
@@ -240,9 +240,9 @@ int memListDeleteEntry(void *ptr, size_t *size)
 }
 
 static
-void memTableInitEntry(int memID)
+void memTableInitEntry(size_t memID)
 {
-  if ( memID < 0 || memID >= memTableSize )
+  if ( memID >= memTableSize )
     memInternalProblem(__func__, "memID %d undefined!", memID);
 
   memTable[memID].ptr    = NULL;
@@ -259,9 +259,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 {
   static int item = 0;
   size_t memSize = 0;
-  int memID = 0;
-  size_t len;
-  int i;
+  size_t memID = 0;
 
   /*
     Look for a free slot in memTable.
@@ -270,11 +268,11 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
   if ( memTableSize == 0 )
     {
       memTableSize = 8;
-      memSize  = memTableSize*sizeof(MemTable_t);
-      memTable = (MemTable_t*) malloc(memSize);
+      memSize  = memTableSize * sizeof(MemTable_t);
+      memTable = (MemTable_t *) malloc(memSize);
       if( memTable == NULL ) memError(__func__, __FILE__, __LINE__, memSize);
 
-      for( i = 0; i < memTableSize; i++ )
+      for(size_t i = 0; i < memTableSize; i++)
 	memTableInitEntry(i);
     }
   else
@@ -295,7 +293,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
       memTable = (MemTable_t*) realloc(memTable, memSize);
       if( memTable == NULL ) memError(__func__, __FILE__, __LINE__, memSize);
 
-      for( i = memID; i < memTableSize; i++ )
+      for (size_t i = memID; i < memTableSize; i++)
 	memTableInitEntry(i);
     }
 
@@ -308,7 +306,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 
   if ( file )
     {
-      len = strlen(file);
+      size_t len = strlen(file);
       if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
       (void) memcpy(memTable[memID].file, file, len);
@@ -321,7 +319,7 @@ int memListNewEntry(int mtype, void *ptr, size_t size, size_t nobj,
 
   if ( caller )
     {
-      len = strlen(caller);
+      size_t len = strlen(caller);
       if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
       (void) memcpy(memTable[memID].caller, caller, len);
@@ -346,7 +344,6 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 {
   int item = UNDEFID;
   int memID = 0;
-  size_t len;
   size_t sizeold;
 
   while( memID < memTableSize )
@@ -375,7 +372,7 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 
       if ( file )
 	{
-	  len = strlen(file);
+	  size_t len = strlen(file);
 	  if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
 	  (void) memcpy(memTable[memID].file, file, len);
@@ -388,7 +385,7 @@ int memListChangeEntry(void *ptrold, void *ptr, size_t size,
 
       if ( caller )
 	{
-	  len = strlen(caller);
+	  size_t len = strlen(caller);
 	  if ( len > MAXNAME-1 ) len = MAXNAME-1;
 
 	  (void) memcpy(memTable[memID].caller, caller, len);
@@ -564,21 +561,21 @@ size_t memTotal(void)
   struct mallinfo meminfo = mallinfo();
   if ( MEM_Debug )
     {
-      fprintf(stderr, "arena      %8ld (non-mmapped space allocated from system)\n", (unsigned long) meminfo.arena);
-      fprintf(stderr, "ordblks    %8ld (number of free chunks)\n", (unsigned long) meminfo.ordblks);
-      fprintf(stderr, "smblks     %8ld (number of fastbin blocks)\n", (unsigned long) meminfo.smblks);
-      fprintf(stderr, "hblks      %8ld (number of mmapped regions)\n", (unsigned long) meminfo.hblks);
-      fprintf(stderr, "hblkhd     %8ld (space in mmapped regions)\n", (unsigned long) meminfo.hblkhd);
-      fprintf(stderr, "usmblks    %8ld (maximum total allocated space)\n", (unsigned long) meminfo.usmblks);
-      fprintf(stderr, "fsmblks    %8ld (maximum total allocated space)\n", (unsigned long) meminfo.fsmblks);
-      fprintf(stderr, "uordblks   %8ld (total allocated space)\n", (unsigned long) meminfo.uordblks);
-      fprintf(stderr, "fordblks   %8ld (total free space)\n", (unsigned long) meminfo.fordblks);
-      fprintf(stderr, "Memory in use:   %8ld bytes\n", (unsigned long) meminfo.usmblks + meminfo.uordblks);
-      fprintf(stderr, "Total heap size: %8ld bytes\n", (unsigned long) meminfo.arena);
+      fprintf(stderr, "arena      %8zu (non-mmapped space allocated from system)\n", (size_t)meminfo.arena);
+      fprintf(stderr, "ordblks    %8zu (number of free chunks)\n", (size_t)meminfo.ordblks);
+      fprintf(stderr, "smblks     %8zu (number of fastbin blocks)\n", (size_t) meminfo.smblks);
+      fprintf(stderr, "hblks      %8zu (number of mmapped regions)\n", (size_t) meminfo.hblks);
+      fprintf(stderr, "hblkhd     %8zu (space in mmapped regions)\n", (size_t) meminfo.hblkhd);
+      fprintf(stderr, "usmblks    %8zu (maximum total allocated space)\n", (size_t) meminfo.usmblks);
+      fprintf(stderr, "fsmblks    %8zu (maximum total allocated space)\n", (size_t) meminfo.fsmblks);
+      fprintf(stderr, "uordblks   %8zu (total allocated space)\n", (size_t) meminfo.uordblks);
+      fprintf(stderr, "fordblks   %8zu (total free space)\n", (size_t) meminfo.fordblks);
+      fprintf(stderr, "Memory in use:   %8zu bytes\n", (size_t) meminfo.usmblks + (size_t)meminfo.uordblks);
+      fprintf(stderr, "Total heap size: %8zu bytes\n", (size_t) meminfo.arena);
 
       /* malloc_stats(); */
     }
-  memtotal = meminfo.arena;
+  memtotal = (size_t)meminfo.arena;
 #endif
 
   return (memtotal);
diff --git a/libcdi/src/extralib.c b/libcdi/src/extralib.c
index 1530317..0ecb706 100644
--- a/libcdi/src/extralib.c
+++ b/libcdi/src/extralib.c
@@ -13,13 +13,13 @@
 #include "error.h"
 #include "file.h"
 #include "binary.h"
+#include "stream_fcommon.h"
 #include "swap.h"
 
 
-#define  SINGLE_PRECISION    4
-#define  DOUBLE_PRECISION    8
-
-#define  EXT_HEADER_LEN      4
+enum {
+  EXT_HEADER_LEN = 4,
+};
 
 
 static int initExtLib       = 0;
@@ -43,7 +43,7 @@ const char *extLibraryVersion(void)
 }
 
 
-int EXT_Debug = 0;    /* If set to 1, debugging */
+static int EXT_Debug = 0;    /* If set to 1, debugging */
 
 
 void extDebug(int debug)
@@ -55,7 +55,7 @@ void extDebug(int debug)
 }
 
 
-void extLibInit()
+static void extLibInit()
 {
   char *envString;
   char *envName = "EXT_PRECISION";
@@ -147,11 +147,11 @@ void extDelete(void *ext)
 
 int extCheckFiletype(int fileID, int *swap)
 {
-  size_t blocklen = 0;
+  size_t blocklen = 0, fact = 0;
   size_t sblocklen = 0;
   size_t data =  0;
   size_t dimxy = 0;
-  int fact = 0, found = 0;
+  int found = 0;
   unsigned char buffer[40], *pbuf;
 
   if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
@@ -232,7 +232,7 @@ int extDefHeader(void *ext, const int *header)
   for ( i = 0; i < EXT_HEADER_LEN; i++ )
     extp->header[i] = header[i];
 
-  extp->datasize = header[3];
+  extp->datasize = (size_t)header[3];
   if ( extp->number == EXT_COMP ) extp->datasize *= 2;
 
   if ( EXT_Debug ) Message("datasize = %lu", extp->datasize);
@@ -241,9 +241,8 @@ int extDefHeader(void *ext, const int *header)
 }
 
 
-int extInqData(void *ext, int prec, void *data)
+static int extInqData(extrec_t *extp, int prec, void *data)
 {
-  extrec_t *extp = (extrec_t *) ext;
   size_t datasize;
   size_t i;
   int ierr = 0;
@@ -334,9 +333,9 @@ int extDefData(void *ext, int prec, const void *data)
 
   header = extp->header;
 
-  datasize = header[3];
+  datasize = (size_t)header[3];
   if ( extp->number == EXT_COMP ) datasize *= 2;
-  blocklen = datasize * rprec;
+  blocklen = datasize * (size_t)rprec;
 
   extp->datasize = datasize;
 
@@ -404,9 +403,7 @@ int extRead(int fileID, void *ext)
   size_t blocklen, blocklen2;
   size_t i;
   char tempheader[32];
-  int hprec, dprec;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -427,9 +424,9 @@ int extRead(int fileID, void *ext)
   if ( EXT_Debug )
     Message("blocklen = %lu", blocklen);
 
-  hprec = blocklen / EXT_HEADER_LEN;
+  size_t hprec = blocklen / EXT_HEADER_LEN;
 
-  extp->prec = hprec;
+  extp->prec = (int)hprec;
 
   switch ( hprec )
     {
@@ -466,15 +463,15 @@ int extRead(int fileID, void *ext)
       if ( blocklen2 != 0 ) return (-1);
     }
 
-  extp->datasize = extp->header[3];
+  extp->datasize = (size_t)extp->header[3];
 
   if ( EXT_Debug ) Message("datasize = %lu", extp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = extp->buffersize;
+  size_t buffersize = (size_t)extp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = extp->buffer;
@@ -485,7 +482,7 @@ int extRead(int fileID, void *ext)
   else
     buffer = extp->buffer;
 
-  dprec = blocklen / extp->datasize;
+  size_t dprec = blocklen / extp->datasize;
 
   if ( dprec == hprec )
     {
@@ -536,7 +533,7 @@ int extWrite(int fileID, void *ext)
   header = extp->header;
 
   /* write header record */
-  blocklen = EXT_HEADER_LEN * rprec;
+  blocklen = EXT_HEADER_LEN * (size_t)rprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -569,9 +566,9 @@ int extWrite(int fileID, void *ext)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = header[3];
+  datasize = (size_t)header[3];
   if ( number == EXT_COMP ) datasize *= 2;
-  blocklen = datasize * rprec;
+  blocklen = datasize * (size_t)rprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
diff --git a/libcdi/src/file.c b/libcdi/src/file.c
index 0d7d074..279d10a 100644
--- a/libcdi/src/file.c
+++ b/libcdi/src/file.c
@@ -3,16 +3,17 @@
 #endif
 
 #include <assert.h>
-#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
-#include <errno.h>
-#include <ctype.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>  // gettimeofday()
-#include <fcntl.h>
 
 #include "dmemory.h"
 #include "error.h"
@@ -189,7 +190,7 @@ void file_list_new(void)
 {
   assert(_fileList == NULL);
 
-  _fileList = (filePtrToIdx *) malloc(_file_max*sizeof(filePtrToIdx));
+  _fileList = (filePtrToIdx *)xmalloc((size_t)_file_max * sizeof (filePtrToIdx));
 }
 
 static
@@ -531,7 +532,6 @@ off_t fileGetPos(int fileID)
 int fileSetPos(int fileID, off_t offset, int whence)
 {
   int status = 0;
-  off_t position;
   bfile_t *fileptr;
 
   fileptr = file_to_pointer(fileID);
@@ -549,7 +549,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
     case SEEK_SET:
       if ( fileptr->mode == 'r' && fileptr->type == FILE_TYPE_OPEN )
 	{
-	  position = offset;
+	  off_t position = offset;
 	  fileptr->position = position;
 	  if ( position < fileptr->bufferStart || position > fileptr->bufferEnd )
 	    {
@@ -571,7 +571,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
 
 		  fileptr->bufferPos = fileptr->bufferEnd + 1;
 		}
-	      fileptr->bufferCnt = fileptr->bufferEnd - position + 1;
+	      fileptr->bufferCnt = (size_t)(fileptr->bufferEnd - position) + 1;
 	      fileptr->bufferPtr = fileptr->buffer + position - fileptr->bufferStart;
 	    }
 	}
@@ -584,7 +584,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
       if ( fileptr->mode == 'r' && fileptr->type == FILE_TYPE_OPEN )
 	{
 	  fileptr->position += offset;
-	  position = fileptr->position;
+	  off_t position = fileptr->position;
 	  if ( position < fileptr->bufferStart || position > fileptr->bufferEnd )
 	    {
 	      if ( fileptr->bufferType == FILE_BUFTYPE_STD )
@@ -605,7 +605,7 @@ int fileSetPos(int fileID, off_t offset, int whence)
 
 		  fileptr->bufferPos = fileptr->bufferEnd + 1;
 		}
-	      fileptr->bufferCnt -= offset;
+	      fileptr->bufferCnt -= (size_t)offset;
 	      fileptr->bufferPtr += offset;
 	    }
 	}
@@ -780,7 +780,7 @@ void file_initialize(void)
 	{
 	case FILE_TYPE_OPEN:
 	case FILE_TYPE_FOPEN:
-	  FileTypeRead = value;
+	  FileTypeRead = (int)value;
 	  break;
 	default:
 	  Warning("File type %d not implemented!", value);
@@ -794,13 +794,16 @@ void file_initialize(void)
 	{
 	case FILE_TYPE_OPEN:
 	case FILE_TYPE_FOPEN:
-	  FileTypeWrite = value;
+	  FileTypeWrite = (int)value;
 	  break;
 	default:
 	  Warning("File type %d not implemented!", value);
 	}
     }
 
+#if defined (O_NONBLOCK)
+  FileFlagWrite = O_NONBLOCK;
+#endif
   envString = getenv("FILE_FLAG_WRITE");
   if ( envString )
     {
@@ -823,7 +826,7 @@ void file_initialize(void)
 	{
 	case FILE_BUFTYPE_STD:
 	case FILE_BUFTYPE_MMAP:
-	  FileBufferTypeEnv = value;
+	  FileBufferTypeEnv = (int)value;
 	  break;
 	default:
 	  Warning("File buffer type %d not implemented!", value);
@@ -916,7 +919,7 @@ void file_set_buffer(bfile_t *fileptr)
 static
 int file_fill_buffer(bfile_t *fileptr)
 {
-  long nread;
+  ssize_t nread;
   int fd;
   long offset = 0;
   off_t retseek;
@@ -941,7 +944,8 @@ int file_fill_buffer(bfile_t *fileptr)
 	}
       else
 	{
-	  nread = fileptr->bufferSize;
+          xassert(fileptr->bufferSize <= SSIZE_MAX);
+	  nread = (ssize_t)fileptr->bufferSize;
 	  if ( (nread + fileptr->bufferPos) > fileptr->size )
 	    nread = fileptr->size - fileptr->bufferPos;
 
@@ -953,7 +957,7 @@ int file_fill_buffer(bfile_t *fileptr)
 	      fileptr->buffer = NULL;
 	    }
 
-	  fileptr->mappedSize = (size_t) nread;
+	  fileptr->mappedSize = (size_t)nread;
 
 	  fileptr->buffer = (char*) mmap(NULL, (size_t) nread, PROT_READ, MAP_PRIVATE, fd, fileptr->bufferPos);
 
@@ -969,7 +973,7 @@ int file_fill_buffer(bfile_t *fileptr)
       if ( retseek == (off_t)-1 )
 	SysError("lseek error at pos %ld file %s", (long) fileptr->bufferPos, fileptr->name);
 
-      nread = (long) read(fd, fileptr->buffer, fileptr->bufferSize);
+      nread = read(fd, fileptr->buffer, fileptr->bufferSize);
     }
 
   if ( nread <= 0 )
@@ -984,7 +988,7 @@ int file_fill_buffer(bfile_t *fileptr)
     }
 
   fileptr->bufferPtr = fileptr->buffer;
-  fileptr->bufferCnt = nread;
+  fileptr->bufferCnt = (size_t)nread;
 
   fileptr->bufferStart = fileptr->bufferPos;
   fileptr->bufferPos  += nread;
@@ -1007,7 +1011,7 @@ int file_fill_buffer(bfile_t *fileptr)
 	Error("Internal problem with buffer handling. nread = %d offset = %d", nread, offset);
 
       fileptr->bufferPtr += offset;
-      fileptr->bufferCnt -= offset;
+      fileptr->bufferCnt -= (size_t)offset;
     }
 
   fileptr->bufferNumFill++;
@@ -1084,11 +1088,9 @@ size_t file_read_from_buffer(bfile_t *fileptr, void *ptr, size_t size)
 
 void fileSetBufferSize(int fileID, long buffersize)
 {
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
-
-  if ( fileptr ) fileptr->bufferSize = buffersize;
+  bfile_t *fileptr = file_to_pointer(fileID);
+  xassert(buffersize >= 0);
+  if ( fileptr ) fileptr->bufferSize = (size_t)buffersize;
 }
 
 /*
@@ -1230,8 +1232,10 @@ int fileClose_serial(int fileID)
       if ( fileptr->type == FILE_TYPE_FOPEN )
 	fprintf(stderr, " file pointer     : %p\n",  (void *) fileptr->fp);
       else
-        fprintf(stderr, " file descriptor  : %d\n",  fileptr->fd);
-
+        {
+          fprintf(stderr, " file descriptor  : %d\n",  fileptr->fd);
+          fprintf(stderr, " file flag        : %d\n", FileFlagWrite);
+        }
       fprintf(stderr, " file mode        : %c\n",  fileptr->mode);
 
       if ( sizeof(off_t) > sizeof(long) )
@@ -1258,8 +1262,7 @@ int fileClose_serial(int fileID)
 
       if ( fileptr->time_in_sec > 0 )
         {
-          rout = fileptr->byteTrans;
-          rout /= 1024.*1014.*fileptr->time_in_sec;
+          rout = (double)fileptr->byteTrans / (1024.*1024.*fileptr->time_in_sec);
         }
 
       fprintf(stderr, " wall time [s]    : %.2f\n", fileptr->time_in_sec);
@@ -1380,8 +1383,8 @@ size_t filePtrRead(void *vfileptr, void *restrict ptr, size_t size)
 	    }
 	}
 
-      fileptr->position  += nread;
-      fileptr->byteTrans += nread;
+      fileptr->position  += (off_t)nread;
+      fileptr->byteTrans += (off_t)nread;
       fileptr->access++;
     }
 
@@ -1420,8 +1423,8 @@ size_t fileRead(int fileID, void *restrict ptr, size_t size)
 
       if ( FileInfo ) fileptr->time_in_sec += file_time() - t_begin;
 
-      fileptr->position  += nread;
-      fileptr->byteTrans += nread;
+      fileptr->position  += (off_t)nread;
+      fileptr->byteTrans += (off_t)nread;
       fileptr->access++;
     }
 
@@ -1449,12 +1452,21 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
       if ( fileptr->type == FILE_TYPE_FOPEN )
         nwrite = fwrite(ptr, 1, size, fileptr->fp);
       else
-        nwrite =  write(fileptr->fd, ptr, size);
+        {
+          ssize_t temp = write(fileptr->fd, ptr, size);
+          if (temp == -1)
+            {
+              perror("error writing to file");
+              nwrite = 0;
+            }
+          else
+            nwrite = (size_t)temp;
+        }
 
       if ( FileInfo ) fileptr->time_in_sec += file_time() - t_begin;
 
-      fileptr->position  += nwrite;
-      fileptr->byteTrans += nwrite;
+      fileptr->position  += (off_t)nwrite;
+      fileptr->byteTrans += (off_t)nwrite;
       fileptr->access++;
     }
 
diff --git a/libcdi/src/gaussgrid.c b/libcdi/src/gaussgrid.c
index 619d84f..ec31a64 100644
--- a/libcdi/src/gaussgrid.c
+++ b/libcdi/src/gaussgrid.c
@@ -15,7 +15,7 @@
 
 
 static
-void cpledn(int kn, int 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;
@@ -24,7 +24,7 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
   double zdlmod;
   double zdlxn;
 
-  int ik, jn;
+  size_t ik, jn;
 
   /* 1.0 Newton iteration step */
 
@@ -41,7 +41,7 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
 
   if (kflag == 0) 
     {
-      for(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);
@@ -73,9 +73,8 @@ void cpledn(int kn, int kodd, double *pfn, double pdx, int kflag,
 }
 
 static
-void gawl(double *pfn, double *pl, double *pw, int kn)
+void gawl(double *pfn, double *pl, double *pw, size_t kn)
 {
-  int iodd;
   double pmod = 0;
   int iflag;
   int itemax;
@@ -88,7 +87,7 @@ void gawl(double *pfn, double *pl, double *pw, int kn)
   iflag  =  0;
   itemax = 20;
 
-  iodd   = (kn % 2);
+  size_t iodd   = (kn % 2);
 
   zdlx   =  *pl;
 
@@ -109,7 +108,7 @@ void gawl(double *pfn, double *pl, double *pw, int kn)
 }
 
 static
-void gauaw(int 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
@@ -121,24 +120,22 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   double z, zfnn;
 
-  int ik, ins2, isym, jgl, jglm1, jn, iodd;
-
-  zfn    = (double *) malloc((kn+1)*(kn+1)*sizeof(double));
-  zfnlat = (double *) malloc((kn/2+1+1)*sizeof(double));  
+  zfn    = (double *) malloc((kn+1) * (kn+1) * sizeof(double));
+  zfnlat = (double *) malloc((kn/2+1+1)*sizeof(double));
 
   zfn[0] = M_SQRT2;
-  for (jn = 1; jn <= kn; jn++)
+  for (size_t jn = 1; jn <= kn; jn++)
     {
       zfnn = zfn[0];
-      for (jgl = 1; jgl <= jn; jgl++)
+      for (size_t jgl = 1; jgl <= jn; jgl++)
 	{
 	  zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl))); 
 	}
 
       zfn[jn*(kn+1)+jn] = zfnn;
 
-      iodd = jn % 2;
-      for (jgl = 2; jgl <= jn-iodd; jgl += 2) 
+      size_t iodd = jn % 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)));
@@ -148,9 +145,9 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   /* 2.0 Gaussian latitudes and weights */
 
-  iodd = kn % 2;
-  ik = iodd;
-  for (jgl = iodd; jgl <= kn; jgl += 2)
+  size_t iodd = kn % 2;
+  size_t ik = iodd;
+  for (size_t jgl = iodd; jgl <= kn; jgl += 2)
     {
       zfnlat[ik] = zfn[kn*(kn+1)+jgl];
       ik++;
@@ -161,9 +158,9 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
    *     Legendre polynomial of degree kn.
    */
 
-  ins2 = kn/2+(kn % 2);
+  size_t ins2 = kn/2+(kn % 2);
 
-  for (jgl = 1; jgl <= ins2; jgl++) 
+  for (size_t jgl = 1; jgl <= ins2; jgl++) 
     {
       z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2)); 
       pl[jgl-1] = z+1.0/(tan(z)*((double)(8*kn*kn)));
@@ -171,23 +168,23 @@ void gauaw(int kn, double *restrict pl, double *restrict pw)
 
   /* 2.2 Computes roots and weights for transformed theta */
 
-  for (jgl = ins2; jgl >= 1 ; jgl--) 
+  for (size_t jgl = ins2; jgl >= 1 ; jgl--) 
     {
-      jglm1 = jgl-1;
+      size_t jglm1 = jgl-1;
       gawl(zfnlat, &(pl[jglm1]), &(pw[jglm1]), kn);
     }
 
   /* convert to physical latitude */
 
-  for (jgl = 0; jgl < ins2; jgl++) 
+  for (size_t jgl = 0; jgl < ins2; jgl++) 
     {
       pl[jgl] = cos(pl[jgl]);
     }
 
-  for (jgl = 1; jgl <= kn/2; jgl++) 
+  for (size_t jgl = 1; jgl <= kn/2; jgl++) 
     {
-      jglm1 = jgl-1;
-      isym =  kn-jgl;
+      size_t jglm1 = jgl-1;
+      size_t isym =  kn-jgl;
       pl[isym] =  -pl[jglm1];
       pw[isym] =  pw[jglm1];
     }
@@ -291,7 +288,7 @@ void gauaw_old(double *pa, double *pw, int nlat)
 }
 #endif
 
-void gaussaw(double *restrict pa, double *restrict pw, int nlat)
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat)
 {
   //gauaw_old(pa, pw, nlat);
   gauaw(nlat, pa, pw);
diff --git a/libcdi/src/gaussgrid.h b/libcdi/src/gaussgrid.h
index 06168f7..c431324 100644
--- a/libcdi/src/gaussgrid.h
+++ b/libcdi/src/gaussgrid.h
@@ -1,7 +1,7 @@
 #ifndef _GAUSSGRID_H
 #define _GAUSSGRID_H
 
-void   gaussaw(double *restrict pa, double *restrict pw, int nlat);
+void   gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
 
 #endif  /* _GAUSSGRID_H */
 /*
diff --git a/libcdi/src/gribapi.c b/libcdi/src/gribapi.c
index 79337c7..331dbf7 100644
--- a/libcdi/src/gribapi.c
+++ b/libcdi/src/gribapi.c
@@ -17,19 +17,37 @@
 #define STRING(x)	XSTRING(x)
 
 static char gribapi_libvers[64] = "";
+#if  defined  (HAVE_LIBGRIB_API)
+static int gribapi_libvers_init;
+#endif
+
 
-const char *gribapiLibraryVersion(void)
+void gribapiLibraryVersion(int* major_version, int* minor_version, int* revision_version)
 {
 #if  defined  (HAVE_LIBGRIB_API)
   long version = grib_get_api_version();
-  int major_version, minor_version, revision_version;
+  (*major_version)    = version/10000;
+  (*minor_version)    = (version-(*major_version)*10000)/100;
+  (*revision_version) = (version-(*major_version)*10000-(*minor_version)*100);
+#else
+  (*major_version)    = 0;
+  (*minor_version)    = 0;
+  (*revision_version) = 0;
+#endif
+}
 
-  major_version    = version/10000;
-  minor_version    = (version-major_version*10000)/100;
-  revision_version = (version-major_version*10000-minor_version*100);
+const char *gribapiLibraryVersionString(void)
+{
+#if  defined  (HAVE_LIBGRIB_API)
+  if (!gribapi_libvers_init)
+    {
+      int major_version, minor_version, revision_version;
 
-  sprintf(gribapi_libvers, "%d.%d.%d",
-	  major_version, minor_version, revision_version);
+      gribapiLibraryVersion(&major_version, &minor_version, &revision_version);
+
+      sprintf(gribapi_libvers, "%d.%d.%d", major_version, minor_version, revision_version);
+      gribapi_libvers_init = 1;
+    }
 #endif
 
   return (gribapi_libvers);
@@ -69,8 +87,8 @@ void gribContainersNew(stream_t * streamptr)
 
       streamptr->gribContainers = (void **) gribContainers;
 #else
-      gribContainer_t *gribContainers;
-      gribContainers = (gribContainer_t *) malloc(nvars*sizeof(gribContainer_t));
+      gribContainer_t *gribContainers
+        = (gribContainer_t *)xmalloc((size_t)nvars*sizeof(gribContainer_t));
 
       for ( int varID = 0; varID < nvars; ++varID )
         {
diff --git a/libcdi/src/gribapi.h b/libcdi/src/gribapi.h
index 7d3bf13..4dc3e9d 100644
--- a/libcdi/src/gribapi.h
+++ b/libcdi/src/gribapi.h
@@ -42,7 +42,7 @@
 #define  GRIB2_GTYPE_GME                 100  /*  hexagonal GME grid                                   */
 #define  GRIB2_GTYPE_UNSTRUCTURED        101  /*  General Unstructured Grid                            */
 
-const char *gribapiLibraryVersion(void);
+const char *gribapiLibraryVersionString(void);
 void gribContainersNew(stream_t * streamptr);
 void gribContainersDelete(stream_t * streamptr);
 void *gribHandleNew(int editionNumber);
diff --git a/libcdi/src/grid.c b/libcdi/src/grid.c
index c88b8c9..dd9658e 100644
--- a/libcdi/src/grid.c
+++ b/libcdi/src/grid.c
@@ -65,7 +65,6 @@ static const resOps gridOps = {
   gridTxCode
 };
 
-
 static int  GRID_Debug = 0;   /* If set to 1, debugging */
 
 
@@ -212,7 +211,7 @@ int gridSize(void)
   return reshCountType ( &gridOps );
 }
 
-
+// used also in CDO
 void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
 {
   if ( (! (fabs(xinc) > 0)) && xsize > 1 )
@@ -235,32 +234,28 @@ void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *x
 static
 void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
 {
-  long yhsize;
-
-  double *yw = (double *)xmalloc(ysize*sizeof(double));
-  gaussaw(yvals, yw, ysize);
+  double *yw = (double *)xmalloc((size_t)ysize * sizeof(double));
+  gaussaw(yvals, yw, (size_t)ysize);
   free(yw);
-  for (long i = 0; i < ysize; i++ )
+  for (int i = 0; i < ysize; i++ )
     yvals[i] = asin(yvals[i])/M_PI*180.0;
 
   if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
     {
-      double ytmp;
-      yhsize = ysize/2;
-      for (long i = 0; i < yhsize; i++ )
+      int yhsize = ysize/2;
+      for (int i = 0; i < yhsize; i++ )
         {
-          ytmp = yvals[i];
+          double ytmp = yvals[i];
           yvals[i] = yvals[ysize-i-1];
           yvals[ysize-i-1] = ytmp;
         }
     }
 }
 
-
+// used also in CDO
 void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals)
 {
-  long i;
-  double deleps = 0.002;
+  const double deleps = 0.002;
 
   if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -279,8 +274,9 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 		/* printf("%g %g %g %g %g %d\n", ylast, yfirst, ylast-yfirst,yinc, 180/yinc, ny); */
 		if ( ny > ysize && ny < 4096 )
 		  {
-		    ytmp = (double *) malloc(ny*sizeof(double));
+		    ytmp = (double *)xmalloc((size_t)ny * sizeof (double));
 		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
+                    int i;
 		    for ( i = 0; i < (ny-ysize); i++ )
 		      if ( fabs(ytmp[i] - yfirst) < deleps ) break;
 
@@ -292,12 +288,12 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 
 		if ( lfound )
 		  {
-		    for ( i = 0; i < ysize; i++ ) yvals[i] = ytmp[i+nstart];
+		    for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
 		  }
 		else
 		  {
 		    Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
-		    for ( i = 0; i < ysize; i++ ) yvals[i] = 0;
+		    for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
 		    yvals[0] = yfirst;
 		    yvals[ysize-1] = ylast;
 		  }
@@ -339,7 +335,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 
       if ( yfirst > ylast && yinc > 0 ) yinc = -yinc;
 
-      for ( i = 0; i < ysize; i++ )
+      for (int i = 0; i < ysize; i++ )
         yvals[i] = yfirst + i*yinc;
     }
   /*
@@ -390,19 +386,16 @@ gridDefYvals(gridID, lats);
 */
 int gridCreate(int gridtype, int size)
 {
-  int gridID;
-  grid_t *gridptr;
-
   if ( CDI_Debug ) Message("gridtype=%s  size=%d", gridNamePtr(gridtype), size);
 
   if ( size < 0 || size > INT_MAX ) Error("Grid size (%d) out of bounds (0 - %d)!", size, INT_MAX);
 
   gridInit();
 
-  gridptr = gridNewEntry(CDI_UNDEFID);
+  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
   if ( ! gridptr ) Error("No memory");
 
-  gridID = gridptr->self;
+  int gridID = gridptr->self;
 
   if ( CDI_Debug ) Message("gridID: %d", gridID);
 
@@ -529,9 +522,7 @@ void gridDestroyKernel( grid_t * gridptr )
 */
 void gridDestroy(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   gridDestroyKernel ( gridptr );
 }
@@ -577,20 +568,15 @@ The function @func{gridDefXname} defines the name of a X-axis.
 */
 void gridDefXname(int gridID, const char *xname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( xname )
-    strcpy(gridptr->xname, xname);
+    {
+      strcpy(gridptr->xname, xname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -609,18 +595,14 @@ The function @func{gridDefXlongname} defines the longname of a X-axis.
 */
 void gridDefXlongname(int gridID, const char *xlongname)
 {
-  grid_t *gridptr;
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
+  grid_check_ptr(gridID, gridptr);
 
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
+  if ( xlongname )
     {
-      Warning ("%s", "Operation not executed." );
-      return;
+      strcpy(gridptr->xlongname, xlongname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
-
-  if ( xlongname )
-    strcpy(gridptr->xlongname, xlongname);
 }
 
 /*
@@ -639,20 +621,15 @@ The function @func{gridDefXunits} defines the units of a X-axis.
 */
 void gridDefXunits(int gridID, const char *xunits)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( xunits )
-    strcpy(gridptr->xunits, xunits);
+    {
+      strcpy(gridptr->xunits, xunits);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -671,20 +648,15 @@ The function @func{gridDefYname} defines the name of a Y-axis.
 */
 void gridDefYname(int gridID, const char *yname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( yname )
-    strcpy(gridptr->yname, yname);
+    {
+      strcpy(gridptr->yname, yname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -703,20 +675,15 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis.
 */
 void gridDefYlongname(int gridID, const char *ylongname)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
   if ( ylongname )
-    strcpy(gridptr->ylongname, ylongname);
+    {
+      strcpy(gridptr->ylongname, ylongname);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -735,20 +702,15 @@ The function @func{gridDefYunits} defines the units of a Y-axis.
 */
 void gridDefYunits(int gridID, const char *yunits)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( yunits )
-    strcpy(gridptr->yunits, yunits);
+    {
+      strcpy(gridptr->yunits, yunits);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -772,9 +734,7 @@ The function @func{gridInqXname} returns the name of a X-axis.
 */
 void gridInqXname(int gridID, char *xname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -802,9 +762,7 @@ The function @func{gridInqXlongname} returns the longname of a X-axis.
 */
 void gridInqXlongname(int gridID, char *xlongname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -832,9 +790,7 @@ The function @func{gridInqXunits} returns the units of a X-axis.
 */
 void gridInqXunits(int gridID, char *xunits)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -844,9 +800,7 @@ void gridInqXunits(int gridID, char *xunits)
 
 void gridInqXstdname(int gridID, char *xstdname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -874,9 +828,7 @@ The function @func{gridInqYname} returns the name of a Y-axis.
 */
 void gridInqYname(int gridID, char *yname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -904,9 +856,7 @@ The function @func{gridInqYlongname} returns the longname of a Y-axis.
 */
 void gridInqYlongname(int gridID, char *ylongname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -934,9 +884,7 @@ The function @func{gridInqYunits} returns the units of a Y-axis.
 */
 void gridInqYunits(int gridID, char *yunits)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -945,9 +893,7 @@ void gridInqYunits(int gridID, char *yunits)
 
 void gridInqYstdname(int gridID, char *ystdname)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -976,9 +922,7 @@ The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
 */
 int gridInqType(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1004,14 +948,11 @@ The function @func{gridInqSize} returns the size of a Grid.
 */
 int gridInqSize(int gridID)
 {
-  int size = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  int size = gridptr->size;
 
   if ( ! size )
     {
@@ -1050,9 +991,7 @@ int nsp2trunc(int nsp)
 
 int gridInqTrunc(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1072,19 +1011,15 @@ int gridInqTrunc(int gridID)
 
 void gridDefTrunc(int gridID, int trunc)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->trunc = trunc;
+  if (gridptr->trunc != trunc)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->trunc = trunc;
+    }
 }
 
 /*
@@ -1103,15 +1038,7 @@ The function @func{gridDefXsize} defines the number of values of a X-axis.
 */
 void gridDefXsize(int gridID, int xsize)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1121,7 +1048,11 @@ void gridDefXsize(int gridID, int xsize)
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED && xsize != gridInqSize(gridID) )
     Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridInqSize(gridID));
 
-  gridptr->xsize = xsize;
+  if (gridptr->xsize != xsize)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->xsize = xsize;
+    }
 
   if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
     {
@@ -1144,19 +1075,15 @@ void gridDefXsize(int gridID, int xsize)
 */
 void gridDefPrec(int gridID, int prec)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->prec = prec;
+  if (gridptr->prec != prec)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->prec = prec;
+    }
 }
 
 /*
@@ -1171,9 +1098,7 @@ void gridDefPrec(int gridID, int prec)
 */
 int gridInqPrec(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1198,9 +1123,7 @@ The function @func{gridInqXsize} returns the number of values of a X-axis.
 */
 int gridInqXsize(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1223,15 +1146,7 @@ The function @func{gridDefYsize} defines the number of values of a Y-axis.
 */
 void gridDefYsize(int gridID, int ysize)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1241,7 +1156,11 @@ void gridDefYsize(int gridID, int ysize)
   if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ysize != gridInqSize(gridID) )
     Error("ysize %d must be equal gridsize %d for gridtype: UNSTRUCTURED", ysize, gridInqSize(gridID));
 
-  gridptr->ysize = ysize;
+  if (gridptr->ysize != ysize)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->ysize = ysize;
+    }
 
   if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
     {
@@ -1270,9 +1189,7 @@ The function @func{gridInqYsize} returns the number of values of a Y-axis.
 */
 int gridInqYsize(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1296,19 +1213,15 @@ of a Gaussian grid.
 */
 void gridDefNP(int gridID, int np)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed." );
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->np = np;
+  if (gridptr->np != np)
+    {
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+      gridptr->np = np;
+    }
 }
 
 /*
@@ -1330,9 +1243,7 @@ of a Gaussian grid.
 */
 int gridInqNP(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1351,22 +1262,14 @@ int gridInqNP(int gridID)
 */
 void gridDefRowlon(int gridID, int nrowlon, const int *rowlon)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->rowlon = (int *) malloc(nrowlon*sizeof(int));
+  gridptr->rowlon = (int *)xmalloc((size_t)nrowlon * sizeof(int));
   gridptr->nrowlon = nrowlon;
-
-  memcpy(gridptr->rowlon, rowlon, nrowlon*sizeof(int));
+  memcpy(gridptr->rowlon, rowlon, (size_t)nrowlon * sizeof(int));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -1381,35 +1284,30 @@ void gridDefRowlon(int gridID, int nrowlon, const int *rowlon)
 */
 void gridInqRowlon(int gridID, int *rowlon)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( gridptr->rowlon == 0 )  Error("undefined pointer!");
 
-  memcpy(rowlon, gridptr->rowlon, gridptr->nrowlon*sizeof(int));
+  memcpy(rowlon, gridptr->rowlon, (size_t)gridptr->nrowlon * sizeof(int));
 }
 
 
 int gridInqMask(int gridID, int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( CDI_Debug && size == 0 )
     Warning("Size undefined for gridID = %d", gridID);
 
-  if ( mask && gridptr->mask )
-    for ( i = 0; i < size; ++i )
-      mask[i] = gridptr->mask[i];
+  if (mask && gridptr->mask)
+    for (long i = 0; i < size; ++i)
+      mask[i] = (int)gridptr->mask[i];
 
   if ( gridptr->mask == NULL ) size = 0;
 
@@ -1419,18 +1317,9 @@ int gridInqMask(int gridID, int *mask)
 
 void gridDefMask(int gridID, const int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d", gridID);
@@ -1446,33 +1335,30 @@ void gridDefMask(int gridID, const int *mask)
   else
     {
       if ( gridptr->mask == NULL )
-	gridptr->mask = (mask_t *) malloc(size*sizeof(mask_t));
+	gridptr->mask = (mask_t *)xmalloc((size_t)size*sizeof(mask_t));
       else if ( CDI_Debug )
 	Warning("grid mask already defined!");
 
-      for ( i = 0; i < size; ++i )
-	gridptr->mask[i] = mask[i];
+      for (long i = 0; i < size; ++i )
+	gridptr->mask[i] = (mask_t)(mask[i] != 0);
     }
 }
 
 
 int gridInqMaskGME(int gridID, int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( CDI_Debug && size == 0 )
     Warning("Size undefined for gridID = %d", gridID);
 
   if ( mask && gridptr->mask_gme )
-    for ( i = 0; i < size; ++i )
-      mask[i] = gridptr->mask_gme[i];
+    for (long i = 0; i < size; ++i)
+      mask[i] = (int)gridptr->mask_gme[i];
 
   if ( gridptr->mask_gme == NULL ) size = 0;
 
@@ -1482,31 +1368,22 @@ int gridInqMaskGME(int gridID, int *mask)
 
 void gridDefMaskGME(int gridID, const int *mask)
 {
-  long size, i;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  long size = gridptr->size;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d", gridID);
 
   if ( gridptr->mask_gme == NULL )
-    gridptr->mask_gme = (mask_t *) malloc(size*sizeof(mask_t));
+    gridptr->mask_gme = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
   else if ( CDI_Debug )
     Warning("mask already defined!");
 
-  for ( i = 0; i < size; ++i )
-    gridptr->mask_gme[i] = mask[i];
+  for (long i = 0; i < size; ++i)
+    gridptr->mask_gme[i] = (mask_t)(mask[i] != 0);
 }
 
 /*
@@ -1531,13 +1408,11 @@ Otherwise, 0 is returned and @func{xvals} is empty.
 */
 int gridInqXvals(int gridID, double *xvals)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
+  long size;
   if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
     size = gridptr->size;
   else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
@@ -1549,7 +1424,7 @@ int gridInqXvals(int gridID, double *xvals)
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && xvals && gridptr->xvals )
-    memcpy(xvals, gridptr->xvals, size*sizeof(double));
+    memcpy(xvals, gridptr->xvals, (size_t)size * sizeof (double));
 
   if ( gridptr->xvals == NULL ) size = 0;
 
@@ -1572,20 +1447,13 @@ The function @func{gridDefXvals} defines all values of the X-axis.
 */
 void gridDefXvals(int gridID, const double *xvals)
 {
-  int gridtype;
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
+  int gridtype;
+  long size;
+
   gridtype = gridptr->type;
 
   if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
@@ -1600,8 +1468,10 @@ void gridDefXvals(int gridID, const double *xvals)
 
   if (gridptr->xvals && CDI_Debug)
     Warning("values already defined!");
-  gridptr->xvals = (double *)xrealloc(gridptr->xvals, size * sizeof(double));
-  memcpy(gridptr->xvals, xvals, size*sizeof(double));
+  gridptr->xvals = (double *)xrealloc(gridptr->xvals,
+                                      (size_t)size * sizeof(double));
+  memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -1626,23 +1496,20 @@ Otherwise, 0 is returned and @func{yvals} is empty.
 */
 int gridInqYvals(int gridID, double *yvals)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = gridptr->size;
-  else
-    size = gridptr->ysize;
+  int gridtype = gridptr->type;
+  long size
+    = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+    ? gridptr->size : gridptr->ysize;
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d!", gridID);
 
   if ( size && yvals && gridptr->yvals )
-    memcpy(yvals, gridptr->yvals, size*sizeof(double));
+    memcpy(yvals, gridptr->yvals, (size_t)size * sizeof (double));
 
   if ( gridptr->yvals == NULL ) size = 0;
 
@@ -1665,26 +1532,14 @@ The function @func{gridDefYvals} defines all values of the Y-axis.
 */
 void gridDefYvals(int gridID, const double *yvals)
 {
-  int gridtype;
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridptr->type;
-
-  if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
-    size = gridptr->size;
-  else
-    size = gridptr->ysize;
+  int gridtype = gridptr->type;
+  long size
+    = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+    ? gridptr->size : gridptr->ysize;
 
   if ( size == 0 )
     Error("Size undefined for gridID = %d!", gridID);
@@ -1692,17 +1547,16 @@ void gridDefYvals(int gridID, const double *yvals)
   if (gridptr->yvals && CDI_Debug)
     Warning("Values already defined!");
 
-  gridptr->yvals = (double *)xrealloc(gridptr->yvals, size*sizeof(double));
-  memcpy(gridptr->yvals, yvals, size*sizeof(double));
+  gridptr->yvals = (double *)xrealloc(gridptr->yvals, (size_t)size * sizeof (double));
+  memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 
 double gridInqXval(int gridID, int index)
 {
   double xval = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1725,9 +1579,7 @@ double gridInqXval(int gridID, int index)
 double gridInqYval(int gridID, int index)
 {
   double yval = 0;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1757,17 +1609,13 @@ double gridInqXinc(int gridID)
 
   if ( (! (fabs(xinc) > 0)) && gridptr->xvals )
     {
-      int xsize;
-      double *xvals;
-
-      xsize = gridptr->xsize;
-      xvals = gridptr->xvals;
-
+      int xsize = gridptr->xsize;
       if ( xsize > 1 )
         {
-          long i;
+          double *xvals = gridptr->xvals;
           xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
-          for ( i = 2; i < xsize; i++ )
+          int i;
+          for (i = 2; i < xsize; i++ )
             if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc ) break;
 
           if ( i < xsize ) xinc = 0;
@@ -1805,8 +1653,8 @@ double gridInqYinc(int gridID)
 
       if ( ysize > 1 )
         {
-          long i;
           yinc = fabs(yvals[1] - yvals[0]);
+          int i;
           for ( i = 2; i < ysize; i++ )
             if ( fabs(fabs(yvals[i] - yvals[i-1]) - yinc) > (yinc/1000) ) break;
 
@@ -1830,9 +1678,7 @@ double gridInqYinc(int gridID)
 */
 double gridInqXpole(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1851,23 +1697,19 @@ double gridInqXpole(int gridID)
 */
 void gridDefXpole(int gridID, double xpole)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( memcmp(gridptr->xstdname, "grid", 4) != 0 )
     strcpy(gridptr->xstdname, "grid_longitude");
 
-  gridptr->isRotated = TRUE;
-  gridptr->xpole = xpole;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->xpole = xpole;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -1882,9 +1724,7 @@ void gridDefXpole(int gridID, double xpole)
 */
 double gridInqYpole(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1903,23 +1743,19 @@ double gridInqYpole(int gridID)
 */
 void gridDefYpole(int gridID, double ypole)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   if ( memcmp(gridptr->ystdname, "grid", 4) != 0 )
     strcpy(gridptr->ystdname, "grid_latitude");
 
-  gridptr->isRotated = TRUE;
-  gridptr->ypole = ypole;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->ypole = ypole;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -1934,9 +1770,7 @@ void gridDefYpole(int gridID, double ypole)
 */
 double gridInqAngle(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -1955,20 +1789,16 @@ double gridInqAngle(int gridID)
 */
 void gridDefAngle(int gridID, double angle)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->isRotated = TRUE;
-  gridptr->angle = angle;
+  if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->angle, angle) )
+    {
+      gridptr->isRotated = TRUE;
+      gridptr->angle = angle;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -1983,9 +1813,7 @@ void gridDefAngle(int gridID, double angle)
 */
 int gridInqGMEnd(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2004,19 +1832,15 @@ int gridInqGMEnd(int gridID)
 */
 void gridDefGMEnd(int gridID, int nd)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->nd = nd;
+  if (gridptr->nd != nd)
+    {
+      gridptr->nd = nd;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -2031,9 +1855,7 @@ void gridDefGMEnd(int gridID, int nd)
 */
 int gridInqGMEni(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2052,19 +1874,15 @@ int gridInqGMEni(int gridID)
 */
 void gridDefGMEni(int gridID, int ni)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni = ni;
+  if (gridptr->ni != ni)
+    {
+      gridptr->ni = ni;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -2079,9 +1897,7 @@ void gridDefGMEni(int gridID, int ni)
 */
 int gridInqGMEni2(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2100,18 +1916,15 @@ int gridInqGMEni2(int gridID)
 */
 void gridDefGMEni2(int gridID, int ni2)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni2 = ni2;
+  if (gridptr->ni2 != ni2)
+    {
+      gridptr->ni2 = ni2;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -2126,9 +1939,7 @@ void gridDefGMEni2(int gridID, int ni2)
 */
 int gridInqGMEni3(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2137,19 +1948,15 @@ int gridInqGMEni3(int gridID)
 
 void gridDefGMEni3(int gridID, int ni3)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->ni3 = ni3;
+  if (gridptr->ni3 != ni3)
+    {
+      gridptr->ni3 = ni3;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -2164,16 +1971,18 @@ void gridDefGMEni3(int gridID, int ni3)
 */
 void gridChangeType(int gridID, int gridtype)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( CDI_Debug ) 
+  if ( CDI_Debug )
     Message("Changed grid type from %s to %s", gridNamePtr(gridptr->type), gridNamePtr(gridtype));
 
-  gridptr->type = gridtype;
+  if (gridptr->type != gridtype)
+    {
+      gridptr->type = gridtype;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 static
@@ -2282,9 +2091,7 @@ void grid_check_cyclic(grid_t *gridptr)
 
 int gridIsCircular(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2296,9 +2103,7 @@ int gridIsCircular(int gridID)
 
 int gridIsRotated(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2313,9 +2118,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 
   if ( !differ && xsize == gridInqXvals(gridID, NULL) )
     {
-      double *xvals;
-
-      xvals = (double *) malloc(xsize*sizeof(double));
+      double *xvals = (double *)xmalloc((size_t)xsize * sizeof (double));
 
       gridInqXvals(gridID, xvals);
 
@@ -2331,9 +2134,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 
   if ( !differ && ysize == gridInqYvals(gridID, NULL) )
     {
-      double *yvals;
-
-      yvals = (double *) malloc(ysize*sizeof(double));
+      double *yvals = (double *)xmalloc((size_t)ysize * sizeof (double));
 
       gridInqYvals(gridID, yvals);
 
@@ -2351,7 +2152,7 @@ int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yv
 }
 
 static
-int compareXYvals2(int gridID, long gridsize, double *xvals, double *yvals)
+int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
 {
   int differ = 0;
 
@@ -2461,8 +2262,8 @@ int gridCompare(int gridID, grid_t grid)
 		    {
 		      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.001 ||
-			     fabs(grid.yfirst - gridInqYval(gridID, 0)) > 0.001 ||
+			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(gridInqXinc(gridID))) > fabs(grid.xinc/1000)) )
 			  {
 			    differ = 1;
@@ -2501,12 +2302,21 @@ int gridCompare(int gridID, grid_t grid)
 	    {
               char uuidOfHGrid[17];
               gridInqUUID(gridID, uuidOfHGrid);
-
+              /*
+              printf("compare unstructured grids\n");
+	      printf("gridID        %d\n", gridID);
+	      printf("gridsize      %d\n", grid.size);
+              if ( uuidOfHGrid[0] != 0 && grid.uuid[0] != 0 && memcmp(grid.uuid, uuidOfHGrid, 16) )
+                printf("uuidOfHGrid     differ\n");
+              printf("nvertex      %d  %d\n", grid.nvertex, gridInqNvertex(gridID));
+              printf("number       %d  %d\n", grid.number, gridInqNumber(gridID));
+              printf("position     %d  %d\n", grid.position, gridInqPosition(gridID));
+              */
               if ( uuidOfHGrid[0] != 0 && grid.uuid[0] != 0 )
                 if ( !differ && memcmp(uuidOfHGrid, grid.uuid, 16) != 0 ) differ = 1;
               if ( !differ && grid.nvertex != gridInqNvertex(gridID) ) differ = 1;
               if ( !differ && grid.number != gridInqNumber(gridID) ) differ = 1;
-              if ( !differ && grid.position != gridInqPosition(gridID) ) differ = 1;
+              if ( !differ && grid.number > 0 && grid.position != gridInqPosition(gridID) ) differ = 1;
 	      if ( !differ )
 		differ = compareXYvals2(gridID, grid.size, grid.xvals, grid.yvals);
 	    }
@@ -2677,8 +2487,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
   if ( g1->reference )
     {
       if ( !g2->reference ) return differ;
-      size = strlen ( g1->reference ) + 1;
-      if ( memcmp ( g1->reference, g2->reference, size ) ) return differ;
+      if ( strcmp(g1->reference, g2->reference) ) return differ;
     }
   else if ( g2->reference )
     return differ;
@@ -2687,7 +2496,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
     {
       xassert ( g1->size );
       if ( !g2->mask ) return differ;
-      if ( memcmp ( g1->mask, g2->mask, g1->size*sizeof(unsigned char)) ) return differ;
+      if ( memcmp ( g1->mask, g2->mask, (size_t)g1->size * sizeof(mask_t)) ) return differ;
     }
   else if ( g2->mask )
     return differ;
@@ -2696,7 +2505,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
     {
       xassert ( g1->size );
       if ( !g2->mask_gme ) return differ;
-      if ( memcmp ( g1->mask_gme, g2->mask_gme, g1->size*sizeof(unsigned char)) ) return differ;
+      if ( memcmp ( g1->mask_gme, g2->mask_gme, (size_t)g1->size * sizeof(mask_t)) ) return differ;
     }
   else if ( g2->mask_gme )
     return differ;
@@ -2707,12 +2516,9 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
 
 int gridGenerate(grid_t grid)
 {
-  int gridID;
-  grid_t *gridptr;
+  int gridID = gridCreate(grid.type, grid.size);
 
-  gridID = gridCreate(grid.type, grid.size);
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -2747,7 +2553,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.xdef == 2 )
 	  {
-	    double *xvals = (double *) malloc(grid.xsize*sizeof(double));
+	    double *xvals
+              = (double *)xmalloc((size_t)grid.xsize * sizeof (double));
 	    gridGenXvals(grid.xsize, grid.xfirst, grid.xlast, grid.xinc, xvals);
 	    gridDefXvals(gridID, xvals);
 	    free(xvals);
@@ -2764,7 +2571,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.ydef == 2 )
 	  {
-	    double *yvals = (double *) malloc(grid.ysize*sizeof(double));
+	    double *yvals
+              = (double *)xmalloc((size_t)grid.ysize * sizeof (double));
 	    gridGenYvals(grid.type, grid.ysize, grid.yfirst, grid.ylast, grid.yinc, yvals);
 	    gridDefYvals(gridID, yvals);
 	    free(yvals);
@@ -2848,7 +2656,8 @@ int gridGenerate(grid_t grid)
 	  }
 	else if ( grid.ydef == 2 )
 	  {
-	    double *yvals = (double *) malloc(grid.ysize*sizeof(double));
+	    double *yvals
+              = (double *)xmalloc((size_t)grid.ysize * sizeof (double));
 	    gridGenYvals(grid.type, grid.ysize, grid.yfirst, grid.ylast, grid.yinc, yvals);
 	    gridDefYvals(gridID, yvals);
 	    free(yvals);
@@ -2931,21 +2740,15 @@ The function @func{gridDuplicate} duplicates a horizontal Grid.
 */
 int gridDuplicate(int gridID)
 {
-  int gridIDnew;
-  int gridtype, gridsize;
-  int nrowlon;
-  int size;
-  grid_t *gridptr, *gridptrnew;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridInqType(gridID);
-  gridsize = gridInqSize(gridID);
+  int gridtype = gridInqType(gridID);
+  int gridsize = gridInqSize(gridID);
 
-  gridIDnew = gridCreate(gridtype, gridsize);
-  gridptrnew = ( grid_t *) reshGetVal ( gridIDnew, &gridOps );
+  int gridIDnew = gridCreate(gridtype, gridsize);
+  grid_t *gridptrnew = reshGetVal(gridIDnew, &gridOps);
 
   grid_copy(gridptrnew, gridptr);
 
@@ -2958,85 +2761,73 @@ int gridDuplicate(int gridID)
   strcpy(gridptrnew->xstdname, gridptr->xstdname);
   strcpy(gridptrnew->ystdname, gridptr->ystdname);
 
-  if ( gridptr->reference )  gridptrnew->reference = strdupx(gridptr->reference);
+  if (gridptr->reference)
+    gridptrnew->reference = strdupx(gridptr->reference);
 
-  nrowlon = gridptr->nrowlon;
+  size_t nrowlon = (size_t)gridptr->nrowlon;
+  int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
   if ( nrowlon )
     {
-      gridptrnew->rowlon = (int *) malloc(nrowlon*sizeof(int));
-      memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon*sizeof(int));
+      gridptrnew->rowlon = (int *)xmalloc(nrowlon * sizeof (int));
+      memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon * sizeof(int));
     }
 
   if ( gridptr->xvals != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->xsize;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->xsize);
 
-      gridptrnew->xvals = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->xvals, gridptr->xvals, size*sizeof(double));
+      gridptrnew->xvals = (double *)xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->xvals, gridptr->xvals, size * sizeof (double));
     }
 
   if ( gridptr->yvals != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->ysize;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->ysize);
 
-      gridptrnew->yvals = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->yvals, gridptr->yvals, size*sizeof(double));
+      gridptrnew->yvals = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->yvals, gridptr->yvals, size * sizeof (double));
     }
 
   if ( gridptr->xbounds != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->xsize;
-
-      size *= gridptr->nvertex;
+      size_t size  = (size_t)(irregular ? gridsize : gridptr->xsize)
+        * (size_t)gridptr->nvertex;
 
-      gridptrnew->xbounds = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->xbounds, gridptr->xbounds, size*sizeof(double));
+      gridptrnew->xbounds = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->xbounds, gridptr->xbounds, size * sizeof (double));
     }
 
   if ( gridptr->ybounds != NULL )
     {
-      if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
-	size = gridsize;
-      else
-        size = gridptr->ysize;
-
-      size *= gridptr->nvertex;
+      size_t size = (size_t)(irregular ? gridsize : gridptr->ysize)
+        * (size_t)gridptr->nvertex;
 
-      gridptrnew->ybounds = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->ybounds, gridptr->ybounds, size*sizeof(double));
+      gridptrnew->ybounds = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->ybounds, gridptr->ybounds, size * sizeof (double));
     }
 
   if ( gridptr->area != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->area = (double *) malloc(size*sizeof(double));
-      memcpy(gridptrnew->area, gridptr->area, size*sizeof(double));
+      gridptrnew->area = xmalloc(size * sizeof (double));
+      memcpy(gridptrnew->area, gridptr->area, size * sizeof (double));
     }
 
   if ( gridptr->mask != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->mask = (mask_t *) malloc(size*sizeof(mask_t));
-      memcpy(gridptrnew->mask, gridptr->mask, size*sizeof(mask_t));
+      gridptrnew->mask = xmalloc(size * sizeof(mask_t));
+      memcpy(gridptrnew->mask, gridptr->mask, size * sizeof (mask_t));
     }
 
   if ( gridptr->mask_gme != NULL )
     {
-      size = gridsize;
+      size_t size = (size_t)gridsize;
 
-      gridptrnew->mask_gme = (mask_t *) malloc(size*sizeof(mask_t));
-      memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size*sizeof(mask_t));
+      gridptrnew->mask_gme = xmalloc(size * sizeof (mask_t));
+      memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size * sizeof(mask_t));
     }
 
   return (gridIDnew);
@@ -3045,38 +2836,38 @@ int gridDuplicate(int gridID)
 
 void gridCompress(int gridID)
 {
-  int gridtype, gridsize;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridtype = gridInqType(gridID);
-  gridsize = gridInqSize(gridID);
-
+  int gridtype = gridInqType(gridID);
   if ( gridtype == GRID_UNSTRUCTURED )
     {
       if ( gridptr->mask_gme != NULL )
 	{
-	  long i, j, iv, nv;
-
-	  nv = gridptr->nvertex;
-
-	  j = 0;
-	  for ( i = 0; i < gridsize; i++ )
+          size_t gridsize = (size_t)gridInqSize(gridID);
+	  size_t nv = (size_t)gridptr->nvertex;
+
+	  size_t j = 0;
+          double *area = gridptr->area,
+            *xvals = gridptr->xvals,
+            *yvals = gridptr->yvals,
+            *xbounds = gridptr->xbounds,
+            *ybounds = gridptr->ybounds;
+          mask_t *mask_gme = gridptr->mask_gme;
+	  for (size_t i = 0; i < gridsize; i++ )
 	    {
-	      if ( gridptr->mask_gme[i] )
+	      if (mask_gme[i])
 		{
-		  if ( gridptr->xvals != NULL ) gridptr->xvals[j] = gridptr->xvals[i];
-		  if ( gridptr->yvals != NULL ) gridptr->yvals[j] = gridptr->yvals[i];
-		  if ( gridptr->area  != NULL ) gridptr->area[j]  = gridptr->area[i];
-		  if ( gridptr->xbounds != NULL )
-		    for ( iv = 0; iv < nv; iv++ )
-		      gridptr->xbounds[j*nv+iv] = gridptr->xbounds[i*nv+iv];
-		  if ( gridptr->ybounds != NULL )
-		    for ( iv = 0; iv < nv; iv++ )
-		      gridptr->ybounds[j*nv+iv] = gridptr->ybounds[i*nv+iv];
+		  if (xvals) xvals[j] = xvals[i];
+		  if (yvals) yvals[j] = yvals[i];
+		  if (area) area[j]  = area[i];
+		  if (xbounds != NULL)
+		    for (size_t iv = 0; iv < nv; iv++)
+		      xbounds[j * nv + iv] = xbounds[i * nv + iv];
+		  if (ybounds != NULL)
+		    for (size_t iv = 0; iv < nv; iv++)
+		      ybounds[j * nv + iv] = ybounds[i * nv + iv];
 
 		  j++;
 		}
@@ -3084,27 +2875,28 @@ void gridCompress(int gridID)
 
 	  /* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */
 	  gridsize = j;
-	  gridptr->size  = gridsize;
-	  gridptr->xsize = gridsize;
-	  gridptr->ysize = gridsize;
+	  gridptr->size  = (int)gridsize;
+	  gridptr->xsize = (int)gridsize;
+	  gridptr->ysize = (int)gridsize;
 
 	  if ( gridptr->xvals )
-	    gridptr->xvals = (double *) realloc(gridptr->xvals, gridsize*sizeof(double));
+	    gridptr->xvals = (double *)xrealloc(gridptr->xvals, gridsize*sizeof(double));
 
 	  if ( gridptr->yvals )
-	    gridptr->yvals = (double *) realloc(gridptr->yvals, gridsize*sizeof(double));
+	    gridptr->yvals = (double *)xrealloc(gridptr->yvals, gridsize*sizeof(double));
 
 	  if ( gridptr->area )
-	    gridptr->area  = (double *) realloc(gridptr->area, gridsize*sizeof(double));
+	    gridptr->area  = (double *)xrealloc(gridptr->area, gridsize*sizeof(double));
 
 	  if ( gridptr->xbounds )
-	    gridptr->xbounds = (double *) realloc(gridptr->xbounds, nv*gridsize*sizeof(double));
+	    gridptr->xbounds = (double *)xrealloc(gridptr->xbounds, nv*gridsize*sizeof(double));
 
 	  if ( gridptr->ybounds )
-	    gridptr->ybounds = (double *) realloc(gridptr->ybounds, nv*gridsize*sizeof(double));
+	    gridptr->ybounds = (double *)xrealloc(gridptr->ybounds, nv*gridsize*sizeof(double));
 
 	  free(gridptr->mask_gme);
 	  gridptr->mask_gme = NULL;
+          reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 	}
     }
   else
@@ -3114,59 +2906,43 @@ void gridCompress(int gridID)
 
 void gridDefArea(int gridID, const double *area)
 {
-  long size;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
+  size_t size = gridptr->size;
 
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
   if ( gridptr->area == NULL )
-    gridptr->area = (double *) malloc(size*sizeof(double));
+    gridptr->area = (double *)xmalloc(size*sizeof(double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->area, area, size*sizeof(double));
+  memcpy(gridptr->area, area, size * sizeof(double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 
 void gridInqArea(int gridID, double *area)
 {
-  long size;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  size = gridptr->size;
-
-  if ( gridptr->area )
-    memcpy(area, gridptr->area, size*sizeof(double));
+  if (gridptr->area)
+    memcpy(area, gridptr->area, (size_t)gridptr->size * sizeof (double));
 }
 
 
 int gridHasArea(int gridID)
 {
-  int hasArea = FALSE;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  if ( gridptr->area != NULL ) hasArea = TRUE;
+  int hasArea = (gridptr->area != NULL);
 
   return (hasArea);
 }
@@ -3174,9 +2950,7 @@ int gridHasArea(int gridID)
 
 const double *gridInqAreaPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3186,27 +2960,21 @@ const double *gridInqAreaPtr(int gridID)
 
 void gridDefNvertex(int gridID, int nvertex)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->nvertex = nvertex;
+  if (gridptr->nvertex != nvertex)
+    {
+      gridptr->nvertex = nvertex;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int gridInqNvertex(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3229,41 +2997,31 @@ The function @func{gridDefXbounds} defines all bounds of the X-axis.
 */
 void gridDefXbounds(int gridID, const double *xbounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning ("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( nvertex == 0 )
     {
       Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
       return;
     }
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->xsize;
-
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex
+    * (size_t)(irregular ? gridptr->size : gridptr->xsize);
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
-  if ( gridptr->xbounds == NULL )
-    gridptr->xbounds = (double *) malloc(size*sizeof(double));
+  if (gridptr->xbounds == NULL)
+    gridptr->xbounds = xmalloc(size * sizeof (double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->xbounds, xbounds, size*sizeof(double));
+  memcpy(gridptr->xbounds, xbounds, size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -3288,28 +3046,23 @@ Otherwise, 0 is returned and @func{xbounds} is empty.
 */
 int gridInqXbounds(int gridID, double *xbounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( CDI_Debug && nvertex == 0 )
     Warning("nvertex undefined for gridID = %d", gridID);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->xsize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && xbounds && gridptr->xbounds )
-    memcpy(xbounds, gridptr->xbounds, size*sizeof(double));
+    memcpy(xbounds, gridptr->xbounds, size * sizeof (double));
 
   if ( gridptr->xbounds == NULL ) size = 0;
 
@@ -3319,9 +3072,7 @@ int gridInqXbounds(int gridID, double *xbounds)
 
 const double *gridInqXboundsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3344,41 +3095,31 @@ The function @func{gridDefYbounds} defines all bounds of the Y-axis.
 */
 void gridDefYbounds(int gridID, const double *ybounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( nvertex == 0 )
     {
       Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
       return;
     }
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->ysize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
 
   if ( size == 0 )
     Error("size undefined for gridID = %d", gridID);
 
   if ( gridptr->ybounds == NULL )
-    gridptr->ybounds = (double *) malloc(size*sizeof(double));
+    gridptr->ybounds = xmalloc(size * sizeof (double));
   else if ( CDI_Debug )
     Warning("values already defined!");
 
-  memcpy(gridptr->ybounds, ybounds, size*sizeof(double));
+  memcpy(gridptr->ybounds, ybounds, size * sizeof (double));
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -3403,28 +3144,23 @@ Otherwise, 0 is returned and @func{ybounds} is empty.
 */
 int gridInqYbounds(int gridID, double *ybounds)
 {
-  long size;
-  long nvertex;
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  nvertex = gridptr->nvertex;
+  size_t nvertex = (size_t)gridptr->nvertex;
   if ( CDI_Debug && nvertex == 0 )
     Warning("nvertex undefined for gridID = %d", gridID);
 
-  if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
-    size = nvertex*gridptr->size;
-  else
-    size = nvertex*gridptr->ysize;
+  int irregular = gridptr->type == GRID_CURVILINEAR
+    || gridptr->type == GRID_UNSTRUCTURED;
+  size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
 
   if ( CDI_Debug && size == 0 )
     Warning("size undefined for gridID = %d", gridID);
 
   if ( size && ybounds && gridptr->ybounds )
-    memcpy(ybounds, gridptr->ybounds, size*sizeof(double));
+    memcpy(ybounds, gridptr->ybounds, size * sizeof (double));
 
   if ( gridptr->ybounds == NULL ) size = 0;
 
@@ -3434,9 +3170,7 @@ int gridInqYbounds(int gridID, double *ybounds)
 
 const double *gridInqYboundsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3698,7 +3432,7 @@ void gridPrintKernel(grid_t * gridptr, int opt, FILE *fp)
             int *rowlon;
             nbyte0 = fprintf(fp, "rowlon    = ");
             nbyte  = nbyte0;
-            rowlon = (int *) malloc(ysize*sizeof(int));
+            rowlon = (int *)xmalloc((size_t)ysize*sizeof(int));
             gridInqRowlon(gridID, rowlon);
             for ( i = 0; i < ysize; i++ )
               {
@@ -3792,9 +3526,7 @@ void gridPrintKernel(grid_t * gridptr, int opt, FILE *fp)
 
 void gridPrint ( int gridID, int opt )
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3861,9 +3593,7 @@ void gridPrintP ( void * voidptr, FILE * fp )
 
 const double *gridInqXvalsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3873,9 +3603,7 @@ const double *gridInqXvalsPtr(int gridID)
 
 const double *gridInqYvalsPtr(int gridID)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3908,15 +3636,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
                 double lat1, double lat2, double xinc, double yinc,
                 int projflag, int scanflag)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3935,6 +3655,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
       gridptr->lcc_projflag  = projflag;
       gridptr->lcc_scanflag  = scanflag;
       gridptr->lcc_defined   = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -3964,9 +3685,7 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar
                 double *lat1, double *lat2, double *xinc, double *yinc,
                 int *projflag, int *scanflag)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -3994,15 +3713,7 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar
 
 void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, double lat_1, double lat_2)
 {
-  grid_t *gridptr;
-
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4017,15 +3728,14 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do
       gridptr->lcc2_lat_1   = lat_1;
       gridptr->lcc2_lat_2   = lat_2;
       gridptr->lcc2_defined = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0, double *lat_1, double *lat_2)
 {
-  grid_t *gridptr;
-
-  gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4049,13 +3759,7 @@ void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0,
 
 void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4068,6 +3772,7 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
       gridptr->laea_lon_0   = lon_0;
       gridptr->laea_lat_0   = lat_0;
       gridptr->laea_defined = TRUE;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -4097,17 +3802,16 @@ void gridInqLaea(int gridID, double *earth_radius, double *lon_0, double *lat_0)
 
 void gridDefComplexPacking(int gridID, int lcomplex)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->lcomplex = lcomplex;
+
+  if (gridptr->lcomplex != lcomplex)
+    {
+      gridptr->lcomplex = lcomplex;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -4123,17 +3827,15 @@ int gridInqComplexPacking(int gridID)
 
 void gridDefHasDims(int gridID, int hasdims)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->hasdims = hasdims;
+  if (gridptr->hasdims != hasdims)
+    {
+      gridptr->hasdims = hasdims;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -4162,17 +3864,15 @@ The function @func{gridDefNumber} defines the reference number for an unstructur
 */
 void gridDefNumber(int gridID, const int number)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->number = number;
+  if (gridptr->number != number)
+    {
+      gridptr->number = number;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -4192,7 +3892,7 @@ The function @func{gridInqNumber} returns the reference number to an unstructure
 */
 int gridInqNumber(int gridID)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t* gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4215,17 +3915,15 @@ The function @func{gridDefPosition} defines the position of grid in the referenc
 */
 void gridDefPosition(int gridID, int position)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
-  gridptr->position = position;
+  if (gridptr->position != position)
+    {
+      gridptr->position = position;
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -4245,7 +3943,7 @@ The function @func{gridInqPosition} returns the position of grid in the referenc
 */
 int gridInqPosition(int gridID)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4268,12 +3966,6 @@ The function @func{gridDefReference} defines the reference URI for an unstructur
 */
 void gridDefReference(int gridID, const char *reference)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
@@ -4287,6 +3979,7 @@ void gridDefReference(int gridID, const char *reference)
         }
 
       gridptr->reference = strdupx(reference);
+      reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -4339,17 +4032,12 @@ The function @func{gridDefUUID} defines the UUID for an unstructured grid.
 */
 void gridDefUUID(int gridID, const char *uuid)
 {
-  if ( reshGetStatus ( gridID, &gridOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
 
   grid_check_ptr(gridID, gridptr);
 
   memcpy(gridptr->uuid, uuid, 16);
+  reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -4369,7 +4057,7 @@ The function @func{gridInqUUID} returns the UUID to an unstructured grid.
 */
 void gridInqUUID(int gridID, char *uuid)
 {
-  grid_t* gridptr = ( grid_t *) reshGetVal ( gridID, &gridOps );
+  grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
 
   grid_check_ptr(gridID, gridptr);
 
@@ -4404,7 +4092,7 @@ enum { gridNint    = 27,
 };
 
 
-static int gridGetComponentFlags ( grid_t * gridP )
+static int gridGetComponentFlags(const grid_t * gridP)
 {
   int flags = (gridHasMaskFlag & (int)((unsigned)(gridP->mask == NULL) - 1U))
     | (gridHasGMEMaskFlag & (int)((unsigned)(gridP->mask_gme == NULL) - 1U))
@@ -4500,8 +4188,9 @@ gridGetPackSize(void * voidP, void *context)
 
   if (gridP->reference)
     {
+      size_t len = strlen(gridP->reference);
       packBuffSize += serializeGetSize(1, DATATYPE_INT, context)
-        + serializeGetSize(strlen(gridP->reference) + 1, DATATYPE_TXT, context)
+        + serializeGetSize((int)len + 1, DATATYPE_TXT, context)
         + serializeGetSize(1, DATATYPE_UINT32, context);
     }
 
@@ -4580,7 +4269,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasRowLonFlag)
     {
       xassert(gridP->nrowlon);
-      gridP->rowlon = (int*) xmalloc(gridP->nrowlon * sizeof (int));
+      gridP->rowlon = (int *)xmalloc((size_t)gridP->nrowlon * sizeof (int));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->rowlon, gridP->nrowlon , DATATYPE_INT, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4622,14 +4311,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
     gridP->angle = doubleBuffer[23];
   }
 
+  int irregular = gridP->type == GRID_UNSTRUCTURED
+    || gridP->type == GRID_CURVILINEAR;
   if (memberMask & gridHasXValsFlag)
     {
-      if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
-	size = gridP->size;
-      else
-	size = gridP->xsize;
+      size = irregular ? gridP->size : gridP->xsize;
 
-      gridP->xvals = (double*) xmalloc(size * sizeof (double));
+      gridP->xvals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->xvals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4639,12 +4327,9 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasYValsFlag)
     {
-      if ( gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR )
-	size = gridP->size;
-      else
-	size = gridP->ysize;
+      size = irregular ? gridP->size : gridP->ysize;
 
-      gridP->yvals =  (double*) xmalloc( size * sizeof (double));
+      gridP->yvals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->yvals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4654,8 +4339,9 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasAreaFlag)
     {
-      xassert((size = gridP->size));
-      gridP->area = (double*) xmalloc(size * sizeof (double));
+      size = gridP->size;
+      xassert(size);
+      gridP->area = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->area, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4665,13 +4351,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasXBoundsFlag)
     {
-      if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
-	size = gridP->nvertex * gridP->size;
-      else
-	size = gridP->nvertex * gridP->xsize;
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->xsize);
       xassert(size);
 
-      gridP->xbounds = (double*) xmalloc(size * sizeof (double));
+      gridP->xbounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->xbounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4681,13 +4364,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & gridHasYBoundsFlag)
     {
-      if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED)
-	size = gridP->nvertex * gridP->size;
-      else
-	size = gridP->nvertex * gridP->ysize;
+      size = gridP->nvertex * (irregular ? gridP->size : gridP->ysize);
       xassert(size);
 
-      gridP->ybounds = (double*) xmalloc(size * sizeof (double));
+      gridP->ybounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
 			  gridP->ybounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4716,7 +4396,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
       int referenceSize;
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       &referenceSize, 1, DATATYPE_INT, context);
-      gridP->reference = (char*) xmalloc(referenceSize);
+      gridP->reference = (char *)xmalloc((size_t)referenceSize);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->reference, referenceSize, DATATYPE_TXT, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4727,7 +4407,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasMaskFlag)
     {
       xassert((size = gridP->size));
-      gridP->mask = (mask_t*) xmalloc(size * sizeof (mask_t));
+      gridP->mask = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->mask, gridP->size, DATATYPE_UCHAR, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4738,7 +4418,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
   if (memberMask & gridHasGMEMaskFlag)
     {
       xassert((size = gridP->size));
-      gridP->mask_gme = (mask_t*) xmalloc(size * sizeof (mask_t));
+      gridP->mask_gme = (mask_t *)xmalloc((size_t)size * sizeof (mask_t));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       gridP->mask_gme, gridP->size, DATATYPE_UCHAR, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -4929,7 +4609,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
 
   if ( gridP->reference )
     {
-      size = strlen ( gridP->reference ) + 1;
+      size = (int)strlen(gridP->reference) + 1;
       serializePack(&size, 1, DATATYPE_INT,
                     packBuffer, packBufferSize, packBufferPos, context);
       serializePack(gridP->reference, size, DATATYPE_TXT,
diff --git a/libcdi/src/ieglib.c b/libcdi/src/ieglib.c
index d1c6d7e..b99bd63 100644
--- a/libcdi/src/ieglib.c
+++ b/libcdi/src/ieglib.c
@@ -13,13 +13,10 @@
 #include "error.h"
 #include "file.h"
 #include "binary.h"
+#include "stream_fcommon.h"
 #include "swap.h"
 
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
-
-
 static int initIegLib      = 0;
 static int iegDefaultDprec = 0;
 
@@ -148,10 +145,10 @@ int iegCheckFiletype(int fileID, int *swap)
   size_t sblocklen = 0;
   size_t data = 0;
   size_t dimx = 0, dimy = 0;
-  int fact = 0, found = 0;
+  size_t fact = 0;
   unsigned char buffer[1048], *pbuf;
 
-  if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
+  if ( fileRead(fileID, buffer, 4) != 4 ) return (0);
 
   blocklen  = get_UINT32(buffer);
   sblocklen = get_SUINT32(buffer);
@@ -163,7 +160,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 0;
       fact = 4;
-      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;    dimx = (size_t) get_UINT32(pbuf);
       pbuf = buffer+(37+5)*4;    dimy = (size_t) get_UINT32(pbuf);
       pbuf = buffer+blocklen+4;  data = (size_t) get_UINT32(pbuf);
@@ -172,7 +169,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 0;
       fact = 8;
-      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;    dimx = (size_t) get_UINT32(pbuf);
       pbuf = buffer+(37+5)*4;    dimy = (size_t) get_UINT32(pbuf);
       pbuf = buffer+blocklen+4;  data = (size_t) get_UINT32(pbuf);
@@ -181,7 +178,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 1;
       fact = 4;
-      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;     dimx = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+(37+5)*4;     dimy = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+sblocklen+4;  data = (size_t) get_SUINT32(pbuf);
@@ -190,7 +187,7 @@ int iegCheckFiletype(int fileID, int *swap)
     {
      *swap = 1;
       fact = 8;
-      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (found);
+      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return (0);
       pbuf = buffer+(37+4)*4;     dimx = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+(37+5)*4;     dimy = (size_t) get_SUINT32(pbuf);
       pbuf = buffer+sblocklen+4;  data = (size_t) get_SUINT32(pbuf);
@@ -198,8 +195,7 @@ int iegCheckFiletype(int fileID, int *swap)
 
   fileRewind(fileID);
 
-  if      ( data && dimx*dimy*fact == data ) found = 1;
-  else if ( data && dimx*dimy*8    == data ) found = 1;
+  int found = data && (dimx*dimy*fact == data || dimx*dimy*8 == data);
 
   if ( IEG_Debug )
     {
@@ -315,8 +311,8 @@ int iegDefData(iegrec_t *iegp, int prec, const void *data)
 
   iegp->dprec = dprec;
 
-  datasize = IEG_G_NumLon(iegp->igdb)*IEG_G_NumLat(iegp->igdb);
-  blocklen = datasize * dprec;
+  datasize = (size_t)IEG_G_NumLon(iegp->igdb) * (size_t)IEG_G_NumLat(iegp->igdb);
+  blocklen = datasize * (size_t)dprec;
 
   iegp->datasize = datasize;
 
@@ -386,7 +382,6 @@ int iegRead(int fileID, iegrec_t *iegp)
   char tmpbuffer[800], *tmpbuf = tmpbuffer;
   int dprec = 0;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -478,16 +473,17 @@ int iegRead(int fileID, iegrec_t *iegp)
       return (-1);
     }
 
-  iegp->datasize = IEG_G_NumLon(iegp->igdb)*IEG_G_NumLat(iegp->igdb);
+  iegp->datasize = (size_t)IEG_G_NumLon(iegp->igdb)
+    * (size_t)IEG_G_NumLat(iegp->igdb);
 
   if ( IEG_Debug )
     Message("datasize = %lu", iegp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = iegp->buffersize;
+  size_t buffersize = iegp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = iegp->buffer;
@@ -573,8 +569,8 @@ int iegWrite(int fileID, iegrec_t *iegp)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = iegp->igdb[4]*iegp->igdb[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)iegp->igdb[4] * (size_t)iegp->igdb[5];
+  blocklen = datasize * (size_t)dprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
diff --git a/libcdi/src/institution.c b/libcdi/src/institution.c
index 50ca01c..827811f 100644
--- a/libcdi/src/institution.c
+++ b/libcdi/src/institution.c
@@ -2,6 +2,9 @@
 #  include "config.h"
 #endif
 
+#include <assert.h>
+#include <limits.h>
+
 #include "dmemory.h"
 #include "cdi.h"
 #include "cdi_int.h"
@@ -61,26 +64,27 @@ void instituteDefaultValue ( institute_t * instituteptr )
 
 void instituteDefaultEntries ( void )
 {
-  cdiResH resH[64];
-  int i, n=0;
-
-  resH[n++]  = ECMWF   = institutDef( 98,   0, "ECMWF",     "European Centre for Medium-Range Weather Forecasts");
-  resH[n++]  = MPIMET  = institutDef( 98, 232, "MPIMET",    "Max-Planck-Institute for Meteorology");
-  resH[n++]  =           institutDef( 98, 255, "MPIMET",    "Max-Planck-Institute for Meteorology");
-  resH[n++]  =           institutDef( 98, 232, "MPIMET",    "Max-Planck Institute for Meteorology");
-  resH[n++]  =           institutDef( 78,   0, "DWD",       "Deutscher Wetterdienst");
-  resH[n++]  =           institutDef( 78, 255, "DWD",       "Deutscher Wetterdienst");
-  resH[n++]  = MCH     = institutDef(215, 255, "MCH",       "MeteoSwiss");
-  resH[n++]  =           institutDef(  7,   0, "NCEP",      "National Centers for Environmental Prediction");
-  resH[n++]  =           institutDef(  7,   1, "NCEP",      "National Centers for Environmental Prediction");
-  resH[n++]  =           institutDef( 60,   0, "NCAR",      "National Center for Atmospheric Research");
-  resH[n++]  =           institutDef( 74,   0, "METOFFICE", "U.K. Met Office");
-  resH[n++]  =           institutDef( 97,   0, "ESA",       "European Space Agency");
-  resH[n++]  =           institutDef( 99,   0, "KNMI",      "Royal Netherlands Meteorological Institute");
+  cdiResH resH[]
+    = { ECMWF   = institutDef( 98,   0, "ECMWF",     "European Centre for Medium-Range Weather Forecasts"),
+        MPIMET  = institutDef( 98, 232, "MPIMET",    "Max-Planck-Institute for Meteorology"),
+        institutDef( 98, 255, "MPIMET",    "Max-Planck-Institute for Meteorology"),
+        institutDef( 98, 232, "MPIMET",    "Max-Planck Institute for Meteorology"),
+        institutDef( 78,   0, "DWD",       "Deutscher Wetterdienst"),
+        institutDef( 78, 255, "DWD",       "Deutscher Wetterdienst"),
+        MCH     = institutDef(215, 255, "MCH",       "MeteoSwiss"),
+        institutDef(  7,   0, "NCEP",      "National Centers for Environmental Prediction"),
+        institutDef(  7,   1, "NCEP",      "National Centers for Environmental Prediction"),
+        institutDef( 60,   0, "NCAR",      "National Center for Atmospheric Research"),
+        institutDef( 74,   0, "METOFFICE", "U.K. Met Office"),
+        institutDef( 97,   0, "ESA",       "European Space Agency"),
+        institutDef( 99,   0, "KNMI",      "Royal Netherlands Meteorological Institute"),
+  };
   /*     (void) institutDef(  0,   0, "IPSL", "IPSL (Institut Pierre Simon Laplace, Paris, France)"); */
 
-  for ( i = 0; i < n ; i++ )
-    reshSetStatus(resH[i], &instituteOps, RESH_PRE_ASSIGNED);
+  size_t n = sizeof(resH)/sizeof(*resH);
+
+  for (size_t i = 0; i < n ; i++ )
+    reshSetStatus(resH[i], &instituteOps, RESH_IN_USE);
 }
 
 
@@ -304,10 +308,13 @@ enum {
 
 static int instituteGetPackSize(institute_t *ip, void *context)
 {
-  int txsize = serializeGetSize(institute_nints, DATATYPE_INT, context)
-    + serializeGetSize(strlen(ip->name) + 1, DATATYPE_TXT, context)
-    + serializeGetSize(strlen(ip->longname) + 1, DATATYPE_TXT, context);
-  return txsize;
+  size_t namelen = strlen(ip->name), longnamelen = strlen(ip->longname);
+  xassert(namelen < INT_MAX && longnamelen < INT_MAX);
+  size_t txsize = (size_t)serializeGetSize(institute_nints, DATATYPE_INT, context)
+    + (size_t)serializeGetSize((int)namelen + 1, DATATYPE_TXT, context)
+    + (size_t)serializeGetSize((int)longnamelen + 1, DATATYPE_TXT, context);
+  xassert(txsize <= INT_MAX);
+  return (int)txsize;
 }
 
 static void institutePackP(void * instituteptr, void *buf, int size, int *position, void *context)
@@ -331,7 +338,7 @@ int instituteUnpack(void *buf, int size, int *position, int originNamespace,
   int instituteID;
   char *name, *longname;
   serializeUnpack(buf, size, position, tempbuf, institute_nints, DATATYPE_INT, context);
-  name = (char *)xmalloc(tempbuf[3] + tempbuf[4]);
+  name = (char *)xmalloc((size_t)tempbuf[3] + (size_t)tempbuf[4]);
   longname = name + tempbuf[3];
   serializeUnpack(buf, size, position, name, tempbuf[3], DATATYPE_TXT, context);
   serializeUnpack(buf, size, position, longname, tempbuf[4], DATATYPE_TXT, context);
diff --git a/libcdi/src/mo_cdi.f90 b/libcdi/src/mo_cdi.f90
index ac377d8..b550921 100644
--- a/libcdi/src/mo_cdi.f90
+++ b/libcdi/src/mo_cdi.f90
@@ -6,3135 +6,2929 @@ module mo_cdi
 
       private
   
-      integer :: CDI_MAX_NAME = 256
-      integer :: CDI_UNDEFID = -1
-      integer :: CDI_GLOBAL = -1
-      integer :: CDI_BIGENDIAN = 0
-      integer :: CDI_LITTLEENDIAN = 1
-      integer :: CDI_REAL = 1
-      integer :: CDI_COMP = 2
-      integer :: CDI_BOTH = 3
-      integer :: CDI_ESYSTEM = -10
-      integer :: CDI_EINVAL = -20
-      integer :: CDI_EUFTYPE = -21
-      integer :: CDI_ELIBNAVAIL = -22
-      integer :: CDI_EUFSTRUCT = -23
-      integer :: CDI_EUNC4 = -24
-      integer :: CDI_ELIMIT = -99
-      integer :: FILETYPE_GRB = 1
-      integer :: FILETYPE_GRB2 = 2
-      integer :: FILETYPE_NC = 3
-      integer :: FILETYPE_NC2 = 4
-      integer :: FILETYPE_NC4 = 5
-      integer :: FILETYPE_NC4C = 6
-      integer :: FILETYPE_SRV = 7
-      integer :: FILETYPE_EXT = 8
-      integer :: FILETYPE_IEG = 9
-      integer :: COMPRESS_NONE = 0
-      integer :: COMPRESS_SZIP = 1
-      integer :: COMPRESS_GZIP = 2
-      integer :: COMPRESS_BZIP2 = 3
-      integer :: COMPRESS_ZIP = 4
-      integer :: COMPRESS_JPEG = 5
-      integer :: DATATYPE_PACK = 0
-      integer :: DATATYPE_PACK1 = 1
-      integer :: DATATYPE_PACK2 = 2
-      integer :: DATATYPE_PACK3 = 3
-      integer :: DATATYPE_PACK4 = 4
-      integer :: DATATYPE_PACK5 = 5
-      integer :: DATATYPE_PACK6 = 6
-      integer :: DATATYPE_PACK7 = 7
-      integer :: DATATYPE_PACK8 = 8
-      integer :: DATATYPE_PACK9 = 9
-      integer :: DATATYPE_PACK10 = 10
-      integer :: DATATYPE_PACK11 = 11
-      integer :: DATATYPE_PACK12 = 12
-      integer :: DATATYPE_PACK13 = 13
-      integer :: DATATYPE_PACK14 = 14
-      integer :: DATATYPE_PACK15 = 15
-      integer :: DATATYPE_PACK16 = 16
-      integer :: DATATYPE_PACK17 = 17
-      integer :: DATATYPE_PACK18 = 18
-      integer :: DATATYPE_PACK19 = 19
-      integer :: DATATYPE_PACK20 = 20
-      integer :: DATATYPE_PACK21 = 21
-      integer :: DATATYPE_PACK22 = 22
-      integer :: DATATYPE_PACK23 = 23
-      integer :: DATATYPE_PACK24 = 24
-      integer :: DATATYPE_PACK25 = 25
-      integer :: DATATYPE_PACK26 = 26
-      integer :: DATATYPE_PACK27 = 27
-      integer :: DATATYPE_PACK28 = 28
-      integer :: DATATYPE_PACK29 = 29
-      integer :: DATATYPE_PACK30 = 30
-      integer :: DATATYPE_PACK31 = 31
-      integer :: DATATYPE_PACK32 = 32
-      integer :: DATATYPE_CPX32 = 64
-      integer :: DATATYPE_CPX64 = 128
-      integer :: DATATYPE_FLT32 = 132
-      integer :: DATATYPE_FLT64 = 164
-      integer :: DATATYPE_INT8 = 208
-      integer :: DATATYPE_INT16 = 216
-      integer :: DATATYPE_INT32 = 232
-      integer :: DATATYPE_UINT8 = 308
-      integer :: DATATYPE_UINT16 = 316
-      integer :: DATATYPE_UINT32 = 332
-      integer :: DATATYPE_INT = 251
-      integer :: DATATYPE_FLT = 252
-      integer :: DATATYPE_TXT = 253
-      integer :: DATATYPE_CPX = 254
-      integer :: DATATYPE_UCHAR = 255
-      integer :: CHUNK_AUTO = 1
-      integer :: CHUNK_GRID = 2
-      integer :: CHUNK_LINES = 3
-      integer :: GRID_GENERIC = 1
-      integer :: GRID_GAUSSIAN = 2
-      integer :: GRID_GAUSSIAN_REDUCED = 3
-      integer :: GRID_LONLAT = 4
-      integer :: GRID_SPECTRAL = 5
-      integer :: GRID_FOURIER = 6
-      integer :: GRID_GME = 7
-      integer :: GRID_TRAJECTORY = 8
-      integer :: GRID_UNSTRUCTURED = 9
-      integer :: GRID_CURVILINEAR = 10
-      integer :: GRID_LCC = 11
-      integer :: GRID_LCC2 = 12
-      integer :: GRID_LAEA = 13
-      integer :: GRID_SINUSOIDAL = 14
-      integer :: GRID_PROJECTION = 15
-      integer :: ZAXIS_SURFACE = 0
-      integer :: ZAXIS_GENERIC = 1
-      integer :: ZAXIS_HYBRID = 2
-      integer :: ZAXIS_HYBRID_HALF = 3
-      integer :: ZAXIS_PRESSURE = 4
-      integer :: ZAXIS_HEIGHT = 5
-      integer :: ZAXIS_DEPTH_BELOW_SEA = 6
-      integer :: ZAXIS_DEPTH_BELOW_LAND = 7
-      integer :: ZAXIS_ISENTROPIC = 8
-      integer :: ZAXIS_TRAJECTORY = 9
-      integer :: ZAXIS_ALTITUDE = 10
-      integer :: ZAXIS_SIGMA = 11
-      integer :: ZAXIS_MEANSEA = 12
-      integer :: ZAXIS_TOA = 13
-      integer :: ZAXIS_SEA_BOTTOM = 14
-      integer :: ZAXIS_ATMOSPHERE = 15
-      integer :: ZAXIS_CLOUD_BASE = 16
-      integer :: ZAXIS_CLOUD_TOP = 17
-      integer :: ZAXIS_ISOTHERM_ZERO = 18
-      integer :: ZAXIS_SNOW = 19
-      integer :: ZAXIS_LAKE_BOTTOM = 20
-      integer :: ZAXIS_SEDIMENT_BOTTOM = 21
-      integer :: ZAXIS_SEDIMENT_BOTTOM_TA = 22
-      integer :: ZAXIS_SEDIMENT_BOTTOM_TW = 23
-      integer :: ZAXIS_MIX_LAYER = 24
-      integer :: ZAXIS_REFERENCE = 25
-      integer :: TIME_CONSTANT = 0
-      integer :: TIME_VARIABLE = 1
-      integer :: TSTEP_CONSTANT = 0
-      integer :: TSTEP_INSTANT = 1
-      integer :: TSTEP_AVG = 2
-      integer :: TSTEP_ACCUM = 3
-      integer :: TSTEP_MAX = 4
-      integer :: TSTEP_MIN = 5
-      integer :: TSTEP_DIFF = 6
-      integer :: TSTEP_RMS = 7
-      integer :: TSTEP_SD = 8
-      integer :: TSTEP_COV = 9
-      integer :: TSTEP_RATIO = 10
-      integer :: TSTEP_RANGE = 11
-      integer :: TSTEP_INSTANT2 = 12
-      integer :: TSTEP_INSTANT3 = 13
-      integer :: TAXIS_ABSOLUTE = 1
-      integer :: TAXIS_RELATIVE = 2
-      integer :: TAXIS_FORECAST = 3
-      integer :: TUNIT_SECOND = 1
-      integer :: TUNIT_MINUTE = 2
-      integer :: TUNIT_HOUR = 3
-      integer :: TUNIT_DAY = 4
-      integer :: TUNIT_MONTH = 5
-      integer :: TUNIT_YEAR = 6
-      integer :: TUNIT_QUARTER = 7
-      integer :: TUNIT_3HOURS = 8
-      integer :: TUNIT_6HOURS = 9
-      integer :: TUNIT_12HOURS = 10
-      integer :: CALENDAR_STANDARD = 0
-      integer :: CALENDAR_PROLEPTIC = 1
-      integer :: CALENDAR_360DAYS = 2
-      integer :: CALENDAR_365DAYS = 3
-      integer :: CALENDAR_366DAYS = 4
-      integer :: CALENDAR_NONE = 5
-
-      interface
-        subroutine cdiReset() bind(c,name='cdiReset')
-       end subroutine cdiReset
+      integer, parameter :: CDI_MAX_NAME = 256
+      integer, parameter :: CDI_UNDEFID = -1
+      integer, parameter :: CDI_GLOBAL = -1
+      integer, parameter :: CDI_BIGENDIAN = 0
+      integer, parameter :: CDI_LITTLEENDIAN = 1
+      integer, parameter :: CDI_REAL = 1
+      integer, parameter :: CDI_COMP = 2
+      integer, parameter :: CDI_BOTH = 3
+      integer, parameter :: CDI_ESYSTEM = -10
+      integer, parameter :: CDI_EINVAL = -20
+      integer, parameter :: CDI_EUFTYPE = -21
+      integer, parameter :: CDI_ELIBNAVAIL = -22
+      integer, parameter :: CDI_EUFSTRUCT = -23
+      integer, parameter :: CDI_EUNC4 = -24
+      integer, parameter :: CDI_ELIMIT = -99
+      integer, parameter :: FILETYPE_UNDEF = -1
+      integer, parameter :: FILETYPE_GRB = 1
+      integer, parameter :: FILETYPE_GRB2 = 2
+      integer, parameter :: FILETYPE_NC = 3
+      integer, parameter :: FILETYPE_NC2 = 4
+      integer, parameter :: FILETYPE_NC4 = 5
+      integer, parameter :: FILETYPE_NC4C = 6
+      integer, parameter :: FILETYPE_SRV = 7
+      integer, parameter :: FILETYPE_EXT = 8
+      integer, parameter :: FILETYPE_IEG = 9
+      integer, parameter :: COMPRESS_NONE = 0
+      integer, parameter :: COMPRESS_SZIP = 1
+      integer, parameter :: COMPRESS_GZIP = 2
+      integer, parameter :: COMPRESS_BZIP2 = 3
+      integer, parameter :: COMPRESS_ZIP = 4
+      integer, parameter :: COMPRESS_JPEG = 5
+      integer, parameter :: DATATYPE_PACK = 0
+      integer, parameter :: DATATYPE_PACK1 = 1
+      integer, parameter :: DATATYPE_PACK2 = 2
+      integer, parameter :: DATATYPE_PACK3 = 3
+      integer, parameter :: DATATYPE_PACK4 = 4
+      integer, parameter :: DATATYPE_PACK5 = 5
+      integer, parameter :: DATATYPE_PACK6 = 6
+      integer, parameter :: DATATYPE_PACK7 = 7
+      integer, parameter :: DATATYPE_PACK8 = 8
+      integer, parameter :: DATATYPE_PACK9 = 9
+      integer, parameter :: DATATYPE_PACK10 = 10
+      integer, parameter :: DATATYPE_PACK11 = 11
+      integer, parameter :: DATATYPE_PACK12 = 12
+      integer, parameter :: DATATYPE_PACK13 = 13
+      integer, parameter :: DATATYPE_PACK14 = 14
+      integer, parameter :: DATATYPE_PACK15 = 15
+      integer, parameter :: DATATYPE_PACK16 = 16
+      integer, parameter :: DATATYPE_PACK17 = 17
+      integer, parameter :: DATATYPE_PACK18 = 18
+      integer, parameter :: DATATYPE_PACK19 = 19
+      integer, parameter :: DATATYPE_PACK20 = 20
+      integer, parameter :: DATATYPE_PACK21 = 21
+      integer, parameter :: DATATYPE_PACK22 = 22
+      integer, parameter :: DATATYPE_PACK23 = 23
+      integer, parameter :: DATATYPE_PACK24 = 24
+      integer, parameter :: DATATYPE_PACK25 = 25
+      integer, parameter :: DATATYPE_PACK26 = 26
+      integer, parameter :: DATATYPE_PACK27 = 27
+      integer, parameter :: DATATYPE_PACK28 = 28
+      integer, parameter :: DATATYPE_PACK29 = 29
+      integer, parameter :: DATATYPE_PACK30 = 30
+      integer, parameter :: DATATYPE_PACK31 = 31
+      integer, parameter :: DATATYPE_PACK32 = 32
+      integer, parameter :: DATATYPE_CPX32 = 64
+      integer, parameter :: DATATYPE_CPX64 = 128
+      integer, parameter :: DATATYPE_FLT32 = 132
+      integer, parameter :: DATATYPE_FLT64 = 164
+      integer, parameter :: DATATYPE_INT8 = 208
+      integer, parameter :: DATATYPE_INT16 = 216
+      integer, parameter :: DATATYPE_INT32 = 232
+      integer, parameter :: DATATYPE_UINT8 = 308
+      integer, parameter :: DATATYPE_UINT16 = 316
+      integer, parameter :: DATATYPE_UINT32 = 332
+      integer, parameter :: DATATYPE_INT = 251
+      integer, parameter :: DATATYPE_FLT = 252
+      integer, parameter :: DATATYPE_TXT = 253
+      integer, parameter :: DATATYPE_CPX = 254
+      integer, parameter :: DATATYPE_UCHAR = 255
+      integer, parameter :: CHUNK_AUTO = 1
+      integer, parameter :: CHUNK_GRID = 2
+      integer, parameter :: CHUNK_LINES = 3
+      integer, parameter :: GRID_GENERIC = 1
+      integer, parameter :: GRID_GAUSSIAN = 2
+      integer, parameter :: GRID_GAUSSIAN_REDUCED = 3
+      integer, parameter :: GRID_LONLAT = 4
+      integer, parameter :: GRID_SPECTRAL = 5
+      integer, parameter :: GRID_FOURIER = 6
+      integer, parameter :: GRID_GME = 7
+      integer, parameter :: GRID_TRAJECTORY = 8
+      integer, parameter :: GRID_UNSTRUCTURED = 9
+      integer, parameter :: GRID_CURVILINEAR = 10
+      integer, parameter :: GRID_LCC = 11
+      integer, parameter :: GRID_LCC2 = 12
+      integer, parameter :: GRID_LAEA = 13
+      integer, parameter :: GRID_SINUSOIDAL = 14
+      integer, parameter :: GRID_PROJECTION = 15
+      integer, parameter :: ZAXIS_SURFACE = 0
+      integer, parameter :: ZAXIS_GENERIC = 1
+      integer, parameter :: ZAXIS_HYBRID = 2
+      integer, parameter :: ZAXIS_HYBRID_HALF = 3
+      integer, parameter :: ZAXIS_PRESSURE = 4
+      integer, parameter :: ZAXIS_HEIGHT = 5
+      integer, parameter :: ZAXIS_DEPTH_BELOW_SEA = 6
+      integer, parameter :: ZAXIS_DEPTH_BELOW_LAND = 7
+      integer, parameter :: ZAXIS_ISENTROPIC = 8
+      integer, parameter :: ZAXIS_TRAJECTORY = 9
+      integer, parameter :: ZAXIS_ALTITUDE = 10
+      integer, parameter :: ZAXIS_SIGMA = 11
+      integer, parameter :: ZAXIS_MEANSEA = 12
+      integer, parameter :: ZAXIS_TOA = 13
+      integer, parameter :: ZAXIS_SEA_BOTTOM = 14
+      integer, parameter :: ZAXIS_ATMOSPHERE = 15
+      integer, parameter :: ZAXIS_CLOUD_BASE = 16
+      integer, parameter :: ZAXIS_CLOUD_TOP = 17
+      integer, parameter :: ZAXIS_ISOTHERM_ZERO = 18
+      integer, parameter :: ZAXIS_SNOW = 19
+      integer, parameter :: ZAXIS_LAKE_BOTTOM = 20
+      integer, parameter :: ZAXIS_SEDIMENT_BOTTOM = 21
+      integer, parameter :: ZAXIS_SEDIMENT_BOTTOM_TA = 22
+      integer, parameter :: ZAXIS_SEDIMENT_BOTTOM_TW = 23
+      integer, parameter :: ZAXIS_MIX_LAYER = 24
+      integer, parameter :: ZAXIS_REFERENCE = 25
+      integer, parameter :: TIME_CONSTANT = 0
+      integer, parameter :: TIME_VARIABLE = 1
+      integer, parameter :: TSTEP_CONSTANT = 0
+      integer, parameter :: TSTEP_INSTANT = 1
+      integer, parameter :: TSTEP_AVG = 2
+      integer, parameter :: TSTEP_ACCUM = 3
+      integer, parameter :: TSTEP_MAX = 4
+      integer, parameter :: TSTEP_MIN = 5
+      integer, parameter :: TSTEP_DIFF = 6
+      integer, parameter :: TSTEP_RMS = 7
+      integer, parameter :: TSTEP_SD = 8
+      integer, parameter :: TSTEP_COV = 9
+      integer, parameter :: TSTEP_RATIO = 10
+      integer, parameter :: TSTEP_RANGE = 11
+      integer, parameter :: TSTEP_INSTANT2 = 12
+      integer, parameter :: TSTEP_INSTANT3 = 13
+      integer, parameter :: TAXIS_ABSOLUTE = 1
+      integer, parameter :: TAXIS_RELATIVE = 2
+      integer, parameter :: TAXIS_FORECAST = 3
+      integer, parameter :: TUNIT_SECOND = 1
+      integer, parameter :: TUNIT_MINUTE = 2
+      integer, parameter :: TUNIT_QUARTER = 3
+      integer, parameter :: TUNIT_30MINUTES = 4
+      integer, parameter :: TUNIT_HOUR = 5
+      integer, parameter :: TUNIT_3HOURS = 6
+      integer, parameter :: TUNIT_6HOURS = 7
+      integer, parameter :: TUNIT_12HOURS = 8
+      integer, parameter :: TUNIT_DAY = 9
+      integer, parameter :: TUNIT_MONTH = 10
+      integer, parameter :: TUNIT_YEAR = 11
+      integer, parameter :: CALENDAR_STANDARD = 0
+      integer, parameter :: CALENDAR_PROLEPTIC = 1
+      integer, parameter :: CALENDAR_360DAYS = 2
+      integer, parameter :: CALENDAR_365DAYS = 3
+      integer, parameter :: CALENDAR_366DAYS = 4
+      integer, parameter :: CALENDAR_NONE = 5
+      interface
+        function strlen(s) bind(c,name='strlen')
+          import :: c_ptr,c_size_t
+          type(c_ptr), value :: s
+          integer(kind=c_size_t) :: strlen
+        end function strlen
+      end interface
+      interface
+        function getchar() bind(c,name='getchar')
+          import :: c_int
+          integer(kind=c_int) :: getchar
+        end function getchar
+      end interface
+      interface
+        function getchar_unlocked() bind(c,name='getchar_unlocked')
+          import :: c_int
+          integer(kind=c_int) :: getchar_unlocked
+        end function getchar_unlocked
       end interface
-  
       interface
-        character(c_char) function cdiStringError(cdiErrno) bind(c,name='cdiStringError')
-          import :: c_int,c_char
-          integer(c_int), value :: cdiErrno
-       end function cdiStringError
+        subroutine cdiReset() bind(c,name='cdiReset')
+        end subroutine cdiReset
       end interface
-  
       interface
         subroutine cdiDebug(debug) bind(c,name='cdiDebug')
           import :: c_int
-          integer(c_int), value :: debug
-       end subroutine cdiDebug
+          integer(kind=c_int), value :: debug
+        end subroutine cdiDebug
       end interface
-  
-      interface
-        character(c_char) function cdiLibraryVersion() bind(c,name='cdiLibraryVersion')
-          import :: c_char
-       end function cdiLibraryVersion
-      end interface
-  
       interface
         subroutine cdiPrintVersion() bind(c,name='cdiPrintVersion')
-       end subroutine cdiPrintVersion
+        end subroutine cdiPrintVersion
       end interface
-  
       interface
-        integer(c_int) function cdiHaveFiletype(filetype) bind(c,name='cdiHaveFiletype')
+        function cdiHaveFiletype(filetype) bind(c,name='cdiHaveFiletype')
           import :: c_int
-          integer(c_int), value :: filetype
-       end function cdiHaveFiletype
+          integer(kind=c_int), value :: filetype
+          integer(kind=c_int) :: cdiHaveFiletype
+        end function cdiHaveFiletype
       end interface
-  
       interface
         subroutine cdiDefMissval(missval) bind(c,name='cdiDefMissval')
           import :: c_double
-          real(c_double), value :: missval
-       end subroutine cdiDefMissval
+          real(kind=c_double), value :: missval
+        end subroutine cdiDefMissval
       end interface
-  
       interface
-        real(c_double) function cdiInqMissval() bind(c,name='cdiInqMissval')
+        function cdiInqMissval() bind(c,name='cdiInqMissval')
           import :: c_double
-       end function cdiInqMissval
+          real(kind=c_double) :: cdiInqMissval
+        end function cdiInqMissval
       end interface
-  
       interface
         subroutine cdiDefGlobal(string,val) bind(c,name='cdiDefGlobal')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: string
-          integer(c_int), value :: val
-       end subroutine cdiDefGlobal
+          character(kind=c_char), dimension(*) :: string
+          integer(kind=c_int), value :: val
+        end subroutine cdiDefGlobal
       end interface
-  
       interface
-        integer(c_int) function namespaceNew() bind(c,name='namespaceNew')
+        function namespaceNew() bind(c,name='namespaceNew')
           import :: c_int
-       end function namespaceNew
+          integer(kind=c_int) :: namespaceNew
+        end function namespaceNew
       end interface
-  
       interface
         subroutine namespaceSetActive(namespaceID) bind(c,name='namespaceSetActive')
           import :: c_int
-          integer(c_int), value :: namespaceID
-       end subroutine namespaceSetActive
+          integer(kind=c_int), value :: namespaceID
+        end subroutine namespaceSetActive
       end interface
-  
       interface
         subroutine namespaceDelete(namespaceID) bind(c,name='namespaceDelete')
           import :: c_int
-          integer(c_int), value :: namespaceID
-       end subroutine namespaceDelete
+          integer(kind=c_int), value :: namespaceID
+        end subroutine namespaceDelete
       end interface
-  
       interface
         subroutine cdiParamToString(param,paramstr,maxlen) bind(c,name='cdiParamToString')
           import :: c_int,c_char
-          integer(c_int), value :: param
-          character(c_char), dimension(*) :: paramstr
-          integer(c_int), value :: maxlen
-       end subroutine cdiParamToString
+          integer(kind=c_int), value :: param
+          character(kind=c_char), dimension(*) :: paramstr
+          integer(kind=c_int), value :: maxlen
+        end subroutine cdiParamToString
       end interface
-  
       interface
         subroutine cdiDecodeParam(param,pnum,pcat,pdis) bind(c,name='cdiDecodeParam')
           import :: c_int
-          integer(c_int), value :: param
-          integer(c_int), intent(out) :: pnum
-          integer(c_int), intent(out) :: pcat
-          integer(c_int), intent(out) :: pdis
-       end subroutine cdiDecodeParam
+          integer(kind=c_int), value :: param
+          integer(kind=c_int), intent(out) :: pnum
+          integer(kind=c_int), intent(out) :: pcat
+          integer(kind=c_int), intent(out) :: pdis
+        end subroutine cdiDecodeParam
       end interface
-  
       interface
-        integer(c_int) function cdiEncodeParam(pnum,pcat,pdis) bind(c,name='cdiEncodeParam')
+        function cdiEncodeParam(pnum,pcat,pdis) bind(c,name='cdiEncodeParam')
           import :: c_int
-          integer(c_int), value :: pnum
-          integer(c_int), value :: pcat
-          integer(c_int), value :: pdis
-       end function cdiEncodeParam
+          integer(kind=c_int), value :: pnum
+          integer(kind=c_int), value :: pcat
+          integer(kind=c_int), value :: pdis
+          integer(kind=c_int) :: cdiEncodeParam
+        end function cdiEncodeParam
       end interface
-  
       interface
         subroutine cdiDecodeDate(date,year,month,day) bind(c,name='cdiDecodeDate')
           import :: c_int
-          integer(c_int), value :: date
-          integer(c_int), intent(out) :: year
-          integer(c_int), intent(out) :: month
-          integer(c_int), intent(out) :: day
-       end subroutine cdiDecodeDate
+          integer(kind=c_int), value :: date
+          integer(kind=c_int), intent(out) :: year
+          integer(kind=c_int), intent(out) :: month
+          integer(kind=c_int), intent(out) :: day
+        end subroutine cdiDecodeDate
       end interface
-  
       interface
-        integer(c_int) function cdiEncodeDate(year,month,day) bind(c,name='cdiEncodeDate')
+        function cdiEncodeDate(year,month,day) bind(c,name='cdiEncodeDate')
           import :: c_int
-          integer(c_int), value :: year
-          integer(c_int), value :: month
-          integer(c_int), value :: day
-       end function cdiEncodeDate
+          integer(kind=c_int), value :: year
+          integer(kind=c_int), value :: month
+          integer(kind=c_int), value :: day
+          integer(kind=c_int) :: cdiEncodeDate
+        end function cdiEncodeDate
       end interface
-  
       interface
         subroutine cdiDecodeTime(time,hour,minute,second) bind(c,name='cdiDecodeTime')
           import :: c_int
-          integer(c_int), value :: time
-          integer(c_int), intent(out) :: hour
-          integer(c_int), intent(out) :: minute
-          integer(c_int), intent(out) :: second
-       end subroutine cdiDecodeTime
+          integer(kind=c_int), value :: time
+          integer(kind=c_int), intent(out) :: hour
+          integer(kind=c_int), intent(out) :: minute
+          integer(kind=c_int), intent(out) :: second
+        end subroutine cdiDecodeTime
       end interface
-  
       interface
-        integer(c_int) function cdiEncodeTime(hour,minute,second) bind(c,name='cdiEncodeTime')
+        function cdiEncodeTime(hour,minute,second) bind(c,name='cdiEncodeTime')
           import :: c_int
-          integer(c_int), value :: hour
-          integer(c_int), value :: minute
-          integer(c_int), value :: second
-       end function cdiEncodeTime
+          integer(kind=c_int), value :: hour
+          integer(kind=c_int), value :: minute
+          integer(kind=c_int), value :: second
+          integer(kind=c_int) :: cdiEncodeTime
+        end function cdiEncodeTime
       end interface
-  
       interface
-        integer(c_int) function streamOpenRead(path) bind(c,name='streamOpenRead')
+        function streamOpenRead(path) bind(c,name='streamOpenRead')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: path
-       end function streamOpenRead
+          character(kind=c_char), dimension(*) :: path
+          integer(kind=c_int) :: streamOpenRead
+        end function streamOpenRead
       end interface
-  
       interface
-        integer(c_int) function streamOpenWrite(path,filetype) bind(c,name='streamOpenWrite')
+        function streamOpenWrite(path,filetype) bind(c,name='streamOpenWrite')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: path
-          integer(c_int), value :: filetype
-       end function streamOpenWrite
+          character(kind=c_char), dimension(*) :: path
+          integer(kind=c_int), value :: filetype
+          integer(kind=c_int) :: streamOpenWrite
+        end function streamOpenWrite
       end interface
-  
       interface
-        integer(c_int) function streamOpenAppend(path) bind(c,name='streamOpenAppend')
+        function streamOpenAppend(path) bind(c,name='streamOpenAppend')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: path
-       end function streamOpenAppend
+          character(kind=c_char), dimension(*) :: path
+          integer(kind=c_int) :: streamOpenAppend
+        end function streamOpenAppend
       end interface
-  
       interface
         subroutine streamClose(streamID) bind(c,name='streamClose')
           import :: c_int
-          integer(c_int), value :: streamID
-       end subroutine streamClose
+          integer(kind=c_int), value :: streamID
+        end subroutine streamClose
       end interface
-  
       interface
         subroutine streamSync(streamID) bind(c,name='streamSync')
           import :: c_int
-          integer(c_int), value :: streamID
-       end subroutine streamSync
+          integer(kind=c_int), value :: streamID
+        end subroutine streamSync
       end interface
-  
       interface
         subroutine streamDefVlist(streamID,vlistID) bind(c,name='streamDefVlist')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: vlistID
-       end subroutine streamDefVlist
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: vlistID
+        end subroutine streamDefVlist
       end interface
-  
       interface
-        integer(c_int) function streamInqVlist(streamID) bind(c,name='streamInqVlist')
+        function streamInqVlist(streamID) bind(c,name='streamInqVlist')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqVlist
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqVlist
+        end function streamInqVlist
       end interface
-  
       interface
-        integer(c_int) function streamInqVlistIDorig(streamID) bind(c,name='streamInqVlistIDorig')
+        function streamInqVlistIDorig(streamID) bind(c,name='streamInqVlistIDorig')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqVlistIDorig
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqVlistIDorig
+        end function streamInqVlistIDorig
       end interface
-  
       interface
-        integer(c_int) function streamInqFiletype(streamID) bind(c,name='streamInqFiletype')
+        function streamInqFiletype(streamID) bind(c,name='streamInqFiletype')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqFiletype
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqFiletype
+        end function streamInqFiletype
       end interface
-  
       interface
         subroutine streamDefByteorder(streamID,byteorder) bind(c,name='streamDefByteorder')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: byteorder
-       end subroutine streamDefByteorder
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: byteorder
+        end subroutine streamDefByteorder
       end interface
-  
       interface
-        integer(c_int) function streamInqByteorder(streamID) bind(c,name='streamInqByteorder')
+        function streamInqByteorder(streamID) bind(c,name='streamInqByteorder')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqByteorder
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqByteorder
+        end function streamInqByteorder
       end interface
-  
       interface
         subroutine streamDefCompType(streamID,comptype) bind(c,name='streamDefCompType')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: comptype
-       end subroutine streamDefCompType
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: comptype
+        end subroutine streamDefCompType
       end interface
-  
       interface
-        integer(c_int) function streamInqCompType(streamID) bind(c,name='streamInqCompType')
+        function streamInqCompType(streamID) bind(c,name='streamInqCompType')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqCompType
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqCompType
+        end function streamInqCompType
       end interface
-  
       interface
         subroutine streamDefCompLevel(streamID,complevel) bind(c,name='streamDefCompLevel')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: complevel
-       end subroutine streamDefCompLevel
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: complevel
+        end subroutine streamDefCompLevel
       end interface
-  
       interface
-        integer(c_int) function streamInqCompLevel(streamID) bind(c,name='streamInqCompLevel')
+        function streamInqCompLevel(streamID) bind(c,name='streamInqCompLevel')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqCompLevel
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqCompLevel
+        end function streamInqCompLevel
       end interface
-  
       interface
-        integer(c_int) function streamDefTimestep(streamID,tsID) bind(c,name='streamDefTimestep')
+        function streamDefTimestep(streamID,tsID) bind(c,name='streamDefTimestep')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: tsID
-       end function streamDefTimestep
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: tsID
+          integer(kind=c_int) :: streamDefTimestep
+        end function streamDefTimestep
       end interface
-  
       interface
-        integer(c_int) function streamInqTimestep(streamID,tsID) bind(c,name='streamInqTimestep')
+        function streamInqTimestep(streamID,tsID) bind(c,name='streamInqTimestep')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: tsID
-       end function streamInqTimestep
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: tsID
+          integer(kind=c_int) :: streamInqTimestep
+        end function streamInqTimestep
       end interface
-  
       interface
-        integer(c_int) function streamInqCurTimestepID(streamID) bind(c,name='streamInqCurTimestepID')
+        function streamInqCurTimestepID(streamID) bind(c,name='streamInqCurTimestepID')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqCurTimestepID
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqCurTimestepID
+        end function streamInqCurTimestepID
       end interface
-  
-      interface
-        character(c_char) function streamFilename(streamID) bind(c,name='streamFilename')
-          import :: c_int,c_char
-          integer(c_int), value :: streamID
-       end function streamFilename
-      end interface
-  
       interface
-        character(c_char) function streamFilesuffix(filetype) bind(c,name='streamFilesuffix')
-          import :: c_int,c_char
-          integer(c_int), value :: filetype
-       end function streamFilesuffix
+        function streamNtsteps(streamID) bind(c,name='streamNtsteps')
+          import :: c_int
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamNtsteps
+        end function streamNtsteps
       end interface
-  
       interface
-        integer(c_int) function streamNtsteps(streamID) bind(c,name='streamNtsteps')
+        function streamInqNvars(streamID) bind(c,name='streamInqNvars')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamNtsteps
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqNvars
+        end function streamInqNvars
       end interface
-  
       interface
         subroutine streamWriteVar(streamID,varID,data_vec,nmiss) bind(c,name='streamWriteVar')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          real(c_double), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteVar
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteVar
       end interface
-  
       interface
         subroutine streamWriteVarF(streamID,varID,data_vec,nmiss) bind(c,name='streamWriteVarF')
           import :: c_int,c_float
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          real(c_float), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteVarF
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          real(kind=c_float), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteVarF
       end interface
-  
       interface
         subroutine streamReadVar(streamID,varID,data_vec,nmiss) bind(c,name='streamReadVar')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          real(c_double), intent(out),dimension(*) :: data_vec
-          integer(c_int), intent(out) :: nmiss
-       end subroutine streamReadVar
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double), intent(out),dimension(*) :: data_vec
+          integer(kind=c_int), intent(out) :: nmiss
+        end subroutine streamReadVar
+      end interface
+      interface
+        subroutine streamReadVarF(streamID,varID,data_vec,nmiss) bind(c,name='streamReadVarF')
+          import :: c_int,c_float
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          real(kind=c_float), intent(out),dimension(*) :: data_vec
+          integer(kind=c_int), intent(out) :: nmiss
+        end subroutine streamReadVarF
       end interface
-  
       interface
         subroutine streamWriteVarSlice(streamID,varID,levelID,data_vec,nmiss) bind(c,name='streamWriteVarSlice')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levelID
-          real(c_double), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteVarSlice
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_double), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteVarSlice
       end interface
-  
       interface
         subroutine streamWriteVarSliceF(streamID,varID,levelID,data_vec,nmiss) bind(c,name='streamWriteVarSliceF')
           import :: c_int,c_float
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levelID
-          real(c_float), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteVarSliceF
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_float), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteVarSliceF
       end interface
-  
       interface
         subroutine streamReadVarSlice(streamID,varID,levelID,data_vec,nmiss) bind(c,name='streamReadVarSlice')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levelID
-          real(c_double), intent(out),dimension(*) :: data_vec
-          integer(c_int), intent(out) :: nmiss
-       end subroutine streamReadVarSlice
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_double), intent(out),dimension(*) :: data_vec
+          integer(kind=c_int), intent(out) :: nmiss
+        end subroutine streamReadVarSlice
+      end interface
+      interface
+        subroutine streamReadVarSliceF(streamID,varID,levelID,data_vec,nmiss) bind(c,name='streamReadVarSliceF')
+          import :: c_int,c_float
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_float), intent(out),dimension(*) :: data_vec
+          integer(kind=c_int), intent(out) :: nmiss
+        end subroutine streamReadVarSliceF
       end interface
-  
       interface
         subroutine streamDefRecord(streamID,varID,levelID) bind(c,name='streamDefRecord')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levelID
-       end subroutine streamDefRecord
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+        end subroutine streamDefRecord
       end interface
-  
       interface
         subroutine streamInqRecord(streamID,varID,levelID) bind(c,name='streamInqRecord')
           import :: c_int
-          integer(c_int), value :: streamID
-          integer(c_int), intent(out) :: varID
-          integer(c_int), intent(out) :: levelID
-       end subroutine streamInqRecord
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), intent(out) :: varID
+          integer(kind=c_int), intent(out) :: levelID
+        end subroutine streamInqRecord
       end interface
-  
       interface
         subroutine streamWriteRecord(streamID,data_vec,nmiss) bind(c,name='streamWriteRecord')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          real(c_double), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteRecord
+          integer(kind=c_int), value :: streamID
+          real(kind=c_double), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteRecord
       end interface
-  
       interface
         subroutine streamWriteRecordF(streamID,data_vec,nmiss) bind(c,name='streamWriteRecordF')
           import :: c_int,c_float
-          integer(c_int), value :: streamID
-          real(c_float), intent(in),dimension(*) :: data_vec
-          integer(c_int), value :: nmiss
-       end subroutine streamWriteRecordF
+          integer(kind=c_int), value :: streamID
+          real(kind=c_float), intent(in),dimension(*) :: data_vec
+          integer(kind=c_int), value :: nmiss
+        end subroutine streamWriteRecordF
       end interface
-  
       interface
         subroutine streamReadRecord(streamID,data_vec,nmiss) bind(c,name='streamReadRecord')
           import :: c_int,c_double
-          integer(c_int), value :: streamID
-          real(c_double), intent(out),dimension(*) :: data_vec
-          integer(c_int), intent(out) :: nmiss
-       end subroutine streamReadRecord
+          integer(kind=c_int), value :: streamID
+          real(kind=c_double), intent(out),dimension(*) :: data_vec
+          integer(kind=c_int), intent(out) :: nmiss
+        end subroutine streamReadRecord
       end interface
-  
       interface
         subroutine streamCopyRecord(streamIDdest,streamIDsrc) bind(c,name='streamCopyRecord')
           import :: c_int
-          integer(c_int), value :: streamIDdest
-          integer(c_int), value :: streamIDsrc
-       end subroutine streamCopyRecord
+          integer(kind=c_int), value :: streamIDdest
+          integer(kind=c_int), value :: streamIDsrc
+        end subroutine streamCopyRecord
       end interface
-  
       interface
-        integer(c_int) function vlistCreate() bind(c,name='vlistCreate')
+        function vlistCreate() bind(c,name='vlistCreate')
           import :: c_int
-       end function vlistCreate
+          integer(kind=c_int) :: vlistCreate
+        end function vlistCreate
       end interface
-  
       interface
         subroutine vlistDestroy(vlistID) bind(c,name='vlistDestroy')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end subroutine vlistDestroy
+          integer(kind=c_int), value :: vlistID
+        end subroutine vlistDestroy
       end interface
-  
       interface
-        integer(c_int) function vlistDuplicate(vlistID) bind(c,name='vlistDuplicate')
+        function vlistDuplicate(vlistID) bind(c,name='vlistDuplicate')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistDuplicate
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistDuplicate
+        end function vlistDuplicate
       end interface
-  
       interface
         subroutine vlistCopy(vlistID2,vlistID1) bind(c,name='vlistCopy')
           import :: c_int
-          integer(c_int), value :: vlistID2
-          integer(c_int), value :: vlistID1
-       end subroutine vlistCopy
+          integer(kind=c_int), value :: vlistID2
+          integer(kind=c_int), value :: vlistID1
+        end subroutine vlistCopy
       end interface
-  
       interface
         subroutine vlistCopyFlag(vlistID2,vlistID1) bind(c,name='vlistCopyFlag')
           import :: c_int
-          integer(c_int), value :: vlistID2
-          integer(c_int), value :: vlistID1
-       end subroutine vlistCopyFlag
+          integer(kind=c_int), value :: vlistID2
+          integer(kind=c_int), value :: vlistID1
+        end subroutine vlistCopyFlag
       end interface
-  
       interface
         subroutine vlistClearFlag(vlistID) bind(c,name='vlistClearFlag')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end subroutine vlistClearFlag
+          integer(kind=c_int), value :: vlistID
+        end subroutine vlistClearFlag
       end interface
-  
       interface
         subroutine vlistCat(vlistID2,vlistID1) bind(c,name='vlistCat')
           import :: c_int
-          integer(c_int), value :: vlistID2
-          integer(c_int), value :: vlistID1
-       end subroutine vlistCat
+          integer(kind=c_int), value :: vlistID2
+          integer(kind=c_int), value :: vlistID1
+        end subroutine vlistCat
       end interface
-  
       interface
         subroutine vlistMerge(vlistID2,vlistID1) bind(c,name='vlistMerge')
           import :: c_int
-          integer(c_int), value :: vlistID2
-          integer(c_int), value :: vlistID1
-       end subroutine vlistMerge
+          integer(kind=c_int), value :: vlistID2
+          integer(kind=c_int), value :: vlistID1
+        end subroutine vlistMerge
       end interface
-  
       interface
         subroutine vlistPrint(vlistID) bind(c,name='vlistPrint')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end subroutine vlistPrint
+          integer(kind=c_int), value :: vlistID
+        end subroutine vlistPrint
       end interface
-  
       interface
-        integer(c_int) function vlistNumber(vlistID) bind(c,name='vlistNumber')
+        function vlistNumber(vlistID) bind(c,name='vlistNumber')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNumber
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNumber
+        end function vlistNumber
       end interface
-  
       interface
-        integer(c_int) function vlistNvars(vlistID) bind(c,name='vlistNvars')
+        function vlistNvars(vlistID) bind(c,name='vlistNvars')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNvars
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNvars
+        end function vlistNvars
       end interface
-  
       interface
-        integer(c_int) function vlistNgrids(vlistID) bind(c,name='vlistNgrids')
+        function vlistNgrids(vlistID) bind(c,name='vlistNgrids')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNgrids
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNgrids
+        end function vlistNgrids
       end interface
-  
       interface
-        integer(c_int) function vlistNzaxis(vlistID) bind(c,name='vlistNzaxis')
+        function vlistNzaxis(vlistID) bind(c,name='vlistNzaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNzaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNzaxis
+        end function vlistNzaxis
       end interface
-  
       interface
         subroutine vlistDefNtsteps(vlistID,nts) bind(c,name='vlistDefNtsteps')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: nts
-       end subroutine vlistDefNtsteps
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: nts
+        end subroutine vlistDefNtsteps
       end interface
-  
       interface
-        integer(c_int) function vlistNtsteps(vlistID) bind(c,name='vlistNtsteps')
+        function vlistNtsteps(vlistID) bind(c,name='vlistNtsteps')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNtsteps
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNtsteps
+        end function vlistNtsteps
       end interface
-  
       interface
-        integer(c_int) function vlistGridsizeMax(vlistID) bind(c,name='vlistGridsizeMax')
+        function vlistGridsizeMax(vlistID) bind(c,name='vlistGridsizeMax')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistGridsizeMax
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistGridsizeMax
+        end function vlistGridsizeMax
       end interface
-  
       interface
-        integer(c_int) function vlistGrid(vlistID,index) bind(c,name='vlistGrid')
+        function vlistGrid(vlistID,index) bind(c,name='vlistGrid')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: index
-       end function vlistGrid
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: index
+          integer(kind=c_int) :: vlistGrid
+        end function vlistGrid
       end interface
-  
       interface
-        integer(c_int) function vlistGridIndex(vlistID,gridID) bind(c,name='vlistGridIndex')
+        function vlistGridIndex(vlistID,gridID) bind(c,name='vlistGridIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: gridID
-       end function vlistGridIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: vlistGridIndex
+        end function vlistGridIndex
       end interface
-  
       interface
         subroutine vlistChangeGridIndex(vlistID,index,gridID) bind(c,name='vlistChangeGridIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: index
-          integer(c_int), value :: gridID
-       end subroutine vlistChangeGridIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: index
+          integer(kind=c_int), value :: gridID
+        end subroutine vlistChangeGridIndex
       end interface
-  
       interface
         subroutine vlistChangeGrid(vlistID,gridID1,gridID2) bind(c,name='vlistChangeGrid')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: gridID1
-          integer(c_int), value :: gridID2
-       end subroutine vlistChangeGrid
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: gridID1
+          integer(kind=c_int), value :: gridID2
+        end subroutine vlistChangeGrid
       end interface
-  
       interface
-        integer(c_int) function vlistZaxis(vlistID,index) bind(c,name='vlistZaxis')
+        function vlistZaxis(vlistID,index) bind(c,name='vlistZaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: index
-       end function vlistZaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: index
+          integer(kind=c_int) :: vlistZaxis
+        end function vlistZaxis
       end interface
-  
       interface
-        integer(c_int) function vlistZaxisIndex(vlistID,zaxisID) bind(c,name='vlistZaxisIndex')
+        function vlistZaxisIndex(vlistID,zaxisID) bind(c,name='vlistZaxisIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: zaxisID
-       end function vlistZaxisIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: vlistZaxisIndex
+        end function vlistZaxisIndex
       end interface
-  
       interface
         subroutine vlistChangeZaxisIndex(vlistID,index,zaxisID) bind(c,name='vlistChangeZaxisIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: index
-          integer(c_int), value :: zaxisID
-       end subroutine vlistChangeZaxisIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: index
+          integer(kind=c_int), value :: zaxisID
+        end subroutine vlistChangeZaxisIndex
       end interface
-  
       interface
         subroutine vlistChangeZaxis(vlistID,zaxisID1,zaxisID2) bind(c,name='vlistChangeZaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: zaxisID1
-          integer(c_int), value :: zaxisID2
-       end subroutine vlistChangeZaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: zaxisID1
+          integer(kind=c_int), value :: zaxisID2
+        end subroutine vlistChangeZaxis
       end interface
-  
       interface
-        integer(c_int) function vlistNrecs(vlistID) bind(c,name='vlistNrecs')
+        function vlistNrecs(vlistID) bind(c,name='vlistNrecs')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistNrecs
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistNrecs
+        end function vlistNrecs
       end interface
-  
       interface
         subroutine vlistDefTaxis(vlistID,taxisID) bind(c,name='vlistDefTaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: taxisID
-       end subroutine vlistDefTaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: taxisID
+        end subroutine vlistDefTaxis
       end interface
-  
       interface
-        integer(c_int) function vlistInqTaxis(vlistID) bind(c,name='vlistInqTaxis')
+        function vlistInqTaxis(vlistID) bind(c,name='vlistInqTaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistInqTaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistInqTaxis
+        end function vlistInqTaxis
       end interface
-  
       interface
         subroutine vlistDefTable(vlistID,tableID) bind(c,name='vlistDefTable')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: tableID
-       end subroutine vlistDefTable
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: tableID
+        end subroutine vlistDefTable
       end interface
-  
       interface
-        integer(c_int) function vlistInqTable(vlistID) bind(c,name='vlistInqTable')
+        function vlistInqTable(vlistID) bind(c,name='vlistInqTable')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistInqTable
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistInqTable
+        end function vlistInqTable
       end interface
-  
       interface
         subroutine vlistDefInstitut(vlistID,instID) bind(c,name='vlistDefInstitut')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: instID
-       end subroutine vlistDefInstitut
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: instID
+        end subroutine vlistDefInstitut
       end interface
-  
       interface
-        integer(c_int) function vlistInqInstitut(vlistID) bind(c,name='vlistInqInstitut')
+        function vlistInqInstitut(vlistID) bind(c,name='vlistInqInstitut')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistInqInstitut
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistInqInstitut
+        end function vlistInqInstitut
       end interface
-  
       interface
         subroutine vlistDefModel(vlistID,modelID) bind(c,name='vlistDefModel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: modelID
-       end subroutine vlistDefModel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: modelID
+        end subroutine vlistDefModel
       end interface
-  
       interface
-        integer(c_int) function vlistInqModel(vlistID) bind(c,name='vlistInqModel')
+        function vlistInqModel(vlistID) bind(c,name='vlistInqModel')
           import :: c_int
-          integer(c_int), value :: vlistID
-       end function vlistInqModel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int) :: vlistInqModel
+        end function vlistInqModel
       end interface
-  
       interface
-        integer(c_int) function vlistDefVar(vlistID,gridID,zaxisID,tsteptype) bind(c,name='vlistDefVar')
+        function vlistDefVar(vlistID,gridID,zaxisID,tsteptype) bind(c,name='vlistDefVar')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: gridID
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: tsteptype
-       end function vlistDefVar
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: tsteptype
+          integer(kind=c_int) :: vlistDefVar
+        end function vlistDefVar
       end interface
-  
       interface
         subroutine vlistChangeVarGrid(vlistID,varID,gridID) bind(c,name='vlistChangeVarGrid')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: gridID
-       end subroutine vlistChangeVarGrid
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: gridID
+        end subroutine vlistChangeVarGrid
       end interface
-  
       interface
         subroutine vlistChangeVarZaxis(vlistID,varID,zaxisID) bind(c,name='vlistChangeVarZaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: zaxisID
-       end subroutine vlistChangeVarZaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: zaxisID
+        end subroutine vlistChangeVarZaxis
       end interface
-  
       interface
         subroutine vlistInqVar(vlistID,varID,gridID,zaxisID,tsteptype) bind(c,name='vlistInqVar')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), intent(out) :: gridID
-          integer(c_int), intent(out) :: zaxisID
-          integer(c_int), intent(out) :: tsteptype
-       end subroutine vlistInqVar
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), intent(out) :: gridID
+          integer(kind=c_int), intent(out) :: zaxisID
+          integer(kind=c_int), intent(out) :: tsteptype
+        end subroutine vlistInqVar
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarGrid(vlistID,varID) bind(c,name='vlistInqVarGrid')
+        function vlistInqVarGrid(vlistID,varID) bind(c,name='vlistInqVarGrid')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarGrid
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarGrid
+        end function vlistInqVarGrid
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarZaxis(vlistID,varID) bind(c,name='vlistInqVarZaxis')
+        function vlistInqVarZaxis(vlistID,varID) bind(c,name='vlistInqVarZaxis')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarZaxis
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarZaxis
+        end function vlistInqVarZaxis
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarID(vlistID,code) bind(c,name='vlistInqVarID')
+        function vlistInqVarID(vlistID,code) bind(c,name='vlistInqVarID')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: code
-       end function vlistInqVarID
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: code
+          integer(kind=c_int) :: vlistInqVarID
+        end function vlistInqVarID
       end interface
-  
       interface
         subroutine vlistDefVarTsteptype(vlistID,varID,tsteptype) bind(c,name='vlistDefVarTsteptype')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: tsteptype
-       end subroutine vlistDefVarTsteptype
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: tsteptype
+        end subroutine vlistDefVarTsteptype
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarTsteptype(vlistID,varID) bind(c,name='vlistInqVarTsteptype')
+        function vlistInqVarTsteptype(vlistID,varID) bind(c,name='vlistInqVarTsteptype')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarTsteptype
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarTsteptype
+        end function vlistInqVarTsteptype
       end interface
-  
       interface
         subroutine vlistDefVarCompType(vlistID,varID,comptype) bind(c,name='vlistDefVarCompType')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: comptype
-       end subroutine vlistDefVarCompType
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: comptype
+        end subroutine vlistDefVarCompType
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarCompType(vlistID,varID) bind(c,name='vlistInqVarCompType')
+        function vlistInqVarCompType(vlistID,varID) bind(c,name='vlistInqVarCompType')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarCompType
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarCompType
+        end function vlistInqVarCompType
       end interface
-  
       interface
         subroutine vlistDefVarCompLevel(vlistID,varID,complevel) bind(c,name='vlistDefVarCompLevel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: complevel
-       end subroutine vlistDefVarCompLevel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: complevel
+        end subroutine vlistDefVarCompLevel
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarCompLevel(vlistID,varID) bind(c,name='vlistInqVarCompLevel')
+        function vlistInqVarCompLevel(vlistID,varID) bind(c,name='vlistInqVarCompLevel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarCompLevel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarCompLevel
+        end function vlistInqVarCompLevel
       end interface
-  
       interface
         subroutine vlistDefVarParam(vlistID,varID,param) bind(c,name='vlistDefVarParam')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: param
-       end subroutine vlistDefVarParam
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: param
+        end subroutine vlistDefVarParam
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarParam(vlistID,varID) bind(c,name='vlistInqVarParam')
+        function vlistInqVarParam(vlistID,varID) bind(c,name='vlistInqVarParam')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarParam
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarParam
+        end function vlistInqVarParam
       end interface
-  
       interface
         subroutine vlistDefVarCode(vlistID,varID,code) bind(c,name='vlistDefVarCode')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: code
-       end subroutine vlistDefVarCode
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: code
+        end subroutine vlistDefVarCode
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarCode(vlistID,varID) bind(c,name='vlistInqVarCode')
+        function vlistInqVarCode(vlistID,varID) bind(c,name='vlistInqVarCode')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarCode
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarCode
+        end function vlistInqVarCode
       end interface
-  
       interface
         subroutine vlistDefVarDatatype(vlistID,varID,datatype) bind(c,name='vlistDefVarDatatype')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: datatype
-       end subroutine vlistDefVarDatatype
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: datatype
+        end subroutine vlistDefVarDatatype
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarDatatype(vlistID,varID) bind(c,name='vlistInqVarDatatype')
+        function vlistInqVarDatatype(vlistID,varID) bind(c,name='vlistInqVarDatatype')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarDatatype
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarDatatype
+        end function vlistInqVarDatatype
       end interface
-  
       interface
         subroutine vlistDefVarChunkType(vlistID,varID,chunktype) bind(c,name='vlistDefVarChunkType')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: chunktype
-       end subroutine vlistDefVarChunkType
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: chunktype
+        end subroutine vlistDefVarChunkType
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarChunkType(vlistID,varID) bind(c,name='vlistInqVarChunkType')
+        function vlistInqVarChunkType(vlistID,varID) bind(c,name='vlistInqVarChunkType')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarChunkType
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarChunkType
+        end function vlistInqVarChunkType
       end interface
-  
       interface
         subroutine vlistDefVarXYZ(vlistID,varID,xyz) bind(c,name='vlistDefVarXYZ')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: xyz
-       end subroutine vlistDefVarXYZ
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: xyz
+        end subroutine vlistDefVarXYZ
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarXYZ(vlistID,varID) bind(c,name='vlistInqVarXYZ')
+        function vlistInqVarXYZ(vlistID,varID) bind(c,name='vlistInqVarXYZ')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarXYZ
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarXYZ
+        end function vlistInqVarXYZ
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarNumber(vlistID,varID) bind(c,name='vlistInqVarNumber')
+        function vlistInqVarNumber(vlistID,varID) bind(c,name='vlistInqVarNumber')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarNumber
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarNumber
+        end function vlistInqVarNumber
       end interface
-  
       interface
         subroutine vlistDefVarInstitut(vlistID,varID,instID) bind(c,name='vlistDefVarInstitut')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: instID
-       end subroutine vlistDefVarInstitut
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: instID
+        end subroutine vlistDefVarInstitut
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarInstitut(vlistID,varID) bind(c,name='vlistInqVarInstitut')
+        function vlistInqVarInstitut(vlistID,varID) bind(c,name='vlistInqVarInstitut')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarInstitut
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarInstitut
+        end function vlistInqVarInstitut
       end interface
-  
       interface
         subroutine vlistDefVarModel(vlistID,varID,modelID) bind(c,name='vlistDefVarModel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: modelID
-       end subroutine vlistDefVarModel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: modelID
+        end subroutine vlistDefVarModel
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarModel(vlistID,varID) bind(c,name='vlistInqVarModel')
+        function vlistInqVarModel(vlistID,varID) bind(c,name='vlistInqVarModel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarModel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarModel
+        end function vlistInqVarModel
       end interface
-  
       interface
         subroutine vlistDefVarTable(vlistID,varID,tableID) bind(c,name='vlistDefVarTable')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: tableID
-       end subroutine vlistDefVarTable
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: tableID
+        end subroutine vlistDefVarTable
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarTable(vlistID,varID) bind(c,name='vlistInqVarTable')
+        function vlistInqVarTable(vlistID,varID) bind(c,name='vlistInqVarTable')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarTable
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarTable
+        end function vlistInqVarTable
       end interface
-  
       interface
         subroutine vlistDefVarName(vlistID,varID,name) bind(c,name='vlistDefVarName')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end subroutine vlistDefVarName
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+        end subroutine vlistDefVarName
       end interface
-  
       interface
         subroutine vlistInqVarName(vlistID,varID,name) bind(c,name='vlistInqVarName')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end subroutine vlistInqVarName
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+        end subroutine vlistInqVarName
       end interface
-  
       interface
         subroutine vlistDefVarStdname(vlistID,varID,stdname) bind(c,name='vlistDefVarStdname')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: stdname
-       end subroutine vlistDefVarStdname
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: stdname
+        end subroutine vlistDefVarStdname
       end interface
-  
       interface
         subroutine vlistInqVarStdname(vlistID,varID,stdname) bind(c,name='vlistInqVarStdname')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: stdname
-       end subroutine vlistInqVarStdname
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: stdname
+        end subroutine vlistInqVarStdname
       end interface
-  
       interface
         subroutine vlistDefVarLongname(vlistID,varID,longname) bind(c,name='vlistDefVarLongname')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: longname
-       end subroutine vlistDefVarLongname
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: longname
+        end subroutine vlistDefVarLongname
       end interface
-  
       interface
         subroutine vlistInqVarLongname(vlistID,varID,longname) bind(c,name='vlistInqVarLongname')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: longname
-       end subroutine vlistInqVarLongname
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: longname
+        end subroutine vlistInqVarLongname
       end interface
-  
       interface
         subroutine vlistDefVarUnits(vlistID,varID,units) bind(c,name='vlistDefVarUnits')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: units
-       end subroutine vlistDefVarUnits
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: units
+        end subroutine vlistDefVarUnits
       end interface
-  
       interface
         subroutine vlistInqVarUnits(vlistID,varID,units) bind(c,name='vlistInqVarUnits')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: units
-       end subroutine vlistInqVarUnits
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: units
+        end subroutine vlistInqVarUnits
       end interface
-  
       interface
         subroutine vlistDefVarMissval(vlistID,varID,missval) bind(c,name='vlistDefVarMissval')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          real(c_double), value :: missval
-       end subroutine vlistDefVarMissval
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double), value :: missval
+        end subroutine vlistDefVarMissval
       end interface
-  
       interface
-        real(c_double) function vlistInqVarMissval(vlistID,varID) bind(c,name='vlistInqVarMissval')
+        function vlistInqVarMissval(vlistID,varID) bind(c,name='vlistInqVarMissval')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarMissval
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double) :: vlistInqVarMissval
+        end function vlistInqVarMissval
       end interface
-  
       interface
         subroutine vlistDefVarExtra(vlistID,varID,extra) bind(c,name='vlistDefVarExtra')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: extra
-       end subroutine vlistDefVarExtra
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: extra
+        end subroutine vlistDefVarExtra
       end interface
-  
       interface
         subroutine vlistInqVarExtra(vlistID,varID,extra) bind(c,name='vlistInqVarExtra')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: extra
-       end subroutine vlistInqVarExtra
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: extra
+        end subroutine vlistInqVarExtra
       end interface
-  
       interface
         subroutine vlistDefVarScalefactor(vlistID,varID,scalefactor) bind(c,name='vlistDefVarScalefactor')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          real(c_double), value :: scalefactor
-       end subroutine vlistDefVarScalefactor
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double), value :: scalefactor
+        end subroutine vlistDefVarScalefactor
       end interface
-  
       interface
-        real(c_double) function vlistInqVarScalefactor(vlistID,varID) bind(c,name='vlistInqVarScalefactor')
+        function vlistInqVarScalefactor(vlistID,varID) bind(c,name='vlistInqVarScalefactor')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarScalefactor
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double) :: vlistInqVarScalefactor
+        end function vlistInqVarScalefactor
       end interface
-  
       interface
         subroutine vlistDefVarAddoffset(vlistID,varID,addoffset) bind(c,name='vlistDefVarAddoffset')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          real(c_double), value :: addoffset
-       end subroutine vlistDefVarAddoffset
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double), value :: addoffset
+        end subroutine vlistDefVarAddoffset
       end interface
-  
       interface
-        real(c_double) function vlistInqVarAddoffset(vlistID,varID) bind(c,name='vlistInqVarAddoffset')
+        function vlistInqVarAddoffset(vlistID,varID) bind(c,name='vlistInqVarAddoffset')
           import :: c_int,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarAddoffset
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          real(kind=c_double) :: vlistInqVarAddoffset
+        end function vlistInqVarAddoffset
       end interface
-  
       interface
         subroutine vlistDefVarTimave(vlistID,varID,timave) bind(c,name='vlistDefVarTimave')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: timave
-       end subroutine vlistDefVarTimave
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: timave
+        end subroutine vlistDefVarTimave
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarTimave(vlistID,varID) bind(c,name='vlistInqVarTimave')
+        function vlistInqVarTimave(vlistID,varID) bind(c,name='vlistInqVarTimave')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarTimave
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarTimave
+        end function vlistInqVarTimave
       end interface
-  
       interface
         subroutine vlistDefVarTimaccu(vlistID,varID,timaccu) bind(c,name='vlistDefVarTimaccu')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: timaccu
-       end subroutine vlistDefVarTimaccu
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: timaccu
+        end subroutine vlistDefVarTimaccu
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarTimaccu(vlistID,varID) bind(c,name='vlistInqVarTimaccu')
+        function vlistInqVarTimaccu(vlistID,varID) bind(c,name='vlistInqVarTimaccu')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarTimaccu
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarTimaccu
+        end function vlistInqVarTimaccu
       end interface
-  
       interface
         subroutine vlistDefVarTypeOfGeneratingProcess(vlistID,varID,typeOfGeneratingProcess) bind(c,&
        name='vlistDefVarTypeOfGeneratingProcess')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: typeOfGeneratingProcess
-       end subroutine vlistDefVarTypeOfGeneratingProcess
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: typeOfGeneratingProcess
+        end subroutine vlistDefVarTypeOfGeneratingProcess
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarTypeOfGeneratingProcess(vlistID,varID) bind(c,name='vlistInqVarTypeOfGeneratingProcess')
+        function vlistInqVarTypeOfGeneratingProcess(vlistID,varID) bind(c,name='vlistInqVarTypeOfGeneratingProcess')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarTypeOfGeneratingProcess
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarTypeOfGeneratingProcess
+        end function vlistInqVarTypeOfGeneratingProcess
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarSize(vlistID,varID) bind(c,name='vlistInqVarSize')
+        subroutine vlistDefVarProductDefinitionTemplate(vlistID,varID,productDefinitionTemplate) bind(c,&
+       name='vlistDefVarProductDefinitionTemplate')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistInqVarSize
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: productDefinitionTemplate
+        end subroutine vlistDefVarProductDefinitionTemplate
+      end interface
+      interface
+        function vlistInqVarProductDefinitionTemplate(vlistID,varID) bind(c,name='vlistInqVarProductDefinitionTemplate')
+          import :: c_int
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarProductDefinitionTemplate
+        end function vlistInqVarProductDefinitionTemplate
+      end interface
+      interface
+        function vlistInqVarSize(vlistID,varID) bind(c,name='vlistInqVarSize')
+          import :: c_int
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistInqVarSize
+        end function vlistInqVarSize
       end interface
-  
       interface
         subroutine vlistDefIndex(vlistID,varID,levID,index) bind(c,name='vlistDefIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levID
-          integer(c_int), value :: index
-       end subroutine vlistDefIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levID
+          integer(kind=c_int), value :: index
+        end subroutine vlistDefIndex
       end interface
-  
       interface
-        integer(c_int) function vlistInqIndex(vlistID,varID,levID) bind(c,name='vlistInqIndex')
+        function vlistInqIndex(vlistID,varID,levID) bind(c,name='vlistInqIndex')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levID
-       end function vlistInqIndex
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levID
+          integer(kind=c_int) :: vlistInqIndex
+        end function vlistInqIndex
       end interface
-  
       interface
         subroutine vlistDefFlag(vlistID,varID,levID,flag) bind(c,name='vlistDefFlag')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levID
-          integer(c_int), value :: flag
-       end subroutine vlistDefFlag
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levID
+          integer(kind=c_int), value :: flag
+        end subroutine vlistDefFlag
       end interface
-  
       interface
-        integer(c_int) function vlistInqFlag(vlistID,varID,levID) bind(c,name='vlistInqFlag')
+        function vlistInqFlag(vlistID,varID,levID) bind(c,name='vlistInqFlag')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levID
-       end function vlistInqFlag
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levID
+          integer(kind=c_int) :: vlistInqFlag
+        end function vlistInqFlag
       end interface
-  
       interface
-        integer(c_int) function vlistFindVar(vlistID,fvarID) bind(c,name='vlistFindVar')
+        function vlistFindVar(vlistID,fvarID) bind(c,name='vlistFindVar')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: fvarID
-       end function vlistFindVar
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: fvarID
+          integer(kind=c_int) :: vlistFindVar
+        end function vlistFindVar
       end interface
-  
       interface
-        integer(c_int) function vlistFindLevel(vlistID,fvarID,flevelID) bind(c,name='vlistFindLevel')
+        function vlistFindLevel(vlistID,fvarID,flevelID) bind(c,name='vlistFindLevel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: fvarID
-          integer(c_int), value :: flevelID
-       end function vlistFindLevel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: fvarID
+          integer(kind=c_int), value :: flevelID
+          integer(kind=c_int) :: vlistFindLevel
+        end function vlistFindLevel
       end interface
-  
       interface
-        integer(c_int) function vlistMergedVar(vlistID,varID) bind(c,name='vlistMergedVar')
+        function vlistMergedVar(vlistID,varID) bind(c,name='vlistMergedVar')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-       end function vlistMergedVar
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int) :: vlistMergedVar
+        end function vlistMergedVar
       end interface
-  
       interface
-        integer(c_int) function vlistMergedLevel(vlistID,varID,levelID) bind(c,name='vlistMergedLevel')
+        function vlistMergedLevel(vlistID,varID,levelID) bind(c,name='vlistMergedLevel')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: levelID
-       end function vlistMergedLevel
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: levelID
+          integer(kind=c_int) :: vlistMergedLevel
+        end function vlistMergedLevel
       end interface
-  
       interface
         subroutine vlistDefVarEnsemble(vlistID,varID,ensID,ensCount,forecast_type) bind(c,name='vlistDefVarEnsemble')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: ensID
-          integer(c_int), value :: ensCount
-          integer(c_int), value :: forecast_type
-       end subroutine vlistDefVarEnsemble
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: ensID
+          integer(kind=c_int), value :: ensCount
+          integer(kind=c_int), value :: forecast_type
+        end subroutine vlistDefVarEnsemble
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarEnsemble(vlistID,varID,ensID,ensCount,forecast_type) bind(c,name='vlistInqVarEnsemble')
+        function vlistInqVarEnsemble(vlistID,varID,ensID,ensCount,forecast_type) bind(c,name='vlistInqVarEnsemble')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), intent(out) :: ensID
-          integer(c_int), intent(out) :: ensCount
-          integer(c_int), intent(out) :: forecast_type
-       end function vlistInqVarEnsemble
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), intent(out) :: ensID
+          integer(kind=c_int), intent(out) :: ensCount
+          integer(kind=c_int), intent(out) :: forecast_type
+          integer(kind=c_int) :: vlistInqVarEnsemble
+        end function vlistInqVarEnsemble
       end interface
-  
       interface
         subroutine cdiClearAdditionalKeys() bind(c,name='cdiClearAdditionalKeys')
-       end subroutine cdiClearAdditionalKeys
+        end subroutine cdiClearAdditionalKeys
       end interface
-  
       interface
         subroutine cdiDefAdditionalKey(string) bind(c,name='cdiDefAdditionalKey')
           import :: c_char
-          character(c_char), dimension(*) :: string
-       end subroutine cdiDefAdditionalKey
+          character(kind=c_char), dimension(*) :: string
+        end subroutine cdiDefAdditionalKey
       end interface
-  
       interface
         subroutine vlistDefVarIntKey(vlistID,varID,name,value) bind(c,name='vlistDefVarIntKey')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: value
-       end subroutine vlistDefVarIntKey
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: value
+        end subroutine vlistDefVarIntKey
       end interface
-  
       interface
         subroutine vlistDefVarDblKey(vlistID,varID,name,value) bind(c,name='vlistDefVarDblKey')
           import :: c_int,c_char,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          real(c_double), value :: value
-       end subroutine vlistDefVarDblKey
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          real(kind=c_double), value :: value
+        end subroutine vlistDefVarDblKey
       end interface
-  
       interface
-        integer(c_int) function vlistHasVarKey(vlistID,varID,name) bind(c,name='vlistHasVarKey')
+        function vlistHasVarKey(vlistID,varID,name) bind(c,name='vlistHasVarKey')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end function vlistHasVarKey
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: vlistHasVarKey
+        end function vlistHasVarKey
       end interface
-  
       interface
-        real(c_double) function vlistInqVarDblKey(vlistID,varID,name) bind(c,name='vlistInqVarDblKey')
+        function vlistInqVarDblKey(vlistID,varID,name) bind(c,name='vlistInqVarDblKey')
           import :: c_int,c_char,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end function vlistInqVarDblKey
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          real(kind=c_double) :: vlistInqVarDblKey
+        end function vlistInqVarDblKey
       end interface
-  
       interface
-        integer(c_int) function vlistInqVarIntKey(vlistID,varID,name) bind(c,name='vlistInqVarIntKey')
+        function vlistInqVarIntKey(vlistID,varID,name) bind(c,name='vlistInqVarIntKey')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end function vlistInqVarIntKey
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: vlistInqVarIntKey
+        end function vlistInqVarIntKey
       end interface
-  
       interface
-        integer(c_int) function vlistInqNatts(vlistID,varID,nattsp) bind(c,name='vlistInqNatts')
+        function vlistInqNatts(vlistID,varID,nattsp) bind(c,name='vlistInqNatts')
           import :: c_int
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), intent(out) :: nattsp
-       end function vlistInqNatts
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), intent(out) :: nattsp
+          integer(kind=c_int) :: vlistInqNatts
+        end function vlistInqNatts
       end interface
-  
       interface
-        integer(c_int) function vlistInqAtt(vlistID,varID,attrnum,name,typep,lenp) bind(c,name='vlistInqAtt')
+        function vlistInqAtt(vlistID,varID,attrnum,name,typep,lenp) bind(c,name='vlistInqAtt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          integer(c_int), value :: attrnum
-          character(c_char), dimension(*) :: name
-          integer(c_int), intent(out) :: typep
-          integer(c_int), intent(out) :: lenp
-       end function vlistInqAtt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          integer(kind=c_int), value :: attrnum
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), intent(out) :: typep
+          integer(kind=c_int), intent(out) :: lenp
+          integer(kind=c_int) :: vlistInqAtt
+        end function vlistInqAtt
       end interface
-  
       interface
-        integer(c_int) function vlistDelAtt(vlistID,varID,name) bind(c,name='vlistDelAtt')
+        function vlistDelAtt(vlistID,varID,name) bind(c,name='vlistDelAtt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-       end function vlistDelAtt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: vlistDelAtt
+        end function vlistDelAtt
       end interface
-  
       interface
-        integer(c_int) function vlistDefAttInt(vlistID,varID,name,type,len,ip_vec) bind(c,name='vlistDefAttInt')
+        function vlistDefAttInt(vlistID,varID,name,type,len,ip_vec) bind(c,name='vlistDefAttInt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: type
-          integer(c_int), value :: len
-          integer(c_int), intent(in),dimension(*) :: ip_vec
-       end function vlistDefAttInt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: type
+          integer(kind=c_int), value :: len
+          integer(kind=c_int), intent(in),dimension(*) :: ip_vec
+          integer(kind=c_int) :: vlistDefAttInt
+        end function vlistDefAttInt
       end interface
-  
       interface
-        integer(c_int) function vlistDefAttFlt(vlistID,varID,name,type,len,dp_vec) bind(c,name='vlistDefAttFlt')
+        function vlistDefAttFlt(vlistID,varID,name,type,len,dp_vec) bind(c,name='vlistDefAttFlt')
           import :: c_int,c_char,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: type
-          integer(c_int), value :: len
-          real(c_double), intent(in),dimension(*) :: dp_vec
-       end function vlistDefAttFlt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: type
+          integer(kind=c_int), value :: len
+          real(kind=c_double), intent(in),dimension(*) :: dp_vec
+          integer(kind=c_int) :: vlistDefAttFlt
+        end function vlistDefAttFlt
       end interface
-  
       interface
-        integer(c_int) function vlistDefAttTxt(vlistID,varID,name,len,tp_cbuf) bind(c,name='vlistDefAttTxt')
+        function vlistDefAttTxt(vlistID,varID,name,len,tp_cbuf) bind(c,name='vlistDefAttTxt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: len
-          character(c_char), dimension(*) :: tp_cbuf
-       end function vlistDefAttTxt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: len
+          character(kind=c_char), dimension(*) :: tp_cbuf
+          integer(kind=c_int) :: vlistDefAttTxt
+        end function vlistDefAttTxt
       end interface
-  
       interface
-        integer(c_int) function vlistInqAttInt(vlistID,varID,name,mlen,ip_vec) bind(c,name='vlistInqAttInt')
+        function vlistInqAttInt(vlistID,varID,name,mlen,ip_vec) bind(c,name='vlistInqAttInt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: mlen
-          integer(c_int), intent(out),dimension(*) :: ip_vec
-       end function vlistInqAttInt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: mlen
+          integer(kind=c_int), intent(out),dimension(*) :: ip_vec
+          integer(kind=c_int) :: vlistInqAttInt
+        end function vlistInqAttInt
       end interface
-  
       interface
-        integer(c_int) function vlistInqAttFlt(vlistID,varID,name,mlen,dp_vec) bind(c,name='vlistInqAttFlt')
+        function vlistInqAttFlt(vlistID,varID,name,mlen,dp_vec) bind(c,name='vlistInqAttFlt')
           import :: c_int,c_char,c_double
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: mlen
-          real(c_double), intent(out),dimension(*) :: dp_vec
-       end function vlistInqAttFlt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: mlen
+          real(kind=c_double), intent(out),dimension(*) :: dp_vec
+          integer(kind=c_int) :: vlistInqAttFlt
+        end function vlistInqAttFlt
       end interface
-  
       interface
-        integer(c_int) function vlistInqAttTxt(vlistID,varID,name,mlen,tp_cbuf) bind(c,name='vlistInqAttTxt')
+        function vlistInqAttTxt(vlistID,varID,name,mlen,tp_cbuf) bind(c,name='vlistInqAttTxt')
           import :: c_int,c_char
-          integer(c_int), value :: vlistID
-          integer(c_int), value :: varID
-          character(c_char), dimension(*) :: name
-          integer(c_int), value :: mlen
-          character(c_char), dimension(*) :: tp_cbuf
-       end function vlistInqAttTxt
+          integer(kind=c_int), value :: vlistID
+          integer(kind=c_int), value :: varID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), value :: mlen
+          character(kind=c_char), dimension(*) :: tp_cbuf
+          integer(kind=c_int) :: vlistInqAttTxt
+        end function vlistInqAttTxt
       end interface
-  
       interface
         subroutine gridName(gridtype,gridnamev) bind(c,name='gridName')
           import :: c_int,c_char
-          integer(c_int), value :: gridtype
-          character(c_char), dimension(*) :: gridnamev
-       end subroutine gridName
+          integer(kind=c_int), value :: gridtype
+          character(kind=c_char), dimension(*) :: gridnamev
+        end subroutine gridName
       end interface
-  
-      interface
-        character(c_char) function gridNamePtr(gridtype) bind(c,name='gridNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: gridtype
-       end function gridNamePtr
-      end interface
-  
       interface
         subroutine gridCompress(gridID) bind(c,name='gridCompress')
           import :: c_int
-          integer(c_int), value :: gridID
-       end subroutine gridCompress
+          integer(kind=c_int), value :: gridID
+        end subroutine gridCompress
       end interface
-  
       interface
         subroutine gridDefMaskGME(gridID,mask_vec) bind(c,name='gridDefMaskGME')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), intent(in),dimension(*) :: mask_vec
-       end subroutine gridDefMaskGME
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), intent(in),dimension(*) :: mask_vec
+        end subroutine gridDefMaskGME
       end interface
-  
       interface
-        integer(c_int) function gridInqMaskGME(gridID,mask_vec) bind(c,name='gridInqMaskGME')
+        function gridInqMaskGME(gridID,mask_vec) bind(c,name='gridInqMaskGME')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), intent(out),dimension(*) :: mask_vec
-       end function gridInqMaskGME
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), intent(out),dimension(*) :: mask_vec
+          integer(kind=c_int) :: gridInqMaskGME
+        end function gridInqMaskGME
       end interface
-  
       interface
         subroutine gridDefMask(gridID,mask_vec) bind(c,name='gridDefMask')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), intent(in),dimension(*) :: mask_vec
-       end subroutine gridDefMask
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), intent(in),dimension(*) :: mask_vec
+        end subroutine gridDefMask
       end interface
-  
       interface
-        integer(c_int) function gridInqMask(gridID,mask_vec) bind(c,name='gridInqMask')
+        function gridInqMask(gridID,mask_vec) bind(c,name='gridInqMask')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), intent(out),dimension(*) :: mask_vec
-       end function gridInqMask
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), intent(out),dimension(*) :: mask_vec
+          integer(kind=c_int) :: gridInqMask
+        end function gridInqMask
       end interface
-  
       interface
         subroutine gridPrint(gridID,opt) bind(c,name='gridPrint')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: opt
-       end subroutine gridPrint
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: opt
+        end subroutine gridPrint
       end interface
-  
       interface
-        integer(c_int) function gridCreate(gridtype,size) bind(c,name='gridCreate')
+        function gridCreate(gridtype,size) bind(c,name='gridCreate')
           import :: c_int
-          integer(c_int), value :: gridtype
-          integer(c_int), value :: size
-       end function gridCreate
+          integer(kind=c_int), value :: gridtype
+          integer(kind=c_int), value :: size
+          integer(kind=c_int) :: gridCreate
+        end function gridCreate
       end interface
-  
       interface
         subroutine gridDestroy(gridID) bind(c,name='gridDestroy')
           import :: c_int
-          integer(c_int), value :: gridID
-       end subroutine gridDestroy
+          integer(kind=c_int), value :: gridID
+        end subroutine gridDestroy
       end interface
-  
       interface
-        integer(c_int) function gridDuplicate(gridID) bind(c,name='gridDuplicate')
+        function gridDuplicate(gridID) bind(c,name='gridDuplicate')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridDuplicate
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridDuplicate
+        end function gridDuplicate
       end interface
-  
       interface
-        integer(c_int) function gridInqType(gridID) bind(c,name='gridInqType')
+        function gridInqType(gridID) bind(c,name='gridInqType')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqType
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqType
+        end function gridInqType
       end interface
-  
       interface
-        integer(c_int) function gridInqSize(gridID) bind(c,name='gridInqSize')
+        function gridInqSize(gridID) bind(c,name='gridInqSize')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqSize
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqSize
+        end function gridInqSize
       end interface
-  
       interface
         subroutine gridDefXsize(gridID,xsize) bind(c,name='gridDefXsize')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: xsize
-       end subroutine gridDefXsize
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: xsize
+        end subroutine gridDefXsize
       end interface
-  
       interface
-        integer(c_int) function gridInqXsize(gridID) bind(c,name='gridInqXsize')
+        function gridInqXsize(gridID) bind(c,name='gridInqXsize')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqXsize
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqXsize
+        end function gridInqXsize
       end interface
-  
       interface
         subroutine gridDefYsize(gridID,ysize) bind(c,name='gridDefYsize')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: ysize
-       end subroutine gridDefYsize
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: ysize
+        end subroutine gridDefYsize
       end interface
-  
       interface
-        integer(c_int) function gridInqYsize(gridID) bind(c,name='gridInqYsize')
+        function gridInqYsize(gridID) bind(c,name='gridInqYsize')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqYsize
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqYsize
+        end function gridInqYsize
       end interface
-  
       interface
         subroutine gridDefNP(gridID,np) bind(c,name='gridDefNP')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: np
-       end subroutine gridDefNP
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: np
+        end subroutine gridDefNP
       end interface
-  
       interface
-        integer(c_int) function gridInqNP(gridID) bind(c,name='gridInqNP')
+        function gridInqNP(gridID) bind(c,name='gridInqNP')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqNP
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqNP
+        end function gridInqNP
       end interface
-  
       interface
         subroutine gridDefXvals(gridID,xvals_vec) bind(c,name='gridDefXvals')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(in),dimension(*) :: xvals_vec
-       end subroutine gridDefXvals
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(in),dimension(*) :: xvals_vec
+        end subroutine gridDefXvals
       end interface
-  
       interface
-        integer(c_int) function gridInqXvals(gridID,xvals_vec) bind(c,name='gridInqXvals')
+        function gridInqXvals(gridID,xvals_vec) bind(c,name='gridInqXvals')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out),dimension(*) :: xvals_vec
-       end function gridInqXvals
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out),dimension(*) :: xvals_vec
+          integer(kind=c_int) :: gridInqXvals
+        end function gridInqXvals
       end interface
-  
       interface
         subroutine gridDefYvals(gridID,yvals_vec) bind(c,name='gridDefYvals')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(in),dimension(*) :: yvals_vec
-       end subroutine gridDefYvals
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(in),dimension(*) :: yvals_vec
+        end subroutine gridDefYvals
       end interface
-  
       interface
-        integer(c_int) function gridInqYvals(gridID,yvals_vec) bind(c,name='gridInqYvals')
+        function gridInqYvals(gridID,yvals_vec) bind(c,name='gridInqYvals')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out),dimension(*) :: yvals_vec
-       end function gridInqYvals
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out),dimension(*) :: yvals_vec
+          integer(kind=c_int) :: gridInqYvals
+        end function gridInqYvals
       end interface
-  
       interface
         subroutine gridDefXname(gridID,xname) bind(c,name='gridDefXname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xname
-       end subroutine gridDefXname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xname
+        end subroutine gridDefXname
       end interface
-  
       interface
         subroutine gridInqXname(gridID,xname) bind(c,name='gridInqXname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xname
-       end subroutine gridInqXname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xname
+        end subroutine gridInqXname
       end interface
-  
       interface
         subroutine gridDefXlongname(gridID,xlongname) bind(c,name='gridDefXlongname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xlongname
-       end subroutine gridDefXlongname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xlongname
+        end subroutine gridDefXlongname
       end interface
-  
       interface
         subroutine gridInqXlongname(gridID,xlongname) bind(c,name='gridInqXlongname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xlongname
-       end subroutine gridInqXlongname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xlongname
+        end subroutine gridInqXlongname
       end interface
-  
       interface
         subroutine gridDefXunits(gridID,xunits) bind(c,name='gridDefXunits')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xunits
-       end subroutine gridDefXunits
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xunits
+        end subroutine gridDefXunits
       end interface
-  
       interface
         subroutine gridInqXunits(gridID,xunits) bind(c,name='gridInqXunits')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xunits
-       end subroutine gridInqXunits
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xunits
+        end subroutine gridInqXunits
       end interface
-  
       interface
         subroutine gridDefYname(gridID,yname) bind(c,name='gridDefYname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: yname
-       end subroutine gridDefYname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: yname
+        end subroutine gridDefYname
       end interface
-  
       interface
         subroutine gridInqYname(gridID,yname) bind(c,name='gridInqYname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: yname
-       end subroutine gridInqYname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: yname
+        end subroutine gridInqYname
       end interface
-  
       interface
         subroutine gridDefYlongname(gridID,ylongname) bind(c,name='gridDefYlongname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: ylongname
-       end subroutine gridDefYlongname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: ylongname
+        end subroutine gridDefYlongname
       end interface
-  
       interface
         subroutine gridInqYlongname(gridID,ylongname) bind(c,name='gridInqYlongname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: ylongname
-       end subroutine gridInqYlongname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: ylongname
+        end subroutine gridInqYlongname
       end interface
-  
       interface
         subroutine gridDefYunits(gridID,yunits) bind(c,name='gridDefYunits')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: yunits
-       end subroutine gridDefYunits
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: yunits
+        end subroutine gridDefYunits
       end interface
-  
       interface
         subroutine gridInqYunits(gridID,yunits) bind(c,name='gridInqYunits')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: yunits
-       end subroutine gridInqYunits
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: yunits
+        end subroutine gridInqYunits
       end interface
-  
       interface
         subroutine gridInqXstdname(gridID,xstdname) bind(c,name='gridInqXstdname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: xstdname
-       end subroutine gridInqXstdname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: xstdname
+        end subroutine gridInqXstdname
       end interface
-  
       interface
         subroutine gridInqYstdname(gridID,ystdname) bind(c,name='gridInqYstdname')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: ystdname
-       end subroutine gridInqYstdname
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: ystdname
+        end subroutine gridInqYstdname
       end interface
-  
       interface
         subroutine gridDefPrec(gridID,prec) bind(c,name='gridDefPrec')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: prec
-       end subroutine gridDefPrec
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: prec
+        end subroutine gridDefPrec
       end interface
-  
       interface
-        integer(c_int) function gridInqPrec(gridID) bind(c,name='gridInqPrec')
+        function gridInqPrec(gridID) bind(c,name='gridInqPrec')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqPrec
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqPrec
+        end function gridInqPrec
       end interface
-  
       interface
-        real(c_double) function gridInqXval(gridID,index) bind(c,name='gridInqXval')
+        function gridInqXval(gridID,index) bind(c,name='gridInqXval')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          integer(c_int), value :: index
-       end function gridInqXval
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: index
+          real(kind=c_double) :: gridInqXval
+        end function gridInqXval
       end interface
-  
       interface
-        real(c_double) function gridInqYval(gridID,index) bind(c,name='gridInqYval')
+        function gridInqYval(gridID,index) bind(c,name='gridInqYval')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          integer(c_int), value :: index
-       end function gridInqYval
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: index
+          real(kind=c_double) :: gridInqYval
+        end function gridInqYval
       end interface
-  
       interface
-        real(c_double) function gridInqXinc(gridID) bind(c,name='gridInqXinc')
+        function gridInqXinc(gridID) bind(c,name='gridInqXinc')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-       end function gridInqXinc
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double) :: gridInqXinc
+        end function gridInqXinc
       end interface
-  
       interface
-        real(c_double) function gridInqYinc(gridID) bind(c,name='gridInqYinc')
+        function gridInqYinc(gridID) bind(c,name='gridInqYinc')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-       end function gridInqYinc
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double) :: gridInqYinc
+        end function gridInqYinc
       end interface
-  
       interface
-        integer(c_int) function gridIsCircular(gridID) bind(c,name='gridIsCircular')
+        function gridIsCircular(gridID) bind(c,name='gridIsCircular')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridIsCircular
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridIsCircular
+        end function gridIsCircular
       end interface
-  
       interface
-        integer(c_int) function gridIsRotated(gridID) bind(c,name='gridIsRotated')
+        function gridIsRotated(gridID) bind(c,name='gridIsRotated')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridIsRotated
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridIsRotated
+        end function gridIsRotated
       end interface
-  
       interface
         subroutine gridDefXpole(gridID,xpole) bind(c,name='gridDefXpole')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: xpole
-       end subroutine gridDefXpole
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: xpole
+        end subroutine gridDefXpole
       end interface
-  
       interface
-        real(c_double) function gridInqXpole(gridID) bind(c,name='gridInqXpole')
+        function gridInqXpole(gridID) bind(c,name='gridInqXpole')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-       end function gridInqXpole
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double) :: gridInqXpole
+        end function gridInqXpole
       end interface
-  
       interface
         subroutine gridDefYpole(gridID,ypole) bind(c,name='gridDefYpole')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: ypole
-       end subroutine gridDefYpole
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: ypole
+        end subroutine gridDefYpole
       end interface
-  
       interface
-        real(c_double) function gridInqYpole(gridID) bind(c,name='gridInqYpole')
+        function gridInqYpole(gridID) bind(c,name='gridInqYpole')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-       end function gridInqYpole
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double) :: gridInqYpole
+        end function gridInqYpole
       end interface
-  
       interface
         subroutine gridDefAngle(gridID,angle) bind(c,name='gridDefAngle')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: angle
-       end subroutine gridDefAngle
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: angle
+        end subroutine gridDefAngle
       end interface
-  
       interface
-        real(c_double) function gridInqAngle(gridID) bind(c,name='gridInqAngle')
+        function gridInqAngle(gridID) bind(c,name='gridInqAngle')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-       end function gridInqAngle
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double) :: gridInqAngle
+        end function gridInqAngle
       end interface
-  
       interface
-        integer(c_int) function gridInqTrunc(gridID) bind(c,name='gridInqTrunc')
+        function gridInqTrunc(gridID) bind(c,name='gridInqTrunc')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqTrunc
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqTrunc
+        end function gridInqTrunc
       end interface
-  
       interface
         subroutine gridDefTrunc(gridID,trunc) bind(c,name='gridDefTrunc')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: trunc
-       end subroutine gridDefTrunc
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: trunc
+        end subroutine gridDefTrunc
       end interface
-  
       interface
         subroutine gridDefGMEnd(gridID,nd) bind(c,name='gridDefGMEnd')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: nd
-       end subroutine gridDefGMEnd
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: nd
+        end subroutine gridDefGMEnd
       end interface
-  
       interface
-        integer(c_int) function gridInqGMEnd(gridID) bind(c,name='gridInqGMEnd')
+        function gridInqGMEnd(gridID) bind(c,name='gridInqGMEnd')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqGMEnd
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqGMEnd
+        end function gridInqGMEnd
       end interface
-  
       interface
         subroutine gridDefGMEni(gridID,ni) bind(c,name='gridDefGMEni')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: ni
-       end subroutine gridDefGMEni
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: ni
+        end subroutine gridDefGMEni
       end interface
-  
       interface
-        integer(c_int) function gridInqGMEni(gridID) bind(c,name='gridInqGMEni')
+        function gridInqGMEni(gridID) bind(c,name='gridInqGMEni')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqGMEni
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqGMEni
+        end function gridInqGMEni
       end interface
-  
       interface
         subroutine gridDefGMEni2(gridID,ni2) bind(c,name='gridDefGMEni2')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: ni2
-       end subroutine gridDefGMEni2
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: ni2
+        end subroutine gridDefGMEni2
       end interface
-  
       interface
-        integer(c_int) function gridInqGMEni2(gridID) bind(c,name='gridInqGMEni2')
+        function gridInqGMEni2(gridID) bind(c,name='gridInqGMEni2')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqGMEni2
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqGMEni2
+        end function gridInqGMEni2
       end interface
-  
       interface
         subroutine gridDefGMEni3(gridID,ni3) bind(c,name='gridDefGMEni3')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: ni3
-       end subroutine gridDefGMEni3
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: ni3
+        end subroutine gridDefGMEni3
       end interface
-  
       interface
-        integer(c_int) function gridInqGMEni3(gridID) bind(c,name='gridInqGMEni3')
+        function gridInqGMEni3(gridID) bind(c,name='gridInqGMEni3')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqGMEni3
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqGMEni3
+        end function gridInqGMEni3
       end interface
-  
       interface
         subroutine gridDefNumber(gridID,number) bind(c,name='gridDefNumber')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: number
-       end subroutine gridDefNumber
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: number
+        end subroutine gridDefNumber
       end interface
-  
       interface
-        integer(c_int) function gridInqNumber(gridID) bind(c,name='gridInqNumber')
+        function gridInqNumber(gridID) bind(c,name='gridInqNumber')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqNumber
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqNumber
+        end function gridInqNumber
       end interface
-  
       interface
         subroutine gridDefPosition(gridID,position) bind(c,name='gridDefPosition')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: position
-       end subroutine gridDefPosition
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: position
+        end subroutine gridDefPosition
       end interface
-  
       interface
-        integer(c_int) function gridInqPosition(gridID) bind(c,name='gridInqPosition')
+        function gridInqPosition(gridID) bind(c,name='gridInqPosition')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqPosition
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqPosition
+        end function gridInqPosition
       end interface
-  
       interface
         subroutine gridDefReference(gridID,reference) bind(c,name='gridDefReference')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: reference
-       end subroutine gridDefReference
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: reference
+        end subroutine gridDefReference
       end interface
-  
       interface
-        integer(c_int) function gridInqReference(gridID,reference) bind(c,name='gridInqReference')
+        function gridInqReference(gridID,reference) bind(c,name='gridInqReference')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: reference
-       end function gridInqReference
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: reference
+          integer(kind=c_int) :: gridInqReference
+        end function gridInqReference
       end interface
-  
       interface
         subroutine gridDefUUID(gridID,uuid_cbuf) bind(c,name='gridDefUUID')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: uuid_cbuf
-       end subroutine gridDefUUID
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: uuid_cbuf
+        end subroutine gridDefUUID
       end interface
-  
       interface
         subroutine gridInqUUID(gridID,uuid_cbuf) bind(c,name='gridInqUUID')
           import :: c_int,c_char
-          integer(c_int), value :: gridID
-          character(c_char), dimension(*) :: uuid_cbuf
-       end subroutine gridInqUUID
+          integer(kind=c_int), value :: gridID
+          character(kind=c_char), dimension(*) :: uuid_cbuf
+        end subroutine gridInqUUID
       end interface
-  
       interface
         subroutine gridDefLCC(gridID,originLon,originLat,lonParY,lat1,lat2,xinc,yinc,projflag,scanflag) bind(c,name='gridDefLCC')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: originLon
-          real(c_double), value :: originLat
-          real(c_double), value :: lonParY
-          real(c_double), value :: lat1
-          real(c_double), value :: lat2
-          real(c_double), value :: xinc
-          real(c_double), value :: yinc
-          integer(c_int), value :: projflag
-          integer(c_int), value :: scanflag
-       end subroutine gridDefLCC
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: originLon
+          real(kind=c_double), value :: originLat
+          real(kind=c_double), value :: lonParY
+          real(kind=c_double), value :: lat1
+          real(kind=c_double), value :: lat2
+          real(kind=c_double), value :: xinc
+          real(kind=c_double), value :: yinc
+          integer(kind=c_int), value :: projflag
+          integer(kind=c_int), value :: scanflag
+        end subroutine gridDefLCC
       end interface
-  
       interface
         subroutine gridInqLCC(gridID,originLon,originLat,lonParY,lat1,lat2,xinc,yinc,projflag,scanflag) bind(c,name='gridInqLCC')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out) :: originLon
-          real(c_double), intent(out) :: originLat
-          real(c_double), intent(out) :: lonParY
-          real(c_double), intent(out) :: lat1
-          real(c_double), intent(out) :: lat2
-          real(c_double), intent(out) :: xinc
-          real(c_double), intent(out) :: yinc
-          integer(c_int), intent(out) :: projflag
-          integer(c_int), intent(out) :: scanflag
-       end subroutine gridInqLCC
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out) :: originLon
+          real(kind=c_double), intent(out) :: originLat
+          real(kind=c_double), intent(out) :: lonParY
+          real(kind=c_double), intent(out) :: lat1
+          real(kind=c_double), intent(out) :: lat2
+          real(kind=c_double), intent(out) :: xinc
+          real(kind=c_double), intent(out) :: yinc
+          integer(kind=c_int), intent(out) :: projflag
+          integer(kind=c_int), intent(out) :: scanflag
+        end subroutine gridInqLCC
       end interface
-  
       interface
         subroutine gridDefLcc2(gridID,earth_radius,lon_0,lat_0,lat_1,lat_2) bind(c,name='gridDefLcc2')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: earth_radius
-          real(c_double), value :: lon_0
-          real(c_double), value :: lat_0
-          real(c_double), value :: lat_1
-          real(c_double), value :: lat_2
-       end subroutine gridDefLcc2
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: earth_radius
+          real(kind=c_double), value :: lon_0
+          real(kind=c_double), value :: lat_0
+          real(kind=c_double), value :: lat_1
+          real(kind=c_double), value :: lat_2
+        end subroutine gridDefLcc2
       end interface
-  
       interface
         subroutine gridInqLcc2(gridID,earth_radius,lon_0,lat_0,lat_1,lat_2) bind(c,name='gridInqLcc2')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out) :: earth_radius
-          real(c_double), intent(out) :: lon_0
-          real(c_double), intent(out) :: lat_0
-          real(c_double), intent(out) :: lat_1
-          real(c_double), intent(out) :: lat_2
-       end subroutine gridInqLcc2
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out) :: earth_radius
+          real(kind=c_double), intent(out) :: lon_0
+          real(kind=c_double), intent(out) :: lat_0
+          real(kind=c_double), intent(out) :: lat_1
+          real(kind=c_double), intent(out) :: lat_2
+        end subroutine gridInqLcc2
       end interface
-  
       interface
         subroutine gridDefLaea(gridID,earth_radius,lon_0,lat_0) bind(c,name='gridDefLaea')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), value :: earth_radius
-          real(c_double), value :: lon_0
-          real(c_double), value :: lat_0
-       end subroutine gridDefLaea
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), value :: earth_radius
+          real(kind=c_double), value :: lon_0
+          real(kind=c_double), value :: lat_0
+        end subroutine gridDefLaea
       end interface
-  
       interface
         subroutine gridInqLaea(gridID,earth_radius,lon_0,lat_0) bind(c,name='gridInqLaea')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out) :: earth_radius
-          real(c_double), intent(out) :: lon_0
-          real(c_double), intent(out) :: lat_0
-       end subroutine gridInqLaea
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out) :: earth_radius
+          real(kind=c_double), intent(out) :: lon_0
+          real(kind=c_double), intent(out) :: lat_0
+        end subroutine gridInqLaea
       end interface
-  
       interface
         subroutine gridDefArea(gridID,area_vec) bind(c,name='gridDefArea')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(in),dimension(*) :: area_vec
-       end subroutine gridDefArea
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(in),dimension(*) :: area_vec
+        end subroutine gridDefArea
       end interface
-  
       interface
         subroutine gridInqArea(gridID,area_vec) bind(c,name='gridInqArea')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out),dimension(*) :: area_vec
-       end subroutine gridInqArea
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out),dimension(*) :: area_vec
+        end subroutine gridInqArea
       end interface
-  
       interface
-        integer(c_int) function gridHasArea(gridID) bind(c,name='gridHasArea')
+        function gridHasArea(gridID) bind(c,name='gridHasArea')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridHasArea
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridHasArea
+        end function gridHasArea
       end interface
-  
       interface
         subroutine gridDefNvertex(gridID,nvertex) bind(c,name='gridDefNvertex')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: nvertex
-       end subroutine gridDefNvertex
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: nvertex
+        end subroutine gridDefNvertex
       end interface
-  
       interface
-        integer(c_int) function gridInqNvertex(gridID) bind(c,name='gridInqNvertex')
+        function gridInqNvertex(gridID) bind(c,name='gridInqNvertex')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqNvertex
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqNvertex
+        end function gridInqNvertex
       end interface
-  
       interface
         subroutine gridDefXbounds(gridID,xbounds_vec) bind(c,name='gridDefXbounds')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(in),dimension(*) :: xbounds_vec
-       end subroutine gridDefXbounds
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(in),dimension(*) :: xbounds_vec
+        end subroutine gridDefXbounds
       end interface
-  
       interface
-        integer(c_int) function gridInqXbounds(gridID,xbounds_vec) bind(c,name='gridInqXbounds')
+        function gridInqXbounds(gridID,xbounds_vec) bind(c,name='gridInqXbounds')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out),dimension(*) :: xbounds_vec
-       end function gridInqXbounds
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out),dimension(*) :: xbounds_vec
+          integer(kind=c_int) :: gridInqXbounds
+        end function gridInqXbounds
       end interface
-  
       interface
         subroutine gridDefYbounds(gridID,ybounds_vec) bind(c,name='gridDefYbounds')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(in),dimension(*) :: ybounds_vec
-       end subroutine gridDefYbounds
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(in),dimension(*) :: ybounds_vec
+        end subroutine gridDefYbounds
       end interface
-  
       interface
-        integer(c_int) function gridInqYbounds(gridID,ybounds_vec) bind(c,name='gridInqYbounds')
+        function gridInqYbounds(gridID,ybounds_vec) bind(c,name='gridInqYbounds')
           import :: c_int,c_double
-          integer(c_int), value :: gridID
-          real(c_double), intent(out),dimension(*) :: ybounds_vec
-       end function gridInqYbounds
+          integer(kind=c_int), value :: gridID
+          real(kind=c_double), intent(out),dimension(*) :: ybounds_vec
+          integer(kind=c_int) :: gridInqYbounds
+        end function gridInqYbounds
       end interface
-  
       interface
         subroutine gridDefRowlon(gridID,nrowlon,rowlon_vec) bind(c,name='gridDefRowlon')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: nrowlon
-          integer(c_int), intent(in),dimension(*) :: rowlon_vec
-       end subroutine gridDefRowlon
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: nrowlon
+          integer(kind=c_int), intent(in),dimension(*) :: rowlon_vec
+        end subroutine gridDefRowlon
       end interface
-  
       interface
         subroutine gridInqRowlon(gridID,rowlon_vec) bind(c,name='gridInqRowlon')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), intent(out),dimension(*) :: rowlon_vec
-       end subroutine gridInqRowlon
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), intent(out),dimension(*) :: rowlon_vec
+        end subroutine gridInqRowlon
       end interface
-  
       interface
         subroutine gridChangeType(gridID,gridtype) bind(c,name='gridChangeType')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: gridtype
-       end subroutine gridChangeType
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: gridtype
+        end subroutine gridChangeType
       end interface
-  
       interface
         subroutine gridDefComplexPacking(gridID,lpack) bind(c,name='gridDefComplexPacking')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: lpack
-       end subroutine gridDefComplexPacking
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: lpack
+        end subroutine gridDefComplexPacking
       end interface
-  
       interface
-        integer(c_int) function gridInqComplexPacking(gridID) bind(c,name='gridInqComplexPacking')
+        function gridInqComplexPacking(gridID) bind(c,name='gridInqComplexPacking')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function gridInqComplexPacking
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: gridInqComplexPacking
+        end function gridInqComplexPacking
       end interface
-  
       interface
         subroutine zaxisName(zaxistype,zaxisnamev) bind(c,name='zaxisName')
           import :: c_int,c_char
-          integer(c_int), value :: zaxistype
-          character(c_char), dimension(*) :: zaxisnamev
-       end subroutine zaxisName
+          integer(kind=c_int), value :: zaxistype
+          character(kind=c_char), dimension(*) :: zaxisnamev
+        end subroutine zaxisName
       end interface
-  
       interface
-        integer(c_int) function zaxisCreate(zaxistype,size) bind(c,name='zaxisCreate')
+        function zaxisCreate(zaxistype,size) bind(c,name='zaxisCreate')
           import :: c_int
-          integer(c_int), value :: zaxistype
-          integer(c_int), value :: size
-       end function zaxisCreate
+          integer(kind=c_int), value :: zaxistype
+          integer(kind=c_int), value :: size
+          integer(kind=c_int) :: zaxisCreate
+        end function zaxisCreate
       end interface
-  
       interface
         subroutine zaxisDestroy(zaxisID) bind(c,name='zaxisDestroy')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end subroutine zaxisDestroy
+          integer(kind=c_int), value :: zaxisID
+        end subroutine zaxisDestroy
       end interface
-  
       interface
-        integer(c_int) function zaxisInqType(zaxisID) bind(c,name='zaxisInqType')
+        function zaxisInqType(zaxisID) bind(c,name='zaxisInqType')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqType
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqType
+        end function zaxisInqType
       end interface
-  
       interface
-        integer(c_int) function zaxisInqSize(zaxisID) bind(c,name='zaxisInqSize')
+        function zaxisInqSize(zaxisID) bind(c,name='zaxisInqSize')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqSize
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqSize
+        end function zaxisInqSize
       end interface
-  
       interface
-        integer(c_int) function zaxisDuplicate(zaxisID) bind(c,name='zaxisDuplicate')
+        function zaxisDuplicate(zaxisID) bind(c,name='zaxisDuplicate')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisDuplicate
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisDuplicate
+        end function zaxisDuplicate
       end interface
-  
       interface
         subroutine zaxisResize(zaxisID,size) bind(c,name='zaxisResize')
           import :: c_int
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: size
-       end subroutine zaxisResize
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: size
+        end subroutine zaxisResize
       end interface
-  
       interface
         subroutine zaxisPrint(zaxisID) bind(c,name='zaxisPrint')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end subroutine zaxisPrint
+          integer(kind=c_int), value :: zaxisID
+        end subroutine zaxisPrint
       end interface
-  
       interface
         subroutine zaxisDefLevels(zaxisID,levels_vec) bind(c,name='zaxisDefLevels')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(in),dimension(*) :: levels_vec
-       end subroutine zaxisDefLevels
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(in),dimension(*) :: levels_vec
+        end subroutine zaxisDefLevels
       end interface
-  
       interface
         subroutine zaxisInqLevels(zaxisID,levels_vec) bind(c,name='zaxisInqLevels')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(out),dimension(*) :: levels_vec
-       end subroutine zaxisInqLevels
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(out),dimension(*) :: levels_vec
+        end subroutine zaxisInqLevels
       end interface
-  
       interface
         subroutine zaxisDefLevel(zaxisID,levelID,levels) bind(c,name='zaxisDefLevel')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: levelID
-          real(c_double), value :: levels
-       end subroutine zaxisDefLevel
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_double), value :: levels
+        end subroutine zaxisDefLevel
       end interface
-  
       interface
-        real(c_double) function zaxisInqLevel(zaxisID,levelID) bind(c,name='zaxisInqLevel')
+        function zaxisInqLevel(zaxisID,levelID) bind(c,name='zaxisInqLevel')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: levelID
-       end function zaxisInqLevel
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: levelID
+          real(kind=c_double) :: zaxisInqLevel
+        end function zaxisInqLevel
       end interface
-  
       interface
         subroutine zaxisDefNlevRef(gridID,nhlev) bind(c,name='zaxisDefNlevRef')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: nhlev
-       end subroutine zaxisDefNlevRef
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: nhlev
+        end subroutine zaxisDefNlevRef
       end interface
-  
       interface
-        integer(c_int) function zaxisInqNlevRef(gridID) bind(c,name='zaxisInqNlevRef')
+        function zaxisInqNlevRef(gridID) bind(c,name='zaxisInqNlevRef')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function zaxisInqNlevRef
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: zaxisInqNlevRef
+        end function zaxisInqNlevRef
       end interface
-  
       interface
         subroutine zaxisDefNumber(gridID,number) bind(c,name='zaxisDefNumber')
           import :: c_int
-          integer(c_int), value :: gridID
-          integer(c_int), value :: number
-       end subroutine zaxisDefNumber
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int), value :: number
+        end subroutine zaxisDefNumber
       end interface
-  
       interface
-        integer(c_int) function zaxisInqNumber(gridID) bind(c,name='zaxisInqNumber')
+        function zaxisInqNumber(gridID) bind(c,name='zaxisInqNumber')
           import :: c_int
-          integer(c_int), value :: gridID
-       end function zaxisInqNumber
+          integer(kind=c_int), value :: gridID
+          integer(kind=c_int) :: zaxisInqNumber
+        end function zaxisInqNumber
       end interface
-  
       interface
         subroutine zaxisDefUUID(zaxisID,uuid_cbuf) bind(c,name='zaxisDefUUID')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: uuid_cbuf
-       end subroutine zaxisDefUUID
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: uuid_cbuf
+        end subroutine zaxisDefUUID
       end interface
-  
       interface
         subroutine zaxisInqUUID(zaxisID,uuid_cbuf) bind(c,name='zaxisInqUUID')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: uuid_cbuf
-       end subroutine zaxisInqUUID
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: uuid_cbuf
+        end subroutine zaxisInqUUID
       end interface
-  
       interface
         subroutine zaxisDefName(zaxisID,name) bind(c,name='zaxisDefName')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: name
-       end subroutine zaxisDefName
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: name
+        end subroutine zaxisDefName
       end interface
-  
       interface
         subroutine zaxisInqName(zaxisID,name) bind(c,name='zaxisInqName')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: name
-       end subroutine zaxisInqName
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: name
+        end subroutine zaxisInqName
       end interface
-  
       interface
         subroutine zaxisDefLongname(zaxisID,longname) bind(c,name='zaxisDefLongname')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: longname
-       end subroutine zaxisDefLongname
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: longname
+        end subroutine zaxisDefLongname
       end interface
-  
       interface
         subroutine zaxisInqLongname(zaxisID,longname) bind(c,name='zaxisInqLongname')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: longname
-       end subroutine zaxisInqLongname
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: longname
+        end subroutine zaxisInqLongname
       end interface
-  
       interface
         subroutine zaxisDefUnits(zaxisID,units) bind(c,name='zaxisDefUnits')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: units
-       end subroutine zaxisDefUnits
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: units
+        end subroutine zaxisDefUnits
       end interface
-  
       interface
         subroutine zaxisInqUnits(zaxisID,units) bind(c,name='zaxisInqUnits')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: units
-       end subroutine zaxisInqUnits
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: units
+        end subroutine zaxisInqUnits
       end interface
-  
       interface
         subroutine zaxisInqStdname(zaxisID,stdname) bind(c,name='zaxisInqStdname')
           import :: c_int,c_char
-          integer(c_int), value :: zaxisID
-          character(c_char), dimension(*) :: stdname
-       end subroutine zaxisInqStdname
+          integer(kind=c_int), value :: zaxisID
+          character(kind=c_char), dimension(*) :: stdname
+        end subroutine zaxisInqStdname
       end interface
-  
       interface
         subroutine zaxisDefPrec(zaxisID,prec) bind(c,name='zaxisDefPrec')
           import :: c_int
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: prec
-       end subroutine zaxisDefPrec
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: prec
+        end subroutine zaxisDefPrec
       end interface
-  
       interface
-        integer(c_int) function zaxisInqPrec(zaxisID) bind(c,name='zaxisInqPrec')
+        function zaxisInqPrec(zaxisID) bind(c,name='zaxisInqPrec')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqPrec
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqPrec
+        end function zaxisInqPrec
       end interface
-  
       interface
         subroutine zaxisDefPositive(zaxisID,positive) bind(c,name='zaxisDefPositive')
           import :: c_int
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: positive
-       end subroutine zaxisDefPositive
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: positive
+        end subroutine zaxisDefPositive
       end interface
-  
       interface
-        integer(c_int) function zaxisInqPositive(zaxisID) bind(c,name='zaxisInqPositive')
+        function zaxisInqPositive(zaxisID) bind(c,name='zaxisInqPositive')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqPositive
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqPositive
+        end function zaxisInqPositive
       end interface
-  
       interface
         subroutine zaxisDefLtype(zaxisID,ltype) bind(c,name='zaxisDefLtype')
           import :: c_int
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: ltype
-       end subroutine zaxisDefLtype
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: ltype
+        end subroutine zaxisDefLtype
       end interface
-  
       interface
-        integer(c_int) function zaxisInqLtype(zaxisID) bind(c,name='zaxisInqLtype')
+        function zaxisInqLtype(zaxisID) bind(c,name='zaxisInqLtype')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqLtype
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqLtype
+        end function zaxisInqLtype
       end interface
-  
       interface
-        real(c_double) function zaxisInqLevelsPtr(zaxisID) bind(c,name='zaxisInqLevelsPtr')
+        function zaxisInqLevelsPtr(zaxisID) bind(c,name='zaxisInqLevelsPtr')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-       end function zaxisInqLevelsPtr
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double) :: zaxisInqLevelsPtr
+        end function zaxisInqLevelsPtr
       end interface
-  
       interface
         subroutine zaxisDefVct(zaxisID,size,vct_vec) bind(c,name='zaxisDefVct')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: size
-          real(c_double), intent(in),dimension(*) :: vct_vec
-       end subroutine zaxisDefVct
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: size
+          real(kind=c_double), intent(in),dimension(*) :: vct_vec
+        end subroutine zaxisDefVct
       end interface
-  
       interface
         subroutine zaxisInqVct(zaxisID,vct_vec) bind(c,name='zaxisInqVct')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(out),dimension(*) :: vct_vec
-       end subroutine zaxisInqVct
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(out),dimension(*) :: vct_vec
+        end subroutine zaxisInqVct
       end interface
-  
       interface
-        integer(c_int) function zaxisInqVctSize(zaxisID) bind(c,name='zaxisInqVctSize')
+        function zaxisInqVctSize(zaxisID) bind(c,name='zaxisInqVctSize')
           import :: c_int
-          integer(c_int), value :: zaxisID
-       end function zaxisInqVctSize
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int) :: zaxisInqVctSize
+        end function zaxisInqVctSize
       end interface
-  
       interface
-        real(c_double) function zaxisInqVctPtr(zaxisID) bind(c,name='zaxisInqVctPtr')
+        function zaxisInqVctPtr(zaxisID) bind(c,name='zaxisInqVctPtr')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-       end function zaxisInqVctPtr
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double) :: zaxisInqVctPtr
+        end function zaxisInqVctPtr
       end interface
-  
       interface
         subroutine zaxisDefLbounds(zaxisID,lbounds_vec) bind(c,name='zaxisDefLbounds')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(in),dimension(*) :: lbounds_vec
-       end subroutine zaxisDefLbounds
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(in),dimension(*) :: lbounds_vec
+        end subroutine zaxisDefLbounds
       end interface
-  
       interface
-        integer(c_int) function zaxisInqLbounds(zaxisID,lbounds_vec) bind(c,name='zaxisInqLbounds')
+        function zaxisInqLbounds(zaxisID,lbounds_vec) bind(c,name='zaxisInqLbounds')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(out),dimension(*) :: lbounds_vec
-       end function zaxisInqLbounds
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(out),dimension(*) :: lbounds_vec
+          integer(kind=c_int) :: zaxisInqLbounds
+        end function zaxisInqLbounds
       end interface
-  
       interface
-        real(c_double) function zaxisInqLbound(zaxisID,index) bind(c,name='zaxisInqLbound')
+        function zaxisInqLbound(zaxisID,index) bind(c,name='zaxisInqLbound')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: index
-       end function zaxisInqLbound
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: index
+          real(kind=c_double) :: zaxisInqLbound
+        end function zaxisInqLbound
       end interface
-  
       interface
         subroutine zaxisDefUbounds(zaxisID,ubounds_vec) bind(c,name='zaxisDefUbounds')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(in),dimension(*) :: ubounds_vec
-       end subroutine zaxisDefUbounds
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(in),dimension(*) :: ubounds_vec
+        end subroutine zaxisDefUbounds
       end interface
-  
       interface
-        integer(c_int) function zaxisInqUbounds(zaxisID,ubounds_vec) bind(c,name='zaxisInqUbounds')
+        function zaxisInqUbounds(zaxisID,ubounds_vec) bind(c,name='zaxisInqUbounds')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(out),dimension(*) :: ubounds_vec
-       end function zaxisInqUbounds
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(out),dimension(*) :: ubounds_vec
+          integer(kind=c_int) :: zaxisInqUbounds
+        end function zaxisInqUbounds
       end interface
-  
       interface
-        real(c_double) function zaxisInqUbound(zaxisID,index) bind(c,name='zaxisInqUbound')
+        function zaxisInqUbound(zaxisID,index) bind(c,name='zaxisInqUbound')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: index
-       end function zaxisInqUbound
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: index
+          real(kind=c_double) :: zaxisInqUbound
+        end function zaxisInqUbound
       end interface
-  
       interface
         subroutine zaxisDefWeights(zaxisID,weights_vec) bind(c,name='zaxisDefWeights')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(in),dimension(*) :: weights_vec
-       end subroutine zaxisDefWeights
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(in),dimension(*) :: weights_vec
+        end subroutine zaxisDefWeights
       end interface
-  
       interface
-        integer(c_int) function zaxisInqWeights(zaxisID,weights_vec) bind(c,name='zaxisInqWeights')
+        function zaxisInqWeights(zaxisID,weights_vec) bind(c,name='zaxisInqWeights')
           import :: c_int,c_double
-          integer(c_int), value :: zaxisID
-          real(c_double), intent(out),dimension(*) :: weights_vec
-       end function zaxisInqWeights
+          integer(kind=c_int), value :: zaxisID
+          real(kind=c_double), intent(out),dimension(*) :: weights_vec
+          integer(kind=c_int) :: zaxisInqWeights
+        end function zaxisInqWeights
       end interface
-  
       interface
         subroutine zaxisChangeType(zaxisID,zaxistype) bind(c,name='zaxisChangeType')
           import :: c_int
-          integer(c_int), value :: zaxisID
-          integer(c_int), value :: zaxistype
-       end subroutine zaxisChangeType
+          integer(kind=c_int), value :: zaxisID
+          integer(kind=c_int), value :: zaxistype
+        end subroutine zaxisChangeType
       end interface
-  
       interface
-        integer(c_int) function taxisCreate(timetype) bind(c,name='taxisCreate')
+        function taxisCreate(timetype) bind(c,name='taxisCreate')
           import :: c_int
-          integer(c_int), value :: timetype
-       end function taxisCreate
+          integer(kind=c_int), value :: timetype
+          integer(kind=c_int) :: taxisCreate
+        end function taxisCreate
       end interface
-  
       interface
         subroutine taxisDestroy(taxisID) bind(c,name='taxisDestroy')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end subroutine taxisDestroy
+          integer(kind=c_int), value :: taxisID
+        end subroutine taxisDestroy
       end interface
-  
       interface
-        integer(c_int) function taxisDuplicate(taxisID) bind(c,name='taxisDuplicate')
+        function taxisDuplicate(taxisID) bind(c,name='taxisDuplicate')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisDuplicate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisDuplicate
+        end function taxisDuplicate
       end interface
-  
       interface
         subroutine taxisCopyTimestep(taxisIDdes,taxisIDsrc) bind(c,name='taxisCopyTimestep')
           import :: c_int
-          integer(c_int), value :: taxisIDdes
-          integer(c_int), value :: taxisIDsrc
-       end subroutine taxisCopyTimestep
+          integer(kind=c_int), value :: taxisIDdes
+          integer(kind=c_int), value :: taxisIDsrc
+        end subroutine taxisCopyTimestep
       end interface
-  
       interface
         subroutine taxisDefType(taxisID,type) bind(c,name='taxisDefType')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: type
-       end subroutine taxisDefType
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: type
+        end subroutine taxisDefType
       end interface
-  
       interface
         subroutine taxisDefVdate(taxisID,date) bind(c,name='taxisDefVdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: date
-       end subroutine taxisDefVdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: date
+        end subroutine taxisDefVdate
       end interface
-  
       interface
         subroutine taxisDefVtime(taxisID,time) bind(c,name='taxisDefVtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: time
-       end subroutine taxisDefVtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: time
+        end subroutine taxisDefVtime
       end interface
-  
       interface
-        integer(c_int) function taxisInqVdate(taxisID) bind(c,name='taxisInqVdate')
+        function taxisInqVdate(taxisID) bind(c,name='taxisInqVdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqVdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqVdate
+        end function taxisInqVdate
       end interface
-  
       interface
-        integer(c_int) function taxisInqVtime(taxisID) bind(c,name='taxisInqVtime')
+        function taxisInqVtime(taxisID) bind(c,name='taxisInqVtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqVtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqVtime
+        end function taxisInqVtime
       end interface
-  
       interface
         subroutine taxisDefRdate(taxisID,date) bind(c,name='taxisDefRdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: date
-       end subroutine taxisDefRdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: date
+        end subroutine taxisDefRdate
       end interface
-  
       interface
         subroutine taxisDefRtime(taxisID,time) bind(c,name='taxisDefRtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: time
-       end subroutine taxisDefRtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: time
+        end subroutine taxisDefRtime
       end interface
-  
       interface
-        integer(c_int) function taxisInqRdate(taxisID) bind(c,name='taxisInqRdate')
+        function taxisInqRdate(taxisID) bind(c,name='taxisInqRdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqRdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqRdate
+        end function taxisInqRdate
       end interface
-  
       interface
-        integer(c_int) function taxisInqRtime(taxisID) bind(c,name='taxisInqRtime')
+        function taxisInqRtime(taxisID) bind(c,name='taxisInqRtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqRtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqRtime
+        end function taxisInqRtime
       end interface
-  
       interface
         subroutine taxisDefFdate(taxisID,date) bind(c,name='taxisDefFdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: date
-       end subroutine taxisDefFdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: date
+        end subroutine taxisDefFdate
       end interface
-  
       interface
         subroutine taxisDefFtime(taxisID,time) bind(c,name='taxisDefFtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: time
-       end subroutine taxisDefFtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: time
+        end subroutine taxisDefFtime
       end interface
-  
       interface
-        integer(c_int) function taxisInqFdate(taxisID) bind(c,name='taxisInqFdate')
+        function taxisInqFdate(taxisID) bind(c,name='taxisInqFdate')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqFdate
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqFdate
+        end function taxisInqFdate
       end interface
-  
       interface
-        integer(c_int) function taxisInqFtime(taxisID) bind(c,name='taxisInqFtime')
+        function taxisInqFtime(taxisID) bind(c,name='taxisInqFtime')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqFtime
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqFtime
+        end function taxisInqFtime
       end interface
-  
       interface
-        integer(c_int) function taxisHasBounds(taxisID) bind(c,name='taxisHasBounds')
+        function taxisHasBounds(taxisID) bind(c,name='taxisHasBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisHasBounds
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisHasBounds
+        end function taxisHasBounds
       end interface
-  
       interface
         subroutine taxisDeleteBounds(taxisID) bind(c,name='taxisDeleteBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end subroutine taxisDeleteBounds
+          integer(kind=c_int), value :: taxisID
+        end subroutine taxisDeleteBounds
       end interface
-  
       interface
         subroutine taxisDefVdateBounds(taxisID,vdate_lb,vdate_ub) bind(c,name='taxisDefVdateBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: vdate_lb
-          integer(c_int), value :: vdate_ub
-       end subroutine taxisDefVdateBounds
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: vdate_lb
+          integer(kind=c_int), value :: vdate_ub
+        end subroutine taxisDefVdateBounds
       end interface
-  
       interface
         subroutine taxisDefVtimeBounds(taxisID,vtime_lb,vtime_ub) bind(c,name='taxisDefVtimeBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: vtime_lb
-          integer(c_int), value :: vtime_ub
-       end subroutine taxisDefVtimeBounds
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: vtime_lb
+          integer(kind=c_int), value :: vtime_ub
+        end subroutine taxisDefVtimeBounds
       end interface
-  
       interface
         subroutine taxisInqVdateBounds(taxisID,vdate_lb,vdate_ub) bind(c,name='taxisInqVdateBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), intent(out) :: vdate_lb
-          integer(c_int), intent(out) :: vdate_ub
-       end subroutine taxisInqVdateBounds
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), intent(out) :: vdate_lb
+          integer(kind=c_int), intent(out) :: vdate_ub
+        end subroutine taxisInqVdateBounds
       end interface
-  
       interface
         subroutine taxisInqVtimeBounds(taxisID,vtime_lb,vtime_ub) bind(c,name='taxisInqVtimeBounds')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), intent(out) :: vtime_lb
-          integer(c_int), intent(out) :: vtime_ub
-       end subroutine taxisInqVtimeBounds
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), intent(out) :: vtime_lb
+          integer(kind=c_int), intent(out) :: vtime_ub
+        end subroutine taxisInqVtimeBounds
       end interface
-  
       interface
         subroutine taxisDefCalendar(taxisID,calendar) bind(c,name='taxisDefCalendar')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: calendar
-       end subroutine taxisDefCalendar
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: calendar
+        end subroutine taxisDefCalendar
       end interface
-  
       interface
-        integer(c_int) function taxisInqCalendar(taxisID) bind(c,name='taxisInqCalendar')
+        function taxisInqCalendar(taxisID) bind(c,name='taxisInqCalendar')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqCalendar
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqCalendar
+        end function taxisInqCalendar
       end interface
-  
       interface
         subroutine taxisDefTunit(taxisID,tunit) bind(c,name='taxisDefTunit')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: tunit
-       end subroutine taxisDefTunit
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: tunit
+        end subroutine taxisDefTunit
       end interface
-  
       interface
-        integer(c_int) function taxisInqTunit(taxisID) bind(c,name='taxisInqTunit')
+        function taxisInqTunit(taxisID) bind(c,name='taxisInqTunit')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqTunit
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqTunit
+        end function taxisInqTunit
       end interface
-  
       interface
         subroutine taxisDefForecastTunit(taxisID,tunit) bind(c,name='taxisDefForecastTunit')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: tunit
-       end subroutine taxisDefForecastTunit
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: tunit
+        end subroutine taxisDefForecastTunit
       end interface
-  
       interface
-        integer(c_int) function taxisInqForecastTunit(taxisID) bind(c,name='taxisInqForecastTunit')
+        function taxisInqForecastTunit(taxisID) bind(c,name='taxisInqForecastTunit')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqForecastTunit
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqForecastTunit
+        end function taxisInqForecastTunit
       end interface
-  
       interface
         subroutine taxisDefForecastPeriod(taxisID,fc_period) bind(c,name='taxisDefForecastPeriod')
           import :: c_int,c_double
-          integer(c_int), value :: taxisID
-          real(c_double), value :: fc_period
-       end subroutine taxisDefForecastPeriod
+          integer(kind=c_int), value :: taxisID
+          real(kind=c_double), value :: fc_period
+        end subroutine taxisDefForecastPeriod
       end interface
-  
       interface
-        real(c_double) function taxisInqForecastPeriod(taxisID) bind(c,name='taxisInqForecastPeriod')
+        function taxisInqForecastPeriod(taxisID) bind(c,name='taxisInqForecastPeriod')
           import :: c_int,c_double
-          integer(c_int), value :: taxisID
-       end function taxisInqForecastPeriod
+          integer(kind=c_int), value :: taxisID
+          real(kind=c_double) :: taxisInqForecastPeriod
+        end function taxisInqForecastPeriod
       end interface
-  
       interface
         subroutine taxisDefNumavg(taxisID,numavg) bind(c,name='taxisDefNumavg')
           import :: c_int
-          integer(c_int), value :: taxisID
-          integer(c_int), value :: numavg
-       end subroutine taxisDefNumavg
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int), value :: numavg
+        end subroutine taxisDefNumavg
       end interface
-  
       interface
-        integer(c_int) function taxisInqType(taxisID) bind(c,name='taxisInqType')
+        function taxisInqType(taxisID) bind(c,name='taxisInqType')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqType
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqType
+        end function taxisInqType
       end interface
-  
       interface
-        integer(c_int) function taxisInqNumavg(taxisID) bind(c,name='taxisInqNumavg')
+        function taxisInqNumavg(taxisID) bind(c,name='taxisInqNumavg')
           import :: c_int
-          integer(c_int), value :: taxisID
-       end function taxisInqNumavg
+          integer(kind=c_int), value :: taxisID
+          integer(kind=c_int) :: taxisInqNumavg
+        end function taxisInqNumavg
       end interface
-  
-      interface
-        character(c_char) function tunitNamePtr(tunitID) bind(c,name='tunitNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: tunitID
-       end function tunitNamePtr
-      end interface
-  
       interface
-        integer(c_int) function institutDef(center,subcenter,name,longname) bind(c,name='institutDef')
+        function institutDef(center,subcenter,name,longname) bind(c,name='institutDef')
           import :: c_int,c_char
-          integer(c_int), value :: center
-          integer(c_int), value :: subcenter
-          character(c_char), dimension(*) :: name
-          character(c_char), dimension(*) :: longname
-       end function institutDef
+          integer(kind=c_int), value :: center
+          integer(kind=c_int), value :: subcenter
+          character(kind=c_char), dimension(*) :: name
+          character(kind=c_char), dimension(*) :: longname
+          integer(kind=c_int) :: institutDef
+        end function institutDef
       end interface
-  
       interface
-        integer(c_int) function institutInq(center,subcenter,name,longname) bind(c,name='institutInq')
+        function institutInq(center,subcenter,name,longname) bind(c,name='institutInq')
           import :: c_int,c_char
-          integer(c_int), value :: center
-          integer(c_int), value :: subcenter
-          character(c_char), dimension(*) :: name
-          character(c_char), dimension(*) :: longname
-       end function institutInq
+          integer(kind=c_int), value :: center
+          integer(kind=c_int), value :: subcenter
+          character(kind=c_char), dimension(*) :: name
+          character(kind=c_char), dimension(*) :: longname
+          integer(kind=c_int) :: institutInq
+        end function institutInq
       end interface
-  
       interface
-        integer(c_int) function institutInqNumber() bind(c,name='institutInqNumber')
+        function institutInqNumber() bind(c,name='institutInqNumber')
           import :: c_int
-       end function institutInqNumber
+          integer(kind=c_int) :: institutInqNumber
+        end function institutInqNumber
       end interface
-  
       interface
-        integer(c_int) function institutInqCenter(instID) bind(c,name='institutInqCenter')
+        function institutInqCenter(instID) bind(c,name='institutInqCenter')
           import :: c_int
-          integer(c_int), value :: instID
-       end function institutInqCenter
+          integer(kind=c_int), value :: instID
+          integer(kind=c_int) :: institutInqCenter
+        end function institutInqCenter
       end interface
-  
       interface
-        integer(c_int) function institutInqSubcenter(instID) bind(c,name='institutInqSubcenter')
+        function institutInqSubcenter(instID) bind(c,name='institutInqSubcenter')
           import :: c_int
-          integer(c_int), value :: instID
-       end function institutInqSubcenter
-      end interface
-  
-      interface
-        character(c_char) function institutInqNamePtr(instID) bind(c,name='institutInqNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: instID
-       end function institutInqNamePtr
+          integer(kind=c_int), value :: instID
+          integer(kind=c_int) :: institutInqSubcenter
+        end function institutInqSubcenter
       end interface
-  
       interface
-        character(c_char) function institutInqLongnamePtr(instID) bind(c,name='institutInqLongnamePtr')
+        function modelDef(instID,modelgribID,name) bind(c,name='modelDef')
           import :: c_int,c_char
-          integer(c_int), value :: instID
-       end function institutInqLongnamePtr
+          integer(kind=c_int), value :: instID
+          integer(kind=c_int), value :: modelgribID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: modelDef
+        end function modelDef
       end interface
-  
-      interface
-        integer(c_int) function modelDef(instID,modelgribID,name) bind(c,name='modelDef')
-          import :: c_int,c_char
-          integer(c_int), value :: instID
-          integer(c_int), value :: modelgribID
-          character(c_char), dimension(*) :: name
-       end function modelDef
-      end interface
-  
       interface
-        integer(c_int) function modelInq(instID,modelgribID,name) bind(c,name='modelInq')
+        function modelInq(instID,modelgribID,name) bind(c,name='modelInq')
           import :: c_int,c_char
-          integer(c_int), value :: instID
-          integer(c_int), value :: modelgribID
-          character(c_char), dimension(*) :: name
-       end function modelInq
+          integer(kind=c_int), value :: instID
+          integer(kind=c_int), value :: modelgribID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: modelInq
+        end function modelInq
       end interface
-  
       interface
-        integer(c_int) function modelInqInstitut(modelID) bind(c,name='modelInqInstitut')
+        function modelInqInstitut(modelID) bind(c,name='modelInqInstitut')
           import :: c_int
-          integer(c_int), value :: modelID
-       end function modelInqInstitut
+          integer(kind=c_int), value :: modelID
+          integer(kind=c_int) :: modelInqInstitut
+        end function modelInqInstitut
       end interface
-  
       interface
-        integer(c_int) function modelInqGribID(modelID) bind(c,name='modelInqGribID')
+        function modelInqGribID(modelID) bind(c,name='modelInqGribID')
           import :: c_int
-          integer(c_int), value :: modelID
-       end function modelInqGribID
+          integer(kind=c_int), value :: modelID
+          integer(kind=c_int) :: modelInqGribID
+        end function modelInqGribID
       end interface
-  
-      interface
-        character(c_char) function modelInqNamePtr(modelID) bind(c,name='modelInqNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: modelID
-       end function modelInqNamePtr
-      end interface
-  
       interface
         subroutine tableWriteC(filename,tableID) bind(c,name='tableWriteC')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: filename
-          integer(c_int), value :: tableID
-       end subroutine tableWriteC
+          character(kind=c_char), dimension(*) :: filename
+          integer(kind=c_int), value :: tableID
+        end subroutine tableWriteC
       end interface
-  
       interface
         subroutine tableWrite(filename,tableID) bind(c,name='tableWrite')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: filename
-          integer(c_int), value :: tableID
-       end subroutine tableWrite
+          character(kind=c_char), dimension(*) :: filename
+          integer(kind=c_int), value :: tableID
+        end subroutine tableWrite
       end interface
-  
       interface
-        integer(c_int) function tableRead(tablefile) bind(c,name='tableRead')
+        function tableRead(tablefile) bind(c,name='tableRead')
           import :: c_char,c_int
-          character(c_char), dimension(*) :: tablefile
-       end function tableRead
+          character(kind=c_char), dimension(*) :: tablefile
+          integer(kind=c_int) :: tableRead
+        end function tableRead
       end interface
-  
       interface
-        integer(c_int) function tableDef(modelID,tablenum,tablename) bind(c,name='tableDef')
+        function tableDef(modelID,tablenum,tablename) bind(c,name='tableDef')
           import :: c_int,c_char
-          integer(c_int), value :: modelID
-          integer(c_int), value :: tablenum
-          character(c_char), dimension(*) :: tablename
-       end function tableDef
+          integer(kind=c_int), value :: modelID
+          integer(kind=c_int), value :: tablenum
+          character(kind=c_char), dimension(*) :: tablename
+          integer(kind=c_int) :: tableDef
+        end function tableDef
       end interface
-  
-      interface
-        character(c_char) function tableInqNamePtr(tableID) bind(c,name='tableInqNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: tableID
-       end function tableInqNamePtr
-      end interface
-  
       interface
         subroutine tableDefEntry(tableID,code,name,longname,units) bind(c,name='tableDefEntry')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: code
-          character(c_char), dimension(*) :: name
-          character(c_char), dimension(*) :: longname
-          character(c_char), dimension(*) :: units
-       end subroutine tableDefEntry
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int), value :: code
+          character(kind=c_char), dimension(*) :: name
+          character(kind=c_char), dimension(*) :: longname
+          character(kind=c_char), dimension(*) :: units
+        end subroutine tableDefEntry
       end interface
-  
       interface
-        integer(c_int) function tableInq(modelID,tablenum,tablename) bind(c,name='tableInq')
+        function tableInq(modelID,tablenum,tablename) bind(c,name='tableInq')
           import :: c_int,c_char
-          integer(c_int), value :: modelID
-          integer(c_int), value :: tablenum
-          character(c_char), dimension(*) :: tablename
-       end function tableInq
+          integer(kind=c_int), value :: modelID
+          integer(kind=c_int), value :: tablenum
+          character(kind=c_char), dimension(*) :: tablename
+          integer(kind=c_int) :: tableInq
+        end function tableInq
       end interface
-  
       interface
-        integer(c_int) function tableInqNumber() bind(c,name='tableInqNumber')
+        function tableInqNumber() bind(c,name='tableInqNumber')
           import :: c_int
-       end function tableInqNumber
+          integer(kind=c_int) :: tableInqNumber
+        end function tableInqNumber
       end interface
-  
       interface
-        integer(c_int) function tableInqNum(tableID) bind(c,name='tableInqNum')
+        function tableInqNum(tableID) bind(c,name='tableInqNum')
           import :: c_int
-          integer(c_int), value :: tableID
-       end function tableInqNum
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int) :: tableInqNum
+        end function tableInqNum
       end interface
-  
       interface
-        integer(c_int) function tableInqModel(tableID) bind(c,name='tableInqModel')
+        function tableInqModel(tableID) bind(c,name='tableInqModel')
           import :: c_int
-          integer(c_int), value :: tableID
-       end function tableInqModel
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int) :: tableInqModel
+        end function tableInqModel
       end interface
-  
       interface
         subroutine tableInqPar(tableID,code,name,longname,units) bind(c,name='tableInqPar')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: code
-          character(c_char), dimension(*) :: name
-          character(c_char), dimension(*) :: longname
-          character(c_char), dimension(*) :: units
-       end subroutine tableInqPar
-      end interface
-  
-      interface
-        integer(c_int) function tableInqParCode(tableID,name,code) bind(c,name='tableInqParCode')
-          import :: c_int,c_char
-          integer(c_int), value :: tableID
-          character(c_char), dimension(*) :: name
-          integer(c_int), intent(out) :: code
-       end function tableInqParCode
-      end interface
-  
-      interface
-        integer(c_int) function tableInqParName(tableID,code,name) bind(c,name='tableInqParName')
-          import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: code
-          character(c_char), dimension(*) :: name
-       end function tableInqParName
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int), value :: code
+          character(kind=c_char), dimension(*) :: name
+          character(kind=c_char), dimension(*) :: longname
+          character(kind=c_char), dimension(*) :: units
+        end subroutine tableInqPar
       end interface
-  
       interface
-        integer(c_int) function tableInqParLongname(tableID,code,longname) bind(c,name='tableInqParLongname')
+        function tableInqParCode(tableID,name,code) bind(c,name='tableInqParCode')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: code
-          character(c_char), dimension(*) :: longname
-       end function tableInqParLongname
+          integer(kind=c_int), value :: tableID
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int), intent(out) :: code
+          integer(kind=c_int) :: tableInqParCode
+        end function tableInqParCode
       end interface
-  
       interface
-        integer(c_int) function tableInqParUnits(tableID,code,units) bind(c,name='tableInqParUnits')
+        function tableInqParName(tableID,code,name) bind(c,name='tableInqParName')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: code
-          character(c_char), dimension(*) :: units
-       end function tableInqParUnits
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int), value :: code
+          character(kind=c_char), dimension(*) :: name
+          integer(kind=c_int) :: tableInqParName
+        end function tableInqParName
       end interface
-  
-      interface
-        character(c_char) function tableInqParNamePtr(tableID,parID) bind(c,name='tableInqParNamePtr')
-          import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: parID
-       end function tableInqParNamePtr
-      end interface
-  
       interface
-        character(c_char) function tableInqParLongnamePtr(tableID,parID) bind(c,name='tableInqParLongnamePtr')
+        function tableInqParLongname(tableID,code,longname) bind(c,name='tableInqParLongname')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: parID
-       end function tableInqParLongnamePtr
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int), value :: code
+          character(kind=c_char), dimension(*) :: longname
+          integer(kind=c_int) :: tableInqParLongname
+        end function tableInqParLongname
       end interface
-  
       interface
-        character(c_char) function tableInqParUnitsPtr(tableID,parID) bind(c,name='tableInqParUnitsPtr')
+        function tableInqParUnits(tableID,code,units) bind(c,name='tableInqParUnits')
           import :: c_int,c_char
-          integer(c_int), value :: tableID
-          integer(c_int), value :: parID
-       end function tableInqParUnitsPtr
+          integer(kind=c_int), value :: tableID
+          integer(kind=c_int), value :: code
+          character(kind=c_char), dimension(*) :: units
+          integer(kind=c_int) :: tableInqParUnits
+        end function tableInqParUnits
       end interface
-  
       interface
         subroutine streamDefHistory(streamID,size,history) bind(c,name='streamDefHistory')
           import :: c_int,c_char
-          integer(c_int), value :: streamID
-          integer(c_int), value :: size
-          character(c_char), dimension(*) :: history
-       end subroutine streamDefHistory
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int), value :: size
+          character(kind=c_char), dimension(*) :: history
+        end subroutine streamDefHistory
       end interface
-  
       interface
-        integer(c_int) function streamInqHistorySize(streamID) bind(c,name='streamInqHistorySize')
+        function streamInqHistorySize(streamID) bind(c,name='streamInqHistorySize')
           import :: c_int
-          integer(c_int), value :: streamID
-       end function streamInqHistorySize
+          integer(kind=c_int), value :: streamID
+          integer(kind=c_int) :: streamInqHistorySize
+        end function streamInqHistorySize
       end interface
-  
       interface
         subroutine streamInqHistoryString(streamID,history) bind(c,name='streamInqHistoryString')
           import :: c_int,c_char
-          integer(c_int), value :: streamID
-          character(c_char), dimension(*) :: history
-       end subroutine streamInqHistoryString
+          integer(kind=c_int), value :: streamID
+          character(kind=c_char), dimension(*) :: history
+        end subroutine streamInqHistoryString
       end interface
-  
+      interface
+        subroutine gribapiLibraryVersion(major_version,minor_version,revision_version) bind(c,name='gribapiLibraryVersion')
+          import :: c_int
+          integer(kind=c_int), intent(out) :: major_version
+          integer(kind=c_int), intent(out) :: minor_version
+          integer(kind=c_int), intent(out) :: revision_version
+        end subroutine gribapiLibraryVersion
+      end interface
+
+      public :: strlen
+      public :: getchar
+      public :: getchar_unlocked
       public :: cdiReset
       public :: cdiStringError
       public :: cdiDebug
@@ -3175,12 +2969,15 @@ module mo_cdi
       public :: streamFilename
       public :: streamFilesuffix
       public :: streamNtsteps
+      public :: streamInqNvars
       public :: streamWriteVar
       public :: streamWriteVarF
       public :: streamReadVar
+      public :: streamReadVarF
       public :: streamWriteVarSlice
       public :: streamWriteVarSliceF
       public :: streamReadVarSlice
+      public :: streamReadVarSliceF
       public :: streamDefRecord
       public :: streamInqRecord
       public :: streamWriteRecord
@@ -3272,6 +3069,8 @@ module mo_cdi
       public :: vlistInqVarTimaccu
       public :: vlistDefVarTypeOfGeneratingProcess
       public :: vlistInqVarTypeOfGeneratingProcess
+      public :: vlistDefVarProductDefinitionTemplate
+      public :: vlistInqVarProductDefinitionTemplate
       public :: vlistInqVarSize
       public :: vlistDefIndex
       public :: vlistInqIndex
@@ -3501,7 +3300,9 @@ module mo_cdi
       public :: streamDefHistory
       public :: streamInqHistorySize
       public :: streamInqHistoryString
+      public :: gribapiLibraryVersion
       public :: ctrim
+      public :: c_len
 
       public :: CDI_MAX_NAME
       public :: CDI_UNDEFID
@@ -3518,6 +3319,7 @@ module mo_cdi
       public :: CDI_EUFSTRUCT
       public :: CDI_EUNC4
       public :: CDI_ELIMIT
+      public :: FILETYPE_UNDEF
       public :: FILETYPE_GRB
       public :: FILETYPE_GRB2
       public :: FILETYPE_NC
@@ -3646,14 +3448,15 @@ module mo_cdi
       public :: TAXIS_FORECAST
       public :: TUNIT_SECOND
       public :: TUNIT_MINUTE
-      public :: TUNIT_HOUR
-      public :: TUNIT_DAY
-      public :: TUNIT_MONTH
-      public :: TUNIT_YEAR
       public :: TUNIT_QUARTER
+      public :: TUNIT_30MINUTES
+      public :: TUNIT_HOUR
       public :: TUNIT_3HOURS
       public :: TUNIT_6HOURS
       public :: TUNIT_12HOURS
+      public :: TUNIT_DAY
+      public :: TUNIT_MONTH
+      public :: TUNIT_YEAR
       public :: CALENDAR_STANDARD
       public :: CALENDAR_PROLEPTIC
       public :: CALENDAR_360DAYS
@@ -3662,22 +3465,273 @@ module mo_cdi
       public :: CALENDAR_NONE
 
 contains
+      function cdiStringError(cdiErrno)
+        integer(kind=c_int), value :: cdiErrno
+        interface
+          function cdiStringError_c(cdiErrno) bind(c,name='cdiStringError')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: cdiErrno
+            type(c_ptr) :: cdiStringError_c
+          end function cdiStringError_c
+        end interface
+        character(len=1, kind=c_char), pointer :: cdiStringError(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = cdiStringError_c(cdiErrno)
+        cdiStringError => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, cdiStringError, slen)
+      end function cdiStringError
+      function cdiLibraryVersion()
+        interface
+          function cdiLibraryVersion_c() bind(c,name='cdiLibraryVersion')
+            import :: c_ptr,c_char
+            type(c_ptr) :: cdiLibraryVersion_c
+          end function cdiLibraryVersion_c
+        end interface
+        character(len=1, kind=c_char), pointer :: cdiLibraryVersion(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = cdiLibraryVersion_c()
+        cdiLibraryVersion => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, cdiLibraryVersion, slen)
+      end function cdiLibraryVersion
+      function streamFilename(streamID)
+        integer(kind=c_int), value :: streamID
+        interface
+          function streamFilename_c(streamID) bind(c,name='streamFilename')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: streamID
+            type(c_ptr) :: streamFilename_c
+          end function streamFilename_c
+        end interface
+        character(len=1, kind=c_char), pointer :: streamFilename(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = streamFilename_c(streamID)
+        streamFilename => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, streamFilename, slen)
+      end function streamFilename
+      function streamFilesuffix(filetype)
+        integer(kind=c_int), value :: filetype
+        interface
+          function streamFilesuffix_c(filetype) bind(c,name='streamFilesuffix')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: filetype
+            type(c_ptr) :: streamFilesuffix_c
+          end function streamFilesuffix_c
+        end interface
+        character(len=1, kind=c_char), pointer :: streamFilesuffix(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = streamFilesuffix_c(filetype)
+        streamFilesuffix => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, streamFilesuffix, slen)
+      end function streamFilesuffix
+      function gridNamePtr(gridtype)
+        integer(kind=c_int), value :: gridtype
+        interface
+          function gridNamePtr_c(gridtype) bind(c,name='gridNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: gridtype
+            type(c_ptr) :: gridNamePtr_c
+          end function gridNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: gridNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = gridNamePtr_c(gridtype)
+        gridNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, gridNamePtr, slen)
+      end function gridNamePtr
+      function tunitNamePtr(tunitID)
+        integer(kind=c_int), value :: tunitID
+        interface
+          function tunitNamePtr_c(tunitID) bind(c,name='tunitNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: tunitID
+            type(c_ptr) :: tunitNamePtr_c
+          end function tunitNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: tunitNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = tunitNamePtr_c(tunitID)
+        tunitNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, tunitNamePtr, slen)
+      end function tunitNamePtr
+      function institutInqNamePtr(instID)
+        integer(kind=c_int), value :: instID
+        interface
+          function institutInqNamePtr_c(instID) bind(c,name='institutInqNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: instID
+            type(c_ptr) :: institutInqNamePtr_c
+          end function institutInqNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: institutInqNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = institutInqNamePtr_c(instID)
+        institutInqNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, institutInqNamePtr, slen)
+      end function institutInqNamePtr
+      function institutInqLongnamePtr(instID)
+        integer(kind=c_int), value :: instID
+        interface
+          function institutInqLongnamePtr_c(instID) bind(c,name='institutInqLongnamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: instID
+            type(c_ptr) :: institutInqLongnamePtr_c
+          end function institutInqLongnamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: institutInqLongnamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = institutInqLongnamePtr_c(instID)
+        institutInqLongnamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, institutInqLongnamePtr, slen)
+      end function institutInqLongnamePtr
+      function modelInqNamePtr(modelID)
+        integer(kind=c_int), value :: modelID
+        interface
+          function modelInqNamePtr_c(modelID) bind(c,name='modelInqNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: modelID
+            type(c_ptr) :: modelInqNamePtr_c
+          end function modelInqNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: modelInqNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = modelInqNamePtr_c(modelID)
+        modelInqNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, modelInqNamePtr, slen)
+      end function modelInqNamePtr
+      function tableInqNamePtr(tableID)
+        integer(kind=c_int), value :: tableID
+        interface
+          function tableInqNamePtr_c(tableID) bind(c,name='tableInqNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: tableID
+            type(c_ptr) :: tableInqNamePtr_c
+          end function tableInqNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: tableInqNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = tableInqNamePtr_c(tableID)
+        tableInqNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, tableInqNamePtr, slen)
+      end function tableInqNamePtr
+      function tableInqParNamePtr(tableID,parID)
+        integer(kind=c_int), value :: tableID
+        integer(kind=c_int), value :: parID
+        interface
+          function tableInqParNamePtr_c(tableID,parID) bind(c,name='tableInqParNamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: tableID
+            integer(kind=c_int), value :: parID
+            type(c_ptr) :: tableInqParNamePtr_c
+          end function tableInqParNamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: tableInqParNamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = tableInqParNamePtr_c(tableID,&
+          parID)
+        tableInqParNamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, tableInqParNamePtr, slen)
+      end function tableInqParNamePtr
+      function tableInqParLongnamePtr(tableID,parID)
+        integer(kind=c_int), value :: tableID
+        integer(kind=c_int), value :: parID
+        interface
+          function tableInqParLongnamePtr_c(tableID,parID) bind(c,name='tableInqParLongnamePtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: tableID
+            integer(kind=c_int), value :: parID
+            type(c_ptr) :: tableInqParLongnamePtr_c
+          end function tableInqParLongnamePtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: tableInqParLongnamePtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = tableInqParLongnamePtr_c(tableID,&
+          parID)
+        tableInqParLongnamePtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, tableInqParLongnamePtr, slen)
+      end function tableInqParLongnamePtr
+      function tableInqParUnitsPtr(tableID,parID)
+        integer(kind=c_int), value :: tableID
+        integer(kind=c_int), value :: parID
+        interface
+          function tableInqParUnitsPtr_c(tableID,parID) bind(c,name='tableInqParUnitsPtr')
+            import :: c_ptr,c_int,c_char
+            integer(kind=c_int), value :: tableID
+            integer(kind=c_int), value :: parID
+            type(c_ptr) :: tableInqParUnitsPtr_c
+          end function tableInqParUnitsPtr_c
+        end interface
+        character(len=1, kind=c_char), pointer :: tableInqParUnitsPtr(:)
+        type(c_ptr) :: cptr
+        integer :: slen(1)
+
+        cptr = tableInqParUnitsPtr_c(tableID,&
+          parID)
+        tableInqParUnitsPtr => null()
+        slen(1) = int(strlen(cptr))
+        call c_f_pointer(cptr, tableInqParUnitsPtr, slen)
+      end function tableInqParUnitsPtr
 
     subroutine ctrim(str)
-    use iso_c_binding
-    character(kind=c_char, len=*)  :: str
-    character                      :: c
+    character(kind=c_char) :: str(:)
+    character(kind=c_char) :: c
     integer                        :: i
 
-    do i=1,len(str)
-      c = str(i:i)
+    do i=1,size(str)
+      c = str(i)
       if (c == c_null_char) then
-        str(i:len(str)) = ' '
+        str(i:size(str)) = ' '
+        exit
       end if
     end do
 
     end subroutine ctrim
-  
+
+    function c_len(s) result(i)
+      character(kind=c_char), intent(in) :: s(:)
+      integer :: i
+      do i = 1, size(s)
+        if (s(i) == c_null_char) then
+          exit
+        end if
+      end do
+      i = i - 1
+    end function
+
 
 end module mo_cdi
-  
diff --git a/libcdi/src/model.c b/libcdi/src/model.c
index 1b101d8..0fbb7a0 100644
--- a/libcdi/src/model.c
+++ b/libcdi/src/model.c
@@ -2,6 +2,8 @@
 #  include "config.h"
 #endif
 
+#include <limits.h>
+
 #include "dmemory.h"
 #include "cdi.h"
 #include "cdi_int.h"
@@ -33,7 +35,7 @@ static int  MODEL_Debug = 0;   /* If set to 1, debugging */
 static void modelInit(void);
 
 
-static int    modelCompareP ( void * modelptr1, void * modelptr2 );
+static int modelCompareP(void *modelptr1, void *modelptr2);
 static void   modelDestroyP ( void * modelptr );
 static void   modelPrintP   ( void * modelptr, FILE * fp );
 static int    modelGetSizeP ( void * modelptr, void *context);
@@ -113,8 +115,9 @@ void modelDefaultEntries ( void )
   instID  = institutInq(  0,   1, "NCEP", NULL);
   resH[9] = modelDef(instID,  80, "T62L28MRF");
 
+  /* pre-defined models are not synchronized */
   for ( i = 0; i < nDefModels ; i++ )
-    reshSetStatus(resH[i], &modelOps, RESH_PRE_ASSIGNED);
+    reshSetStatus(resH[i], &modelOps, RESH_IN_USE);
 }
 
 static
@@ -247,9 +250,15 @@ char *modelInqNamePtr(int modelID)
 }
 
 
-int  modelCompareP ( void * modelptr1, void * modelptr2 )
+static int
+modelCompareP(void *modelptr1, void *modelptr2)
 {
-  return 0;
+  model_t *model1 = modelptr1, *model2 = modelptr2;
+  int diff = (namespaceResHDecode(model1->instID).idx
+              != namespaceResHDecode(model2->instID).idx)
+    | (model1->modelgribID != model2->modelgribID)
+    | (strcmp(model1->name, model2->name) != 0);
+  return diff;
 }
 
 
@@ -292,10 +301,11 @@ enum {
 
 static int modelGetSizeP(void * modelptr, void *context)
 {
-  model_t *p = (model_t*) modelptr;
-  int txsize = serializeGetSize(model_nints, DATATYPE_INT, context)
-    + serializeGetSize(p->name?strlen(p->name) + 1:0, DATATYPE_TXT, context);
-  return txsize;
+  model_t *p = (model_t*)modelptr;
+  size_t txsize = (size_t)serializeGetSize(model_nints, DATATYPE_INT, context)
+    + (size_t)serializeGetSize(p->name?(int)strlen(p->name) + 1:0, DATATYPE_TXT, context);
+  xassert(txsize <= INT_MAX);
+  return (int)txsize;
 }
 
 
@@ -321,8 +331,9 @@ modelUnpack(void *buf, int size, int *position, int originNamespace, void *conte
   serializeUnpack(buf, size, position, tempbuf, model_nints, DATATYPE_INT, context);
   if (tempbuf[3] != 0)
     {
-      name = (char*) xmalloc(tempbuf[3]);
-      serializeUnpack(buf, size, position, name, tempbuf[3], DATATYPE_TXT, context);
+      name = (char *)xmalloc((size_t)tempbuf[3]);
+      serializeUnpack(buf, size, position,
+                      name, tempbuf[3], DATATYPE_TXT, context);
     }
   else
     {
diff --git a/libcdi/src/namespace.c b/libcdi/src/namespace.c
index 387dce2..7f3927c 100644
--- a/libcdi/src/namespace.c
+++ b/libcdi/src/namespace.c
@@ -202,7 +202,8 @@ namespaceNew()
   else if (namespacesSize == 1)
     {
       /* make room for additional namespace */
-      struct Namespace *newNameSpaces = (struct Namespace*) xmalloc((namespacesSize + 1) * sizeof (namespaces[0]));
+      struct Namespace *newNameSpaces
+        = (struct Namespace *)xmalloc(((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
       memcpy(newNameSpaces, namespaces, sizeof (namespaces[0]));
       namespaces = newNameSpaces;
       ++namespacesSize;
@@ -212,7 +213,8 @@ namespaceNew()
     {
       /* make room for additional namespace */
       newNamespaceID = namespacesSize;
-      namespaces = (struct Namespace*) xrealloc(namespaces, (namespacesSize + 1) * sizeof (namespaces[0]));
+      namespaces
+        = (struct Namespace *)xrealloc(namespaces, ((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
       ++namespacesSize;
     }
   else /* implicit: namespacesSize >= NUM_NAMESPACES */
diff --git a/libcdi/src/pio_server.c b/libcdi/src/pio_server.c
index b0f734d..68a1fe7 100644
--- a/libcdi/src/pio_server.c
+++ b/libcdi/src/pio_server.c
@@ -532,7 +532,7 @@ buildStreamMap(struct winHeaderEntry *winDict)
 {
   int streamIDOld = CDI_UNDEFID;
   int oldStreamIdx = CDI_UNDEFID;
-  int filetype = CDI_UNDEFID;
+  int filetype = FILETYPE_UNDEF;
   int sizeStreamMap = 16;
   struct streamMapping *streamMap = (struct streamMapping *) xmalloc(sizeStreamMap * sizeof (streamMap[0]));
   int numDataEntries = winDict[0].specific.headerSize.numDataEntries;
@@ -972,7 +972,8 @@ cdiPioStreamCDFOpenWrap(const char *filename, const char *filemode,
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
       {
-        int rank, fileID;
+        /* Only needs initialization to shut up gcc */
+        int rank = -1, fileID;
         int ioMode = commInqIOMode();
         if (ioMode == PIO_NONE
             || commInqRankColl() == (rank = cdiPioNextOpenRank()))
diff --git a/libcdi/src/resource_handle.c b/libcdi/src/resource_handle.c
index 52ffb31..ed7a193 100644
--- a/libcdi/src/resource_handle.c
+++ b/libcdi/src/resource_handle.c
@@ -8,6 +8,26 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <assert.h>
+
+#if defined (HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+static
+void show_stackframe()
+{
+#if defined (HAVE_EXECINFO_H)
+  void *trace[16];
+  size_t i;
+  size_t trace_size = backtrace(trace, 16);
+  char **messages = backtrace_symbols(trace, trace_size);
+
+  fprintf(stderr, "[bt] Execution path:\n");
+  for ( i = 0; i < trace_size; ++i ) fprintf(stderr, "[bt] %s\n", messages[i]);
+  if ( messages ) free(messages);
+#endif
+}
 
 #include "dmemory.h"
 #include "resource_handle.h"
@@ -130,7 +150,7 @@ reshListCreate(int namespaceID)
   LIST_LOCK();
   if (resHListSize <= namespaceID)
     {
-      resHList = (struct resHList_t*) xrealloc(resHList, (namespaceID + 1) * sizeof (resHList[0]));
+      resHList = (struct resHList_t *)xrealloc(resHList, (namespaceID + 1) * sizeof (resHList[0]));
       for (int i = resHListSize; i <= namespaceID; ++i)
         reshListClearEntry(i);
       resHListSize = namespaceID + 1;
@@ -154,10 +174,11 @@ reshListDestruct(int namespaceID)
       for ( int j = 0; j < resHList[namespaceID].size; j++ )
         {
           listElem_t *listElem = resHList[namespaceID].resources + j;
-          if (listElem->status != RESH_UNUSED)
+          if (listElem->status & RESH_IN_USE_BIT)
             listElem->res.v.ops->valDestroy(listElem->res.v.val);
         }
       free(resHList[namespaceID].resources);
+      resHList[namespaceID].resources = NULL;
       reshListClearEntry(namespaceID);
     }
   if (resHList[callerNamespaceID].resources)
@@ -172,6 +193,7 @@ static void listDestroy ( void )
   for (int i = resHListSize; i > 0; --i)
     if (resHList[i-1].resources)
       namespaceDelete(i-1);
+  resHListSize = 0;
   free(resHList);
   resHList = NULL;
   cdiReset();
@@ -209,26 +231,25 @@ void listSizeExtend()
 {
   int nsp = namespaceGetActive ();
   int oldSize = resHList[nsp].size;
-  int newListSize = oldSize + MIN_LIST_SIZE;
+  size_t newListSize = (size_t)oldSize + MIN_LIST_SIZE;
 
   resHList[nsp].resources = (listElem_t*) xrealloc(resHList[nsp].resources,
                                                    newListSize * sizeof(listElem_t));
 
   listElem_t *r = resHList[nsp].resources;
-  for (int i = oldSize; i < newListSize; ++i)
+  for (size_t i = (size_t)oldSize; i < newListSize; ++i)
     {
-      r[i].res.free.next = i + 1;
-      r[i].res.free.prev = i - 1;
+      r[i].res.free.next = (int)i + 1;
+      r[i].res.free.prev = (int)i - 1;
       r[i].status = RESH_UNUSED;
     }
 
   if (resHList[nsp].freeHead != -1)
-    r[resHList[nsp].freeHead].res.free.next
-      = newListSize - 1;
+    r[resHList[nsp].freeHead].res.free.prev = (int)newListSize - 1;
   r[newListSize-1].res.free.next = resHList[nsp].freeHead;
   r[oldSize].res.free.prev = -1;
   resHList[nsp].freeHead = oldSize;
-  resHList[nsp].size = newListSize;
+  resHList[nsp].size = (int)newListSize;
 }
 
 /**************************************************************/
@@ -237,13 +258,17 @@ static void
 reshPut_(int nsp, int entry, void *p, const resOps *ops)
 {
   listElem_t *newListElem = resHList[nsp].resources + entry;
-  int next = newListElem->res.free.next;
+  int next = newListElem->res.free.next,
+    prev = newListElem->res.free.prev;
   if (next != -1)
-    resHList[nsp].resources[next].res.free.prev = -1;
-  resHList[nsp].freeHead = next;
+    resHList[nsp].resources[next].res.free.prev = prev;
+  if (prev != -1)
+    resHList[nsp].resources[prev].res.free.next = next;
+  else
+    resHList[nsp].freeHead = next;
   newListElem->res.v.val = p;
   newListElem->res.v.ops = ops;
-  newListElem->status = RESH_ASSIGNED;
+  newListElem->status = RESH_DESYNC_IN_USE;
 }
 
 int reshPut ( void *p, const resOps *ops )
@@ -274,18 +299,39 @@ reshRemove_(int nsp, int idx)
   int curFree = resHList[nsp].freeHead;
   listElem_t *r = resHList[nsp].resources;
   r[idx].res.free.next = curFree;
+  r[idx].res.free.prev = -1;
   if (curFree != -1)
     r[curFree].res.free.prev = idx;
-  r[idx].status = RESH_UNUSED;
+  r[idx].status = RESH_DESYNC_DELETED;
   resHList[nsp].freeHead = idx;
 }
 
-void reshRemove ( cdiResH resH, const resOps * ops )
+void reshDestroy(cdiResH resH)
 {
   int nsp;
   namespaceTuple_t nspT;
 
-  LIST_INIT(1);
+  LIST_LOCK();
+
+  nsp = namespaceGetActive ();
+
+  nspT = namespaceResHDecode ( resH );
+
+  xassert ( nspT.nsp == nsp
+            && nspT.idx >= 0
+            && nspT.idx < resHList[nsp].size
+            && resHList[nsp].resources[nspT.idx].res.v.ops);
+
+  if (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
+    reshRemove_(nsp, nspT.idx);
+
+  LIST_UNLOCK();
+}
+
+void reshRemove ( cdiResH resH, const resOps * ops )
+{
+  int nsp;
+  namespaceTuple_t nspT;
 
   LIST_LOCK();
 
@@ -296,7 +342,7 @@ void reshRemove ( cdiResH resH, const resOps * ops )
   xassert ( nspT.nsp == nsp
             && nspT.idx >= 0
             && nspT.idx < resHList[nsp].size
-            && resHList[nsp].resources[nspT.idx].status != RESH_UNUSED
+            && (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
             && resHList[nsp].resources[nspT.idx].res.v.ops
             && resHList[nsp].resources[nspT.idx].res.v.ops == ops );
 
@@ -317,7 +363,7 @@ void reshReplace(cdiResH resH, void *p, const resOps *ops)
   while (resHList[nsp].size <= nspT.idx)
     listSizeExtend();
   listElem_t *q = resHList[nsp].resources + nspT.idx;
-  if (q->status != RESH_UNUSED)
+  if (q->status & RESH_IN_USE_BIT)
     {
       q->res.v.ops->valDestroy(q->res.v.val);
       reshRemove_(nsp, nspT.idx);
@@ -328,7 +374,7 @@ void reshReplace(cdiResH resH, void *p, const resOps *ops)
 
 
 static listElem_t *
-reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
+reshGetElem(const char *caller, const char* expressionString, cdiResH resH, const resOps *ops)
 {
   listElem_t *listElem;
   int nsp;
@@ -342,9 +388,9 @@ reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
   nsp = namespaceGetActive ();
 
   nspT = namespaceResHDecode ( resH );
+  assert(nspT.idx >= 0);
 
   if (nspT.nsp == nsp &&
-      nspT.idx >= 0 &&
       nspT.idx < resHList[nsp].size)
     {
       listElem = resHList[nsp].resources + nspT.idx;
@@ -353,20 +399,32 @@ reshGetElem(const char *caller, cdiResH resH, const resOps *ops)
   else
     {
       LIST_UNLOCK();
-      xabortC(caller, "Invalid namespace %d or index %d for resource handle %d when using namespace %d of size %d!",
-              nspT.nsp, nspT.idx, (int)resH, nsp, resHList[nsp].size);
+      show_stackframe();
+
+      if ( resH == CDI_UNDEFID )
+        {
+          xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is CDI_UNDEFID (= %d).\n\tThis is most likely the result of a failed earlier call. Please check the IDs returned by CDI.", expressionString, caller, resH);
+        }
+      else
+        {
+          xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is garbage (= %d, which resolves to namespace = %d, index = %d).\n\tThis is either the result of using an uninitialized variable,\n\tof using a value as an ID that is not an ID,\n\tor of using an ID after it has been invalidated.", expressionString, caller, resH, nspT.nsp, nspT.idx);
+        }
     }
 
   if ( !(listElem && listElem->res.v.ops == ops) )
-    xabortC(caller, "Invalid resource handle %d, list element not found!",
-            (int)resH);
+    {
+      show_stackframe();
+
+      xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: list element not found. The failed ID is %d", expressionString, caller, (int)resH);
+    }
+
   return listElem;
 }
 
 
-void *reshGetValue(const char * caller, cdiResH resH, const resOps * ops)
+void *reshGetValue(const char * caller, const char* expressionString, cdiResH resH, const resOps * ops)
 {
-  return reshGetElem(caller, resH, ops)->res.v.val;
+  return reshGetElem(caller, expressionString, resH, ops)->res.v.val;
 }
 
 /**************************************************************/
@@ -384,7 +442,7 @@ void reshGetResHListOfType ( int c, int * resHs, const resOps * ops )
   nsp = namespaceGetActive ();
 
   for ( i = 0; i < resHList[nsp].size && j < c; i++ )
-    if (resHList[nsp].resources[i].status != RESH_UNUSED
+    if ((resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
         && resHList[nsp].resources[i].res.v.ops == ops)
       resHs[j++] = namespaceIdxEncode2(nsp, i);
 
@@ -404,7 +462,7 @@ cdiResHApply(enum cdiApplyRet (*func)(int id, void *res, const resOps *p,
   int nsp = namespaceGetActive ();
   enum cdiApplyRet ret = CDI_APPLY_GO_ON;
   for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
-    if (resHList[nsp].resources[i].status != RESH_UNUSED)
+    if (resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
       ret = func(namespaceIdxEncode2(nsp, i),
                  resHList[nsp].resources[i].res.v.val,
                  resHList[nsp].resources[i].res.v.ops, data);
@@ -428,7 +486,7 @@ cdiResHFilterApply(const resOps *p,
   enum cdiApplyRet ret = CDI_APPLY_GO_ON;
   listElem_t *r = resHList[nsp].resources;
   for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
-    if (r[i].status != RESH_UNUSED && r[i].res.v.ops == p)
+    if ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == p)
       ret = func(namespaceIdxEncode2(nsp, i), r[i].res.v.val,
                  data);
   LIST_UNLOCK();
@@ -454,7 +512,7 @@ int reshCountType ( const resOps * ops )
 
   listElem_t *r = resHList[nsp].resources;
   for ( i = 0; i < resHList[nsp].size; i++ )
-    countType += (r[i].status != RESH_UNUSED && r[i].res.v.ops == ops);
+    countType += ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == ops);
 
   LIST_UNLOCK();
 
@@ -464,42 +522,47 @@ int reshCountType ( const resOps * ops )
 /**************************************************************/
 
 int
-reshResourceGetPackSize(int resH, const resOps *ops, void *context)
+reshResourceGetPackSize_intern(int resH, const resOps *ops, void *context, const char* caller, const char* expressionString)
 {
-  listElem_t *curr = reshGetElem(__func__, resH, ops);
+  listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
   return curr->res.v.ops->valGetPackSize(curr->res.v.val, context);
 }
 
 void
-reshPackResource(int resH, const resOps *ops,
-                 void *buf, int buf_size, int *position, void *context)
+reshPackResource_intern(int resH, const resOps *ops, void *buf, int buf_size, int *position, void *context,
+                        const char* caller, const char* expressionString)
 {
-  listElem_t *curr = reshGetElem(__func__, resH, ops);
+  listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
   curr->res.v.ops->valPack(curr->res.v.val, buf, buf_size, position, context);
 }
 
 
 static int getPackBufferSize(void *context)
 {
-  int nsp, i;
   int intpacksize, packBufferSize = 0;
 
-  nsp = namespaceGetActive ();
+  int nsp = namespaceGetActive ();
 
   /* pack start marker, namespace and sererator marker */
   packBufferSize += 3 * (intpacksize = serializeGetSize(1, DATATYPE_INT, context));
 
   /* pack resources, type marker and seperator marker */
   listElem_t *r = resHList[nsp].resources;
-  for ( i = 0; i < resHList[nsp].size; i++)
-    if (r[i].status == RESH_ASSIGNED)
+  for ( int i = 0; i < resHList[nsp].size; i++)
+    if (r[i].status & RESH_SYNC_BIT)
       {
-        xassert ( r[i].res.v.ops );
-
-        /* message plus frame of 2 ints */
-        packBufferSize +=
-          r[i].res.v.ops->valGetPackSize(r[i].res.v.val, context)
-          + 2 * intpacksize;
+        if (r[i].status == RESH_DESYNC_DELETED)
+          {
+            packBufferSize += 3 * intpacksize;
+          }
+        else if (r[i].status == RESH_DESYNC_IN_USE)
+          {
+            xassert ( r[i].res.v.ops );
+            /* message plus frame of 2 ints */
+            packBufferSize +=
+              r[i].res.v.ops->valGetPackSize(r[i].res.v.val, context)
+              + 2 * intpacksize;
+          }
       }
   /* end marker */
   packBufferSize += intpacksize;
@@ -528,7 +591,7 @@ void reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
   int nsp = namespaceGetActive ();
 
   int pBSize = *packBufferSize = getPackBufferSize(context);
-  char *pB = *packBuffer = (char*) xcalloc(1, *packBufferSize);
+  char *pB = *packBuffer = (char *)xcalloc(1, (size_t)pBSize);
 
   {
     int header[3] = { start, nsp, sep };
@@ -537,24 +600,29 @@ void reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
 
   listElem_t *r = resHList[nsp].resources;
   for ( i = 0; i < resHList[nsp].size; i++ )
-    if ( r[i].status == RESH_ASSIGNED)
+    if (r[i].status & RESH_SYNC_BIT)
       {
-        listElem_t * curr = r + i;
-        xassert ( curr->res.v.ops );
-
-        type = curr->res.v.ops->valTxCode ();
-
-        if ( ! type ) continue;
-
-        serializePack( &type, 1, DATATYPE_INT, * packBuffer,
-                       * packBufferSize, &packBufferPos, context);
-
-        curr->res.v.ops->valPack(curr->res.v.val,
-                                 pB, pBSize, &packBufferPos, context);
-
-        serializePack(&sep, 1, DATATYPE_INT, pB, pBSize, &packBufferPos, context);
-
-        curr->status = RESH_CLOSED;
+        if (r[i].status == RESH_DESYNC_DELETED)
+          {
+            enum { del_ints = 3 };
+            int temp[del_ints] = { RESH_DELETE, namespaceIdxEncode2(nsp, i), SEPARATOR };
+            serializePack(temp, del_ints, DATATYPE_INT,
+                          pB, pBSize, &packBufferPos, context);
+          }
+        else
+          {
+            listElem_t * curr = r + i;
+            xassert ( curr->res.v.ops );
+            type = curr->res.v.ops->valTxCode ();
+            if ( ! type ) continue;
+            serializePack(&type, 1, DATATYPE_INT, pB,
+                          pBSize, &packBufferPos, context);
+            curr->res.v.ops->valPack(curr->res.v.val,
+                                     pB, pBSize, &packBufferPos, context);
+            serializePack(&sep, 1, DATATYPE_INT,
+                          pB, pBSize, &packBufferPos, context);
+          }
+        r[i].status &= ~RESH_SYNC_BIT;
       }
 
   LIST_UNLOCK();
@@ -572,7 +640,7 @@ void reshSetStatus ( cdiResH resH, const resOps * ops, int status )
   namespaceTuple_t nspT;
   listElem_t * listElem;
 
-  xassert(ops && status != RESH_UNUSED);
+  xassert(ops && (status & RESH_IN_USE_BIT));
 
   LIST_INIT(1);
 
@@ -659,8 +727,8 @@ int reshListCompare ( int nsp0, int nsp1 )
     *resources1 = resHList[nsp1].resources;
   for (i = 0; i < listSizeMin; i++)
     {
-      int occupied0 = resources0[i].status != RESH_UNUSED,
-        occupied1 = resources1[i].status != RESH_UNUSED;
+      int occupied0 = (resources0[i].status & RESH_IN_USE_BIT) != 0,
+        occupied1 = (resources1[i].status & RESH_IN_USE_BIT) != 0;
       /* occupation mismatch ? */
       int diff = occupied0 ^ occupied1;
       valCompare |= (diff << cdiResHListOccupationMismatch);
@@ -682,11 +750,11 @@ int reshListCompare ( int nsp0, int nsp1 )
     }
   /* find resources in nsp 0 beyond end of nsp 1 */
   for (int j = listSizeMin; j < resHList[nsp0].size; ++j)
-    valCompare |= ((resources0[j].status != RESH_UNUSED)
+    valCompare |= (((resources0[j].status & RESH_IN_USE_BIT) != 0)
                    << cdiResHListOccupationMismatch);
   /* find resources in nsp 1 beyond end of nsp 0 */
   for (; i < resHList[nsp1].size; ++i)
-    valCompare |= ((resources1[i].status != RESH_UNUSED)
+    valCompare |= (((resources1[i].status & RESH_IN_USE_BIT) != 0)
                    << cdiResHListOccupationMismatch);
 
   LIST_UNLOCK();
@@ -725,7 +793,7 @@ void reshListPrint(FILE *fp)
       for ( j = 0; j < resHList[i].size; j++ )
         {
           curr = resHList[i].resources + j;
-          if (curr->status != RESH_UNUSED)
+          if (!(curr->status & RESH_IN_USE_BIT))
             {
               curr->res.v.ops->valPrint(curr->res.v.val, fp);
               fprintf ( fp, "\n" );
diff --git a/libcdi/src/resource_handle.h b/libcdi/src/resource_handle.h
index 78846fb..aad9a0c 100644
--- a/libcdi/src/resource_handle.h
+++ b/libcdi/src/resource_handle.h
@@ -34,10 +34,19 @@ typedef struct {
 }resOps;
 
 enum {
-  RESH_UNUSED,             /* resource holds no value */
-  RESH_ASSIGNED,           /* resource is user-assigned */
-  RESH_PRE_ASSIGNED,       /* resource is pre-assigned by library */
-  RESH_CLOSED,             /* resource is marked immutable */
+  RESH_IN_USE_BIT = 1 << 0,
+  RESH_SYNC_BIT = 1 << 1,
+  /* resource holds no value */
+  RESH_UNUSED = 0,
+  /* resource was deleted and needs to be synced */
+  RESH_DESYNC_DELETED
+    = RESH_SYNC_BIT,
+  /* resource is synchronized */
+  RESH_IN_USE
+    = RESH_IN_USE_BIT,
+  /* resource is in use, desynchronized and needs to be synced */
+  RESH_DESYNC_IN_USE
+    = RESH_IN_USE_BIT | RESH_SYNC_BIT,
 };
 
 void   reshListCreate(int namespaceID);
@@ -45,11 +54,14 @@ void   reshListDestruct(int namespaceID);
 int    reshPut ( void *, const resOps * );
 void reshReplace(cdiResH resH, void *p, const resOps *ops);
 void   reshRemove ( cdiResH, const resOps * );
+/*> doesn't check resource type */
+void reshDestroy(cdiResH);
 
 int    reshCountType ( const resOps * );
 
-void * reshGetValue(const char *, cdiResH, const resOps * );
-#define reshGetVal(resH, ops)  reshGetValue(__func__, resH, ops)
+void * reshGetValue(const char* caller, const char* expressionString, cdiResH id, const resOps* ops);
+#define reshGetVal(resH, ops)  reshGetValue(__func__, #resH, resH, ops)
+
 
 void   reshGetResHListOfType ( int, int *, const resOps * );
 
@@ -69,9 +81,11 @@ cdiResHFilterApply(const resOps *p,
 
 void   reshPackBufferCreate ( char **, int *, void *context );
 void   reshPackBufferDestroy ( char ** );
-int    reshResourceGetPackSize(int resh, const resOps *ops, void *context);
-void   reshPackResource(int resh, const resOps *ops,
-                        void *buf, int buf_size, int *position, void *context);
+int    reshResourceGetPackSize_intern(int resh, const resOps *ops, void *context, const char* caller, const char* expressionString);
+#define reshResourceGetPackSize(resh, ops, context) reshResourceGetPackSize_intern(resh, ops, context, __func__, #resh)
+void   reshPackResource_intern(int resh, const resOps *ops, void *buf, int buf_size, int *position, void *context, const char* caller, const char* expressionString);
+#define reshPackResource(resh, ops, buf, buf_size, position, context) reshPackResource_intern(resh, ops, buf, buf_size, position, context, __func__, #resh)
+
 void   reshSetStatus ( cdiResH, const resOps *, int );
 int    reshGetStatus ( cdiResH, const resOps * );
 
diff --git a/libcdi/src/resource_unpack.c b/libcdi/src/resource_unpack.c
index 72210c1..a362a7b 100644
--- a/libcdi/src/resource_unpack.c
+++ b/libcdi/src/resource_unpack.c
@@ -11,6 +11,7 @@
 #include "vlist.h"
 #include "namespace.h"
 #include "serialize.h"
+#include "resource_handle.h"
 #include "resource_unpack.h"
 #include "taxis.h"
 #include "zaxis.h"
@@ -24,7 +25,8 @@ void reshUnpackResources(char * unpackBuffer, int unpackBufferSize,
   int unpackBufferPos = 0;
   int numAssociations = 0, sizeAssociations = 16;
   struct streamAssoc *associations
-    = xmalloc(sizeof (associations[0]) * sizeAssociations);
+    = (struct streamAssoc *)xmalloc(sizeof (associations[0])
+                                    * (size_t)sizeAssociations);
 
   while ( unpackBufferPos < unpackBufferSize )
     {
@@ -63,7 +65,7 @@ void reshUnpackResources(char * unpackBuffer, int unpackBufferSize,
           if (sizeAssociations == numAssociations)
             associations
               = xrealloc(associations,
-                         sizeof (associations[0]) * (sizeAssociations *= 2));
+                         sizeof (associations[0]) * (size_t)(sizeAssociations *= 2));
 	  associations[numAssociations]
             = streamUnpack(unpackBuffer, unpackBufferSize, &unpackBufferPos,
                            originNamespace, context);
@@ -73,6 +75,11 @@ void reshUnpackResources(char * unpackBuffer, int unpackBufferSize,
           vlistUnpack(unpackBuffer, unpackBufferSize, &unpackBufferPos,
                       originNamespace, context, 1);
 	  break;
+        case RESH_DELETE:
+          serializeUnpack(unpackBuffer, unpackBufferSize, &unpackBufferPos,
+                          &token2, 1, DATATYPE_INT, context);
+          reshDestroy(namespaceAdaptKey(token2, originNamespace));
+          break;
 	default:
 	  xabort ( "TOKEN MAPS NO VALID DATATYPE" );
 	}
diff --git a/libcdi/src/resource_unpack.h b/libcdi/src/resource_unpack.h
index 53e2c59..13c92b5 100644
--- a/libcdi/src/resource_unpack.h
+++ b/libcdi/src/resource_unpack.h
@@ -13,6 +13,7 @@ enum
   MODEL     = 5,
   STREAM    = 6,
   VLIST     = 7,
+  RESH_DELETE,
   START     = 55555555,
   SEPARATOR = 66666666,
   END       = 99999999
diff --git a/libcdi/src/service.h b/libcdi/src/service.h
index 8ef4f38..1fbe0f0 100644
--- a/libcdi/src/service.h
+++ b/libcdi/src/service.h
@@ -25,7 +25,7 @@ srvrec_t *srvNew(void);
 void srvDelete(srvrec_t *srvp);
 
 int  srvRead(int fileID, srvrec_t *srvp);
-int  srvWrite(int fileID, srvrec_t *srvp);
+void srvWrite(int fileID, srvrec_t *srvp);
 
 int  srvInqHeader(srvrec_t *srvp, int *header);
 int  srvInqDataSP(srvrec_t *srvp, float *data);
diff --git a/libcdi/src/servicelib.c b/libcdi/src/servicelib.c
index bcfcee1..56df92e 100644
--- a/libcdi/src/servicelib.c
+++ b/libcdi/src/servicelib.c
@@ -13,13 +13,13 @@
 #include "error.h"
 #include "file.h"
 #include "binary.h"
+#include "stream_fcommon.h"
 #include "swap.h"
 
 
-#define SINGLE_PRECISION  4
-#define DOUBLE_PRECISION  8
-
-#define SRV_HEADER_LEN    8
+enum {
+  SRV_HEADER_LEN = 8,
+};
 
 
 static int initSrvLib      = 0;
@@ -152,7 +152,8 @@ int srvCheckFiletype(int fileID, int *swap)
   size_t sblocklen = 0;
   size_t data = 0;
   size_t dimx = 0, dimy = 0;
-  int fact = 0, found = 0;
+  size_t fact = 0;
+  int found = 0;
   unsigned char buffer[72], *pbuf;
 
   if ( fileRead(fileID, buffer, 4) != 4 ) return (found);
@@ -235,8 +236,8 @@ int srvDefHeader(srvrec_t *srvp, const int *header)
 
   for ( i = 0; i < SRV_HEADER_LEN; i++ )
     srvp->header[i] = header[i];
-  
-  srvp->datasize = header[4]*header[5];
+
+  srvp->datasize = (size_t)(header[4] * header[5]);
 
   if ( SRV_Debug )
     Message("datasize = %lu", srvp->datasize);
@@ -345,8 +346,8 @@ int srvDefData(srvrec_t *srvp, int prec, const void *data)
 
   header = srvp->header;
 
-  datasize = header[4]*header[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)(header[4] * header[5]);
+  blocklen = datasize * (size_t)dprec;
 
   srvp->datasize = datasize;
 
@@ -414,9 +415,7 @@ int srvRead(int fileID, srvrec_t *srvp)
   size_t blocklen, blocklen2;
   size_t i;
   char tempheader[64];
-  int hprec, dprec;
   void *buffer;
-  int buffersize;
   int byteswap;
   int status;
 
@@ -437,9 +436,9 @@ int srvRead(int fileID, srvrec_t *srvp)
   if ( SRV_Debug )
     Message("blocklen = %lu", blocklen);
 
-  hprec = blocklen / SRV_HEADER_LEN;
+  size_t hprec = blocklen / SRV_HEADER_LEN;
 
-  srvp->hprec = hprec;
+  srvp->hprec = (int)hprec;
 
   switch ( hprec )
     {
@@ -476,16 +475,16 @@ int srvRead(int fileID, srvrec_t *srvp)
       if ( blocklen2 != 0 ) return (-1);
     }
 
-  srvp->datasize = srvp->header[4]*srvp->header[5];
+  srvp->datasize = (size_t)(srvp->header[4] * srvp->header[5]);
 
   if ( SRV_Debug )
     Message("datasize = %lu", srvp->datasize);
 
   blocklen = binReadF77Block(fileID, byteswap);
 
-  buffersize = srvp->buffersize;
+  size_t buffersize = srvp->buffersize;
 
-  if ( buffersize < (int) blocklen )
+  if ( buffersize < blocklen )
     {
       buffersize = blocklen;
       buffer = srvp->buffer;
@@ -498,9 +497,9 @@ int srvRead(int fileID, srvrec_t *srvp)
 
   datasize = srvp->datasize;
 
-  dprec = blocklen / datasize;
+  size_t dprec = blocklen / datasize;
 
-  srvp->dprec = dprec;
+  srvp->dprec = (int)dprec;
 
   if ( dprec != SINGLE_PRECISION && dprec != DOUBLE_PRECISION )
     {
@@ -522,7 +521,7 @@ int srvRead(int fileID, srvrec_t *srvp)
 }
 
 
-int srvWrite(int fileID, srvrec_t *srvp)
+void srvWrite(int fileID, srvrec_t *srvp)
 {
   size_t datasize;
   size_t blocklen;
@@ -538,7 +537,7 @@ int srvWrite(int fileID, srvrec_t *srvp)
   header = srvp->header;
 
   /* write header record */
-  blocklen = SRV_HEADER_LEN * hprec;
+  blocklen = SRV_HEADER_LEN * (size_t)hprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -571,8 +570,8 @@ int srvWrite(int fileID, srvrec_t *srvp)
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
-  datasize = header[4]*header[5];
-  blocklen = datasize * dprec;
+  datasize = (size_t)(header[4] * header[5]);
+  blocklen = datasize * (size_t)dprec;
 
   binWriteF77Block(fileID, byteswap, blocklen);
 
@@ -600,8 +599,6 @@ int srvWrite(int fileID, srvrec_t *srvp)
     }
 
   binWriteF77Block(fileID, byteswap, blocklen);
-
-  return (0);
 }
 /*
  * Local Variables:
diff --git a/libcdi/src/stream.c b/libcdi/src/stream.c
index 1631d96..7725713 100644
--- a/libcdi/src/stream.c
+++ b/libcdi/src/stream.c
@@ -12,6 +12,7 @@
 
 #include "cdi.h"
 #include "cdi_int.h"
+#include "cdi_cksum.h"
 #include "cdf.h"
 #include "dmemory.h"
 #include "error.h"
@@ -28,98 +29,32 @@
 #include "extra.h"
 #include "ieg.h"
 #include "vlist.h"
+#include "serialize.h"
 #include "resource_handle.h"
+#include "resource_unpack.h"
 
 #include "namespace.h"
 
 
-#define  MAX_FNAMES  3
+static stream_t *stream_new_entry(void);
+static void stream_delete_entry(stream_t *streamptr);
+static int streamCompareP(void * streamptr1, void * streamptr2);
+static void streamDestroyP(void * streamptr);
+static void streamPrintP(void * streamptr, FILE * fp);
+static int streamGetPackSize(void * streamptr, void *context);
+static void streamPack(void * streamptr, void * buff, int size, int * position, void *context);
+static int streamTxCode(void);
 
-static void
-cdiPrintDefaults(void)
-{
-  fprintf (stderr, "default instID     :  %d\n", cdiDefaultInstID);
-  fprintf (stderr, "default modelID    :  %d\n", cdiDefaultModelID);
-  fprintf (stderr, "default tableID    :  %d\n", cdiDefaultTableID);
-  fprintf (stderr, "default missval    :  %g\n", cdiDefaultMissval);
-}
-
-
-void cdiDebug(int level)
-{
-  if ( level == 1 || (level &  2) ) CDI_Debug = 1;
-
-  if ( CDI_Debug ) Message("debug level %d", level);
-
-  if ( level == 1 || (level &  4) ) memDebug(1);
-
-  if ( level == 1 || (level &  8) ) fileDebug(1);
-
-  if ( level == 1 || (level & 16) )
-    {
-#if  defined  (HAVE_LIBGRIB)
-      gribSetDebug(1);
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-      cdfDebug(1);
-#endif
-#if  defined  (HAVE_LIBSERVICE)
-      srvDebug(1);
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-      extDebug(1);
-#endif
-#if  defined  (HAVE_LIBIEG)
-      iegDebug(1);
-#endif
-    }
-
-  if ( CDI_Debug )
-    {
-      cdiPrintDefaults();
-      cdiPrintDatatypes();
-    }
-}
+const resOps streamOps = {
+  streamCompareP,
+  streamDestroyP,
+  streamPrintP,
+  streamGetPackSize,
+  streamPack,
+  streamTxCode
+};
 
 
-int cdiHaveFiletype(int filetype)
-{
-  int status = 0;
-
-  switch (filetype)
-    {
-#if  defined  (HAVE_LIBSERVICE)
-    case FILETYPE_SRV:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-    case FILETYPE_EXT:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBIEG)
-    case FILETYPE_IEG:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBGRIB)
-#if  defined  (HAVE_LIBGRIB_API) || defined  (HAVE_LIBCGRIBEX)
-    case FILETYPE_GRB:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_LIBGRIB_API)
-    case FILETYPE_GRB2: { status = 1; break; }
-#endif
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-    case FILETYPE_NC:   { status = 1; break; }
-#if  defined  (HAVE_NETCDF2)
-    case FILETYPE_NC2:  { status = 1; break; }
-#endif
-#if  defined  (HAVE_NETCDF4)
-    case FILETYPE_NC4:  { status = 1; break; }
-    case FILETYPE_NC4C: { status = 1; break; }
-#endif
-#endif
-    default: { status = 0; break; }
-    }
-
-  return (status);
-}
 
 
 #undef  IsBigendian
@@ -146,18 +81,16 @@ int getByteorder(int byteswap)
   return (byteorder);
 }
 
-
 static
 int getFiletype(const char *filename, int *byteorder)
 {
   int filetype = CDI_EUFTYPE;
-  int fileID;
   int swap = 0;
   int version;
   long recpos;
   char buffer[8];
 
-  fileID = fileOpen(filename, "r");
+  int fileID = fileOpen(filename, "r");
 
   if ( fileID == CDI_UNDEFID )
     {
@@ -242,139 +175,6 @@ int getFiletype(const char *filename, int *byteorder)
   return (filetype);
 }
 
-
-int _readline_(FILE *fp, char *line, int len)
-{
-  int ichar, ipos = 0;
-
-  while ( (ichar = fgetc(fp)) != EOF )
-    {
-      if ( ichar == '\n' ) break;
-      line[ipos++] = ichar;
-      if ( ipos >= len )
-        {
-          fprintf(stderr, "readline Warning: end of line not found (maxlen = %d)!\n", len);
-          break;
-        }
-    }
-  line[ipos] = 0;
-
-  if ( feof(fp) && ipos == 0 ) return (0);
-
-  return (1);
-}
-
-#define  MAX_LINE  4096
-
-int get_fnames(const char *argument, char *fnames[], int max_fnames)
-{
-  int num_fnames = 0;
-  int len;
-  int nfiles = 0;
-  int i, j;
-  const char *pch;
-  char line[MAX_LINE];
-
-  len = (int) strlen(argument);
-  for ( i = 0; i < len; ++i )
-    if ( argument[i] == ':' ) break;
-
-  if ( i < len )
-    {
-      pch = &argument[i+1];
-      len -= (i+1);
-      if ( len && ( memcmp(argument, "filelist:", i) == 0 ||
-		    memcmp(argument, "flist:", i) == 0 ) )
-	{
-	  for ( i = 0; i < len; ++i ) if ( pch[i] == ',' ) nfiles++;
-
-	  if ( nfiles == 0 )
-	    {
-	      FILE *fp;
-	      fp = fopen(pch, "r");
-	      if ( fp == NULL ) Error("Open failed on %s", pch);
-
-	      if ( CDI_Debug )
-		Message("Reading file names from %s", pch);
-
-	      rewind(fp);
-
-	      nfiles = 0;
-	      while ( _readline_(fp, line, MAX_LINE) )
-		{
-		  if ( line[0] == '#' || line[0] == '\0' ||
-		       line[0] == ' ' ) continue;
-
-		  if ( nfiles >= max_fnames )
-		    {
-		      Warning("Too many input files (limit: %d)", max_fnames);
-		      break;
-		    }
-		  fnames[nfiles] = strdupx(line);
-		  nfiles++;
-		}
-
-	      fclose(fp);
-
-	      if ( nfiles == 0 ) Error("No input file found in %s", pch);
-	    }
-	  else
-	    {
-	      char xline[65536];
-
-	      strcpy(xline, pch);
-	      for ( i = 0; i < len; i++ ) if ( xline[i] == ',' ) xline[i] = 0;
-
-	      nfiles++;
-	      if ( nfiles >= max_fnames )
-		{
-		  Warning("Too many input files (limit: %d)", max_fnames);
-		  nfiles = max_fnames;
-		}
-
-	      i = 0;
-	      for ( j = 0; j < nfiles; j++ )
-		{
-		  fnames[j] = strdupx(&xline[i]);
-		  i += strlen(&xline[i]) + 1;
-		}
-	    }
-	}
-      else if ( len && memcmp(argument, "ls:", i) == 0 )
-	{
-	  char command[4096];
-	  FILE *pfp;
-
-	  strcpy(command, "ls ");
-	  strcat(command, pch);
-
-	  pfp = popen(command, "r");
-	  if ( pfp == NULL ) SysError("popen %s failed", command);
-
-	  nfiles = 0;
-	  while ( _readline_(pfp, line, MAX_LINE) )
-	    {
-	      if ( nfiles >= max_fnames )
-		{
-		  Warning("Too many input files (limit: %d)", max_fnames);
-		  break;
-		}
-	      fnames[nfiles++] = strdupx(line);
-	    }
-
-	  pclose(pfp);
-	  /*
-	  for ( j = 0; j < nfiles; j++ )
-	    fnames[j] = fnames[j];
-	  */
-	}
-    }
-
-  num_fnames = nfiles;
-
-  return (num_fnames);
-}
-
 /*
 @Function  streamInqFiletype
 @Title     Get the filetype
@@ -444,12 +244,6 @@ void streamDefByteorder(int streamID, int byteorder)
 
   stream_check_ptr(__func__, streamptr);
 
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   streamptr->byteorder = byteorder;
   filetype = streamptr->filetype;
 
@@ -483,6 +277,7 @@ void streamDefByteorder(int streamID, int byteorder)
       }
 #endif
     }
+  reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -536,20 +331,18 @@ char *streamFilename(int streamID)
 }
 
 static
-int cdiInqTimeSize(int streamID)
+long cdiInqTimeSize(int streamID)
 {
-  int ntsteps;
   int tsID = 0, nrecs;
   stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  ntsteps = streamptr->ntsteps;
+  long ntsteps = streamptr->ntsteps;
 
-  if ( ntsteps == CDI_UNDEFID )
+  if ( ntsteps == (long)CDI_UNDEFID )
     while ( (nrecs = streamInqTimestep(streamID, tsID++)) )
-
-  ntsteps = streamptr->ntsteps;
+      ntsteps = streamptr->ntsteps;
 
   return (ntsteps);
 }
@@ -557,12 +350,9 @@ int cdiInqTimeSize(int streamID)
 static
 int cdiInqContents(stream_t * streamptr)
 {
-  int filetype;
-  int vlistID;
-  int taxisID;
   int status = 0;
 
-  filetype = streamptr->filetype;
+  int filetype = streamptr->filetype;
 
   switch (filetype)
     {
@@ -617,15 +407,13 @@ int cdiInqContents(stream_t * streamptr)
 
   if ( status == 0 )
     {
-      vlistID = streamptr->vlistID;
-      taxisID = vlistInqTaxis(vlistID);
-      if ( taxisID != -1 )
+      int vlistID = streamptr->vlistID;
+      int taxisID = vlistInqTaxis(vlistID);
+      if ( taxisID != CDI_UNDEFID )
         {
           taxis_t *taxisptr1 = &streamptr->tsteps[0].taxis;
           taxis_t *taxisptr2 = taxisPtr(taxisID);
           ptaxisCopy(taxisptr2, taxisptr1);
-          if ( taxisptr1->name     ) taxisptr2->name = taxisptr1->name;
-          if ( taxisptr1->longname ) taxisptr2->longname = taxisptr1->longname;
         }
     }
 
@@ -765,16 +553,14 @@ int streamOpen(const char *filename, const char *filemode, int filetype)
 
       if ( streamptr->filemode == 'r' )
 	{
-	  vlist_t *vlistptr;
-	  int vlistID;
-	  vlistID = vlistCreate();
+	  int vlistID = vlistCreate();
 	  if ( vlistID < 0 ) return(CDI_ELIMIT);
 
 	  streamptr->vlistID = vlistID;
 	  /* cdiReadByteorder(streamID); */
 	  status = cdiInqContents(streamptr);
 	  if ( status < 0 ) return (status);
-	  vlistptr = vlist_to_pointer(streamptr->vlistID);
+	  vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
 	  vlistptr->ntsteps = streamNtsteps(streamID);
 	}
     }
@@ -819,7 +605,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
   status = cdiInqContents(streamptr);
   if ( status < 0 ) return (status);
   vlistptr = vlist_to_pointer(streamptr->vlistID);
-  vlistptr->ntsteps = cdiInqTimeSize(streamID);
+  vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
 
   {
     void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
@@ -934,46 +720,21 @@ if ( streamID < 0 ) handle_error(streamID);
 @EndSource
 @EndFunction
 */
-int streamOpenRead(const char *filenames)
+int streamOpenRead(const char *filename)
 {
-  int filetype, byteorder;
-  int streamID;
-  int num_fnames = 0;
-  char *fnames[MAX_FNAMES];
-  const char *filename;
-
   cdiInitialize();
 
-  //num_fnames = get_fnames(filenames, fnames, MAX_FNAMES);
-
-  if ( num_fnames == 0 )
-    filename = filenames;
-  else
-    {
-      int i;
-      for ( i = 0; i < num_fnames; ++i ) printf("fnames: %d %s\n", i, fnames[i]);
-      filename = fnames[0];
-    }
-
-  filetype = getFiletype(filename, &byteorder);
+  int byteorder = 0;
+  int filetype = getFiletype(filename, &byteorder);
 
   if ( filetype < 0 ) return (filetype);
 
-  streamID = streamOpen(filename, "r", filetype);
+  int streamID = streamOpen(filename, "r", filetype);
 
   if ( streamID >= 0 )
     {
       stream_t *streamptr = stream_to_pointer(streamID);
       streamptr->byteorder = byteorder;
-
-      if ( num_fnames > 0 )
-	{
-	  int i;
-	  streamptr->nfiles = num_fnames;
-	  streamptr->fnames = (char **) malloc(num_fnames*sizeof(char *));
-	  for ( i = 0; i < num_fnames; ++i )
-	    streamptr->fnames[i] = fnames[i];
-	}
     }
 
   return (streamID);
@@ -982,10 +743,9 @@ int streamOpenRead(const char *filenames)
 
 int streamOpenAppend(const char *filename)
 {
-  int byteorder;
-
   cdiInitialize();
 
+  int byteorder = 0;
   int filetype = getFiletype(filename, &byteorder);
 
   if ( filetype < 0 ) return (filetype);
@@ -1049,6 +809,81 @@ int streamOpenWrite(const char *filename, int filetype)
   return (streamOpen(filename, "w", filetype));
 }
 
+static
+void streamDefaultValue ( stream_t * streamptr )
+{
+  int i;
+
+  streamptr->self              = CDI_UNDEFID;
+  streamptr->accesstype        = CDI_UNDEFID;
+  streamptr->accessmode        = 0;
+  streamptr->filetype          = FILETYPE_UNDEF;
+  streamptr->byteorder         = CDI_UNDEFID;
+  streamptr->fileID            = 0;
+  streamptr->dimgroupID        = CDI_UNDEFID;
+  streamptr->filemode          = 0;
+  streamptr->numvals           = 0;
+  streamptr->filename          = NULL;
+  streamptr->record            = NULL;
+  streamptr->varsAllocated     = 0;
+  streamptr->nrecs             = 0;
+  streamptr->nvars             = 0;
+  streamptr->vars              = NULL;
+  streamptr->varinit           = 0;
+  streamptr->ncmode            = 0;
+  streamptr->curTsID           = CDI_UNDEFID;
+  streamptr->rtsteps           = 0;
+  streamptr->ntsteps           = CDI_UNDEFID;
+  streamptr->numTimestep       = 0;
+  streamptr->tsteps            = NULL;
+  streamptr->tstepsTableSize   = 0;
+  streamptr->tstepsNextID      = 0;
+  streamptr->historyID         = CDI_UNDEFID;
+  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->complevel         = 0;
+
+  basetimeInit(&streamptr->basetime);
+
+  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_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->curfile           = 0;
+  streamptr->nfiles            = 0;
+  streamptr->fnames            = NULL;
+
+  streamptr->gribContainers    = NULL;
+  streamptr->vlistIDorig       = CDI_UNDEFID;
+}
+
+
+static stream_t *stream_new_entry(void)
+{
+  stream_t *streamptr;
+
+  cdiInitialize(); /* ***************** make MT version !!! */
+
+  streamptr = (stream_t *) xmalloc(sizeof(stream_t));
+  streamDefaultValue ( streamptr );
+  streamptr->self = reshPut (( void * ) streamptr, &streamOps );
+
+  return streamptr;
+}
+
+
 void
 cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
 {
@@ -1173,10 +1008,13 @@ void streamClose(int streamID)
 	free(streamptr->tsteps[index].records);
       if ( streamptr->tsteps[index].recIDs )
 	free(streamptr->tsteps[index].recIDs);
+      taxisDestroyKernel(&streamptr->tsteps[index].taxis);
     }
 
   if ( streamptr->tsteps ) free(streamptr->tsteps);
 
+  if ( streamptr->basetime.timevar_cache ) free(streamptr->basetime.timevar_cache);
+
   if ( streamptr->nfiles > 0 )
     {
       for ( index = 0; index < streamptr->nfiles; ++index )
@@ -1193,12 +1031,28 @@ void streamClose(int streamID)
 	    taxisDestroy(vlistInqTaxis(vlistID));
 	  }
 
+      vlist_unlock(vlistID);
       vlistDestroy(vlistID);
     }
 
   stream_delete_entry(streamptr);
 }
 
+static void stream_delete_entry(stream_t *streamptr)
+{
+  int idx;
+
+  xassert ( streamptr );
+
+  idx = streamptr->self;
+  free ( streamptr );
+  reshRemove ( idx, &streamOps );
+
+  if ( CDI_Debug )
+    Message("Removed idx %d from stream list", idx);
+}
+
+
 void cdiStreamSync_(stream_t *streamptr)
 {
   int fileID   = streamptr->fileID;
@@ -1300,11 +1154,6 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
       taxis_t *taxisptr1 = taxisPtr(taxisID);
       taxis_t *taxisptr2 = &streamptr->tsteps[tsID].taxis;
       ptaxisCopy(taxisptr2, taxisptr1);
-      if ( tsID == 0 )
-        {
-          if ( taxisptr1->name     ) taxisptr2->name = taxisptr1->name;
-          if ( taxisptr1->longname ) taxisptr2->longname = taxisptr1->longname;
-        }
     }
 
   streamptr->ntsteps = tsID + 1;
@@ -1325,7 +1174,7 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
 
   cdi_create_records(streamptr, tsID);
 
-  return (streamptr->ntsteps);
+  return (int)streamptr->ntsteps;
 }
 
 /*
@@ -1468,24 +1317,9 @@ int streamInqTimestep(int streamID, int tsID)
   return (nrecs);
 }
 
-/*
- at Function  streamReadVar
- at Title     Read a variable
-
- at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
- at Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
-    @Item  varID     Variable identifier.
-    @Item  data      Pointer to the location into which the data values are read.
-                     The caller must allocate space for the returned values.
-    @Item  nmiss     Number of missing values.
-
- at Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+/* the single image implementation */
+static
+void cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamID, varID);
 
@@ -1506,6 +1340,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("grbReadVar not implemented for memtype float!");
         grbReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -1513,6 +1348,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("srvReadVar not implemented for memtype float!");
         srvReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -1520,6 +1356,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("extReadVar not implemented for memtype float!");
         extReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -1527,6 +1364,7 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
       {
+        if ( memtype == MEMTYPE_FLOAT ) Error("iegReadVar not implemented for memtype float!");
         iegReadVarDP(streamptr, varID, data, nmiss);
 	break;
       }
@@ -1537,7 +1375,11 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
       {
-        cdfReadVarDP(streamptr, varID, data, nmiss);
+        if ( memtype == MEMTYPE_FLOAT )
+          cdfReadVarSP(streamptr, varID, data, nmiss);
+        else
+          cdfReadVarDP(streamptr, varID, data, nmiss);
+
 	break;
       }
 #endif
@@ -1549,36 +1391,52 @@ void streamReadVar(int streamID, int varID, double *data, int *nmiss)
     }
 }
 
+/*
+ at Function  streamReadVar
+ at Title     Read a variable
+
+ at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+{
+  cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+}
 
 /*
- at Function  streamWriteVar
- at Title     Write a variable
+ at Function  streamReadVarF
+ at Title     Read a variable
 
- at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+ at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
 @Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
     @Item  varID     Variable identifier.
-    @Item  data      Pointer to a block of double precision floating point data values to be written.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamWriteVar writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
 @EndFunction
 */
-void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
 {
-  void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
-                               const void *data, int nmiss)
-    = (void (*)(int, int, int, const void *, int))
-    namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
-  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+  cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
 }
 
 /* the single image implementation */
-void
-cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
-                   int nmiss)
+void cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
 
@@ -1647,51 +1505,63 @@ cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
 }
 
 /*
- at Function  streamWriteVarF
+ at Function  streamWriteVar
 @Title     Write a variable
 
- at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+ at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
 @Parameter
     @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
     @Item  varID     Variable identifier.
-    @Item  data      Pointer to a block of single precision floating point data values to be written.
+    @Item  data      Pointer to a block of double precision floating point data values to be written.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The function streamWriteVar writes the values of one time step of a variable to an open dataset.
 The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
 @EndFunction
 */
-void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
 {
   void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
                                const void *data, int nmiss)
     = (void (*)(int, int, int, const void *, int))
     namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
-  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
 }
 
 /*
- at Function  streamReadVarSlice
- at Title     Read a horizontal slice of a variable
+ at Function  streamWriteVarF
+ at Title     Write a variable
 
- at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
 @Parameter
-    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
     @Item  varID     Variable identifier.
-    @Item  levelID   Level identifier.
-    @Item  data      Pointer to the location into which the data values are read.
-                     The caller must allocate space for the returned values.
+    @Item  data      Pointer to a block of single precision floating point data values to be written.
     @Item  nmiss     Number of missing values.
 
 @Description
-The function streamReadVar reads all the values of a horizontal slice of a variable
-from an open dataset.
+The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+Only support for netCDF was implemented in this function.
 @EndFunction
 */
-void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
 {
+  void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+                               const void *data, int nmiss)
+    = (void (*)(int, int, int, const void *, int))
+    namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+  myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+}
+
+static
+int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
+{
+  // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+  // A value > 0 is returned in this case, otherwise it returns zero.
+  int status = 0;
+
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamID, varID);
 
   check_parg(data);
@@ -1711,6 +1581,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         grbReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -1718,6 +1589,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         srvReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -1725,6 +1597,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         extReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -1732,6 +1605,7 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
       {
+        if ( memtype == MEMTYPE_FLOAT ) return 1;
         iegReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
 	break;
       }
@@ -1742,21 +1616,86 @@ void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
       {
-        /* FIXME: status value ignored */
-        int ierr = cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
-	break;
+        if ( memtype == MEMTYPE_FLOAT )
+          cdfReadVarSliceSP(streamptr, varID, levelID, data, nmiss);
+        else
+          cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
+        break;
       }
 #endif
     default:
       {
 	Error("%s support not compiled in!", strfiletype(filetype));
+        status = 2;
 	break;
       }
     }
+
+  return status;
+}
+
+/*
+ at Function  streamReadVarSlice
+ at Title     Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  levelID   Level identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVarSlice reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+{
+  if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
+    {
+      Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
+      size_t elementCount = gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+      memset(data, 0, elementCount * sizeof(*data));
+    }
+}
+
+/*
+ at Function  streamReadVarSliceF
+ at Title     Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+ at Parameter
+    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead}.
+    @Item  varID     Variable identifier.
+    @Item  levelID   Level identifier.
+    @Item  data      Pointer to the location into which the data values are read.
+                     The caller must allocate space for the returned values.
+    @Item  nmiss     Number of missing values.
+
+ at Description
+The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+{
+  if ( cdiStreamReadVarSlice(streamID, varID,levelID, MEMTYPE_FLOAT, data, nmiss) )
+    {
+      // In case the file format does not support single precision reading,
+      // we fall back to double precision reading, converting the data on the fly.
+      size_t elementCount = gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+      double* conversionBuffer = malloc(elementCount * sizeof(*conversionBuffer));
+      streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+      for (size_t i = elementCount; i--; ) data[i] = conversionBuffer[i];
+      free(conversionBuffer);
+    }
 }
 
 static
-void stream_write_var_slice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
+void cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
   if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
 
@@ -1810,12 +1749,9 @@ void stream_write_var_slice(int streamID, int varID, int levelID, int memtype, c
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        int ierr = 0;
-	if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
-        ierr = cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-	break;
-      }
+      if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+      cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+      break;
 #endif
     default:
       {
@@ -1844,7 +1780,7 @@ The values are converted to the external data type of the variable, if necessary
 */
 void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
 {
-  stream_write_var_slice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
+  cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
 }
 
 /*
@@ -1867,7 +1803,7 @@ Only support for netCDF was implemented in this function.
 */
 void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
 {
-  stream_write_var_slice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
+  cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
 }
 
 
@@ -2031,53 +1967,17 @@ void streamWriteContents(int streamID, char *cname)
 }
 
 
-void cdiDefTableID(int tableID)
-{
-  cdiDefaultTableID = tableID;
-  int modelID = cdiDefaultModelID = tableInqModel(tableID);
-  cdiDefaultInstID = modelInqInstitut(modelID);
-}
-
-
-void cdiPrintVersion(void)
-{
-  fprintf(stderr, "     CDI library version : %s\n", cdiLibraryVersion());
-#if  defined  (HAVE_LIBCGRIBEX)
-  fprintf(stderr, " CGRIBEX library version : %s\n", cgribexLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBGRIB_API)
-  fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBNETCDF)
-  fprintf(stderr, "  netCDF library version : %s\n", cdfLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBHDF5)
-  fprintf(stderr, "    HDF5 library version : %s\n", hdfLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBSERVICE)
-  fprintf(stderr, " SERVICE library version : %s\n", srvLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBEXTRA)
-  fprintf(stderr, "   EXTRA library version : %s\n", extLibraryVersion());
-#endif
-#if  defined  (HAVE_LIBIEG)
-  fprintf(stderr, "     IEG library version : %s\n", iegLibraryVersion());
-#endif
-  fprintf(stderr, "    FILE library version : %s\n", fileLibraryVersion());
-}
-
-
 int streamNtsteps(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  return (streamptr->ntsteps);
+  return (int)streamptr->ntsteps;
 }
 
-
-off_t   streamNvals(int streamID)
+// This function is used in CDO!
+off_t streamNvals(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
@@ -2159,37 +2059,29 @@ int streamInqVlistIDorig(int streamID)
 
 void streamDefCompType(int streamID, int comptype)
 {
-  stream_t *streamptr;
-
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  streamptr->comptype = comptype;
+  if (streamptr->comptype != comptype)
+    {
+      streamptr->comptype = comptype;
+      reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void streamDefCompLevel(int streamID, int complevel)
 {
-  stream_t *streamptr;
-
-  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  streamptr->complevel = complevel;
+  if (streamptr->complevel != complevel)
+    {
+      streamptr->complevel = complevel;
+      reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -2211,6 +2103,309 @@ int streamInqCompLevel(int streamID)
 
   return (streamptr->complevel);
 }
+
+int streamInqFileID(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->fileID);
+}
+
+void streamDefDimgroupID(int streamID, int dimgroupID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  streamptr->dimgroupID = dimgroupID;
+}
+
+
+int streamInqDimgroupID(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->dimgroupID);
+}
+
+
+void cdiDefAccesstype(int streamID, int type)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  if ( streamptr->accesstype == CDI_UNDEFID )
+    {
+      streamptr->accesstype = type;
+    }
+  else
+    {
+      if ( streamptr->accesstype != type )
+	{
+	  if ( streamptr->accesstype == TYPE_REC )
+	    Error("Changing access type from REC to VAR not allowed!");
+	  else
+	    Error("Changing access type from VAR to REC not allowed!");
+	}
+    }
+}
+
+
+int cdiInqAccesstype(int streamID)
+{
+  stream_t *streamptr;
+
+  streamptr = ( stream_t *) reshGetVal ( streamID, &streamOps );
+
+  return (streamptr->accesstype);
+}
+
+static
+int streamTxCode(void)
+{
+  return STREAM;
+}
+
+
+void cdiStreamSetupVlist(stream_t *streamptr, int vlistID, int vlistIDorig)
+{
+  vlist_lock(vlistID);
+  int nvars = vlistNvars(vlistID);
+  streamptr->vlistID = vlistID;
+  streamptr->vlistIDorig = vlistIDorig;
+  for (int varID = 0; varID < nvars; varID++ )
+    {
+      int gridID  = vlistInqVarGrid(vlistID, varID);
+      int zaxisID = vlistInqVarZaxis(vlistID, varID);
+      stream_new_var(streamptr, gridID, zaxisID);
+      if ( streamptr->have_missval )
+        vlistDefVarMissval(vlistID, varID,
+                           vlistInqVarMissval(vlistID, varID));
+    }
+
+  if (streamptr->filemode == 'w' )
+    {
+      if ( streamptr->filetype == FILETYPE_NC  ||
+           streamptr->filetype == FILETYPE_NC2 ||
+           streamptr->filetype == FILETYPE_NC4 ||
+           streamptr->filetype == FILETYPE_NC4C )
+        {
+#ifdef HAVE_LIBNETCDF
+          void (*myCdfDefVars)(stream_t *streamptr)
+            = (void (*)(stream_t *))
+            namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
+          myCdfDefVars(streamptr);
+#endif
+        }
+      else if ( streamptr->filetype == FILETYPE_GRB  ||
+                streamptr->filetype == FILETYPE_GRB2 )
+        {
+          gribContainersNew(streamptr);
+        }
+    }
+}
+
+
+void streamGetIndexList ( int nstreams, int * streamIndexList )
+{
+  reshGetResHListOfType ( nstreams, streamIndexList, &streamOps );
+}
+
+int streamInqNvars ( int streamID )
+{
+  stream_t * streamptr;
+  streamptr = ( stream_t * ) reshGetVal ( streamID, &streamOps );
+  return ( streamptr->nvars );
+}
+
+
+static int streamCompareP(void * streamptr1, void * streamptr2)
+{
+  stream_t * s1 = ( stream_t * ) streamptr1;
+  stream_t * s2 = ( stream_t * ) streamptr2;
+  enum {
+    differ = -1,
+    equal  = 0,
+  };
+
+  xassert ( s1 );
+  xassert ( s2 );
+
+  if ( s1->filetype  != s2->filetype  ) return differ;
+  if (  namespaceAdaptKey2 ( s1->vlistIDorig ) !=
+	namespaceAdaptKey2 ( s2->vlistIDorig )) return differ;
+  if ( s1->byteorder != s2->byteorder ) return differ;
+  if ( s1->comptype  != s2->comptype  ) return differ;
+  if ( s1->complevel != s2->complevel ) return differ;
+
+  if ( s1->filename )
+    {
+      if (strcmp(s1->filename, s2->filename))
+	return differ;
+    }
+  else if ( s2->filename )
+    return differ;
+
+  return equal;
+}
+
+
+void streamDestroyP ( void * streamptr )
+{
+  stream_t * sp = ( stream_t * ) streamptr;
+
+  xassert ( sp );
+
+  int id = sp->self;
+  streamClose ( id );
+}
+
+
+void streamPrintP   ( void * streamptr, FILE * fp )
+{
+  stream_t * sp = ( stream_t * ) streamptr;
+
+  if ( !sp ) return;
+
+  fprintf ( fp, "#\n");
+  fprintf ( fp, "# streamID %d\n", sp->self);
+  fprintf ( fp, "#\n");
+  fprintf ( fp, "self          = %d\n", sp->self );
+  fprintf ( fp, "accesstype    = %d\n", sp->accesstype );
+  fprintf ( fp, "accessmode    = %d\n", sp->accessmode );
+  fprintf ( fp, "filetype      = %d\n", sp->filetype );
+  fprintf ( fp, "byteorder     = %d\n", sp->byteorder );
+  fprintf ( fp, "fileID        = %d\n", sp->fileID );
+  fprintf ( fp, "dimgroupID    = %d\n", sp->dimgroupID );
+  fprintf ( fp, "filemode      = %d\n", sp->filemode );
+  fprintf ( fp, "//off_t numvals;\n" );
+  fprintf ( fp, "filename      = %s\n", sp->filename );
+  fprintf ( fp, "//Record   *record;\n" );
+  fprintf ( fp, "nrecs         = %d\n", sp->nrecs );
+  fprintf ( fp, "nvars         = %d\n", sp->nvars );
+  fprintf ( fp, "varlocked     = %d\n", sp->varlocked );
+  fprintf ( fp, "//svarinfo_t *vars;\n" );
+  fprintf ( fp, "varsAllocated = %d\n", sp->varsAllocated );
+  fprintf ( fp, "varinit       = %d\n", sp->varinit );
+  fprintf ( fp, "curTsID       = %d\n", sp->curTsID );
+  fprintf ( fp, "rtsteps       = %d\n", sp->rtsteps );
+  fprintf ( fp, "//long ntsteps;\n" );
+  fprintf ( fp, "numTimestep   = %d\n", sp->numTimestep );
+  fprintf ( fp, "//  tsteps_t   *tsteps;\n" );
+  fprintf ( fp, "tstepsTableSize= %d\n", sp->tstepsTableSize );
+  fprintf ( fp, "tstepsNextID  = %d\n", sp->tstepsNextID );
+  fprintf ( fp, "//basetime_t  basetime;\n" );
+  fprintf ( fp, "ncmode        = %d\n", sp->ncmode );
+  fprintf ( fp, "vlistID       = %d\n", sp->vlistID );
+  fprintf ( fp, "//  int       xdimID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ydimID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       zaxisID[MAX_ZAXES_PS];\n" );
+  fprintf ( fp, "//  int       ncxvarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ncyvarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "//  int       ncavarID[MAX_GRIDS_PS];\n" );
+  fprintf ( fp, "historyID     = %d\n", sp->historyID );
+  fprintf ( fp, "globalatts    = %d\n", sp->globalatts );
+  fprintf ( fp, "localatts     = %d\n", sp->localatts );
+  fprintf ( fp, "//  VCT       vct;\n" );
+  fprintf ( fp, "unreduced     = %d\n", sp->unreduced );
+  fprintf ( fp, "sortname      = %d\n", sp->sortname );
+  fprintf ( fp, "have_missval  = %d\n", sp->have_missval );
+  fprintf ( fp, "ztype         = %d\n", sp->comptype );
+  fprintf ( fp, "zlevel        = %d\n", sp->complevel );
+  fprintf ( fp, "curfile       = %d\n", sp->curfile );
+  fprintf ( fp, "nfiles        = %d\n", sp->nfiles );
+  fprintf ( fp, "//  char    **fnames;\n" );
+  fprintf ( fp, "//  void    **gribContainers;\n" );
+  fprintf ( fp, "vlistIDorig   = %d\n", sp->vlistIDorig );
+}
+
+
+enum {
+  streamNint = 11,
+};
+
+static int
+streamGetPackSize(void * voidP, void *context)
+{
+  stream_t * streamP = ( stream_t * ) voidP;
+  int packBufferSize
+    = serializeGetSize(streamNint, DATATYPE_INT, context)
+    + serializeGetSize(2, DATATYPE_UINT32, context)
+    + serializeGetSize((int)strlen(streamP->filename) + 1,
+                       DATATYPE_TXT, context)
+    + serializeGetSize(1, DATATYPE_FLT64, context);
+  return packBufferSize;
+}
+
+
+static void
+streamPack(void * streamptr, void * packBuffer, int packBufferSize,
+           int * packBufferPos, void *context)
+{
+  stream_t * streamP = ( stream_t * ) streamptr;
+  int intBuffer[streamNint];
+
+  intBuffer[0]  = streamP->self;
+  intBuffer[1]  = streamP->filetype;
+  intBuffer[2]  = (int)strlen(streamP->filename) + 1;
+  intBuffer[3]  = streamP->vlistID;
+  intBuffer[4]  = streamP->vlistIDorig;
+  intBuffer[5]  = streamP->byteorder;
+  intBuffer[6]  = streamP->comptype;
+  intBuffer[7]  = streamP->complevel;
+  intBuffer[8]  = streamP->unreduced;
+  intBuffer[9]  = streamP->sortname;
+  intBuffer[10] = streamP->have_missval;
+
+  serializePack(intBuffer, streamNint, DATATYPE_INT, packBuffer, packBufferSize, packBufferPos, context);
+  uint32_t d = cdiCheckSum(DATATYPE_INT, streamNint, intBuffer);
+  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
+
+  serializePack(&cdiDefaultMissval, 1, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context);
+  serializePack(streamP->filename, intBuffer[2], DATATYPE_TXT, packBuffer, packBufferSize, packBufferPos, context);
+  d = cdiCheckSum(DATATYPE_TXT, intBuffer[2], streamP->filename);
+  serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context);
+}
+
+struct streamAssoc
+streamUnpack(char * unpackBuffer, int unpackBufferSize,
+             int * unpackBufferPos, int originNamespace, void *context)
+{
+  int intBuffer[streamNint], streamID;
+  uint32_t d;
+  char filename[CDI_MAX_NAME];
+
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  intBuffer, streamNint, DATATYPE_INT, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &d, 1, DATATYPE_UINT32, context);
+  xassert(cdiCheckSum(DATATYPE_INT, streamNint, intBuffer) == d);
+
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &cdiDefaultMissval, 1, DATATYPE_FLT64, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &filename, intBuffer[2], DATATYPE_TXT, context);
+  serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                  &d, 1, DATATYPE_UINT32, context);
+  xassert(d == cdiCheckSum(DATATYPE_TXT, intBuffer[2], filename));
+  streamID = streamOpenWrite ( filename, intBuffer[1] );
+  xassert ( streamID >= 0 &&
+            namespaceAdaptKey ( intBuffer[0], originNamespace ) == streamID );
+  streamDefByteorder(streamID, intBuffer[5]);
+  streamDefCompType(streamID, intBuffer[6]);
+  streamDefCompLevel(streamID, intBuffer[7]);
+  stream_t *streamptr = stream_to_pointer(streamID);
+  streamptr->unreduced = intBuffer[8];
+  streamptr->sortname = intBuffer[9];
+  streamptr->have_missval = intBuffer[10];
+  struct streamAssoc retval = { streamID, intBuffer[3], intBuffer[4] };
+  return retval;
+}
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/stream_cdf.c b/libcdi/src/stream_cdf.c
index 58bc0bb..e3b681d 100644
--- a/libcdi/src/stream_cdf.c
+++ b/libcdi/src/stream_cdf.c
@@ -32,6 +32,8 @@
 #define UNDEFID  CDI_UNDEFID
 
 
+void    vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]);
+
 void cdfDefGlobalAtts(stream_t *streamptr);
 void cdfDefLocalAtts(stream_t *streamptr);
 
@@ -126,18 +128,13 @@ ncvar_t;
 static
 void strtolower(char *str)
 {
-  int i, len;
-
   if ( str )
-    {
-      len = (int) strlen(str);
-      for ( i = 0; i < len; i++ )
-        str[i] = tolower((int) str[i]);
-    }
+    for (size_t i = 0; str[i]; ++i)
+      str[i] = (char)tolower((int)str[i]);
 }
 
 static
-int get_timeunit(int len, const char *ptu)
+int get_timeunit(size_t len, const char *ptu)
 {
   int timeunit = -1;
 
@@ -176,18 +173,17 @@ int isTimeUnits(const char *timeunits)
 static
 int isTimeAxisUnits(const char *timeunits)
 {
-  int len, i;
   char *ptu, *tu;
   int timetype = -1;
   int timeunit;
   int status = FALSE;
 
-  len = (int) strlen(timeunits);
-  tu = (char *) malloc((len+1)*sizeof(char));
-  memcpy(tu, timeunits, (len+1)*sizeof(char));
+  size_t len = strlen(timeunits);
+  tu = xmalloc((len+1)*sizeof(char));
+  memcpy(tu, timeunits, (len+1) * sizeof(char));
   ptu = tu;
 
-  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);
+  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
 
   timeunit = get_timeunit(len, ptu);
   if ( timeunit != -1 )
@@ -295,18 +291,17 @@ void setForecastTime(const char *timestr, taxis_t *taxis)
 static
 int setBaseTime(const char *timeunits, taxis_t *taxis)
 {
-  int len, i;
   char *ptu, *tu;
   int timetype = TAXIS_ABSOLUTE;
   int rdate = -1, rtime = -1;
   int timeunit;
 
-  len = (int) strlen(timeunits);
-  tu = (char *) malloc((len+1)*sizeof(char));
-  memcpy(tu, timeunits, (len+1)*sizeof(char));
+  size_t len = strlen(timeunits);
+  tu = xmalloc((len+1) * sizeof (char));
+  memcpy(tu, timeunits, (len+1) * sizeof (char));
   ptu = tu;
 
-  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);
+  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
 
   timeunit = get_timeunit(len, ptu);
   if ( timeunit == -1 )
@@ -376,7 +371,7 @@ void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attin
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
   if ( (int)nc_attlen > attlen )
-    pintatt = (int *) malloc(nc_attlen*sizeof(int));
+    pintatt = (int *) malloc(nc_attlen * sizeof (int));
   else
     pintatt = attint;
 
@@ -384,7 +379,7 @@ void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attin
 
   if ( (int)nc_attlen > attlen )
     {
-      memcpy(attint, pintatt, attlen*sizeof(int));
+      memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
       free(pintatt);
     }
 }
@@ -398,7 +393,7 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
   if ( (int)nc_attlen > attlen )
-    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
+    pdoubleatt = (double *) malloc(nc_attlen * sizeof (double));
   else
     pdoubleatt = attdouble;
 
@@ -406,7 +401,7 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
 
   if ( (int)nc_attlen > attlen )
     {
-      memcpy(attdouble, pdoubleatt, attlen*sizeof(double));
+      memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
       free(pdoubleatt);
     }
 }
@@ -414,31 +409,75 @@ void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double
 static
 void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
 {
+  nc_type atttype;
   size_t nc_attlen;
-  char attbuf[65636];
 
+  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
   cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
 
-  if ( nc_attlen < sizeof(attbuf) )
+  if ( atttype == NC_CHAR )
     {
-      cdf_get_att_text(fileID, ncvarid, attname, attbuf);
+      char attbuf[65636];
+      if ( nc_attlen < sizeof(attbuf) )
+        {
+          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
 
-      attbuf[nc_attlen++] = 0;
+          attbuf[nc_attlen++] = 0;
 
-      if ( (int) nc_attlen > attlen ) nc_attlen = attlen;
-      memcpy(atttext, attbuf, nc_attlen);
+          if ( (int) nc_attlen > attlen ) nc_attlen = (size_t)attlen;
+          memcpy(atttext, attbuf, nc_attlen);
+        }
+      else
+        {
+          atttext[0] = 0;
+        }
     }
-  else
+#if  defined  (HAVE_NETCDF4)
+  else if ( atttype == NC_STRING )
     {
-      atttext[0] = 0;
+      if ( nc_attlen == 1 )
+        {
+          char *attbuf = NULL;
+          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
+
+          int slen = (int) strlen(attbuf);
+          slen++;
+
+          if ( slen > attlen ) slen = attlen;
+          memcpy(atttext, attbuf, slen);
+
+          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 = FALSE;
+
   if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
+
   return isFloat;
 }
 
@@ -527,19 +566,17 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
 
       if ( atttype == DATATYPE_TXT )
         {
-          char *atttxt;
-          atttxt = (char *) malloc(attlen*sizeof(char));
+          char *atttxt = (char *)xmalloc((size_t)attlen*sizeof(char));
           vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
-          len = attlen;
+          len = (size_t)attlen;
           cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
           free(atttxt);
         }
       else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
         {
-          int *attint;
-          attint = (int *) malloc(attlen*sizeof(int));
+          int *attint = (int *)xmalloc((size_t)attlen*sizeof(int));
           vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
-          len = attlen;
+          len = (size_t)attlen;
           if ( atttype == DATATYPE_INT16 )
             cdf_put_att_int(fileID, ncvarID, attname, NC_SHORT, len, attint);
           else
@@ -548,10 +585,9 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
         }
       else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
         {
-          double *attflt;
-          attflt = (double *) malloc(attlen*sizeof(double));
+          double *attflt = (double *)xmalloc((size_t)attlen*sizeof(double));
           vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
-          len = attlen;
+          len = (size_t)attlen;
           if ( atttype == DATATYPE_FLT32 )
             cdf_put_att_double(fileID, ncvarID, attname, NC_FLOAT, len, attflt);
           else
@@ -562,39 +598,30 @@ void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
 }
 #endif
 
-int cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  double *data;
-  int datasize;
-  int tsID1, recID1;
-  int ivarID, gridID;
-  int nmiss;
-  int ierr = 0;
   int memtype = MEMTYPE_DOUBLE;
-  int vlistID1;
+  int vlistID1 = streamptr1->vlistID;
 
-  vlistID1 = streamptr1->vlistID;
+  int tsID1 = streamptr1->curTsID;
 
-  tsID1 = streamptr1->curTsID;
+  int recID1 = streamptr1->tsteps[tsID1].curRecID;
 
-  recID1 = streamptr1->tsteps[tsID1].curRecID;
+  int ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;
 
-  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;
+  int gridID = vlistInqVarGrid(vlistID1, ivarID);
 
-  gridID = vlistInqVarGrid(vlistID1, ivarID);
-
-  datasize = gridInqSize(gridID);
+  int datasize = gridInqSize(gridID);
   /* bug fix for constant netCDF fields */
   if ( datasize < 1048576 ) datasize = 1048576;
 
-  data = (double *) malloc(datasize*sizeof(double));
+  double *data = xmalloc((size_t)datasize * sizeof (double));
 
+  int nmiss;
   cdfReadRecord(streamptr1, data, &nmiss);
   cdf_write_record(streamptr2, memtype, data, nmiss);
 
   free(data);
-
-  return (ierr);
 }
 
 /* not used
@@ -625,36 +652,25 @@ int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
 */
 
 
-int cdfDefRecord(stream_t *streamptr)
+void cdfDefRecord(stream_t *streamptr)
 {
-  int ierr = 0;
-
-  if ( streamptr->fileID < 0 ) ierr = 1;
-
-  return (ierr);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
 static
 void cdfWriteGridTraj(stream_t *streamptr, int gridID)
 {
-  int tsID, fileID;
-  int lonID, latID, gridindex;
-  size_t index;
-  double xlon, xlat;
-  int vlistID;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  lonID = streamptr->xdimID[gridindex];
-  latID = streamptr->ydimID[gridindex];
+  int gridindex = vlistGridIndex(vlistID, gridID);
+  int lonID = streamptr->xdimID[gridindex],
+    latID = streamptr->ydimID[gridindex];
 
-  xlon = gridInqXval(gridID, 0);
-  xlat = gridInqYval(gridID, 0);
-  tsID = streamptr->curTsID;
-  index = tsID;
+  double xlon = gridInqXval(gridID, 0),
+    xlat = gridInqYval(gridID, 0);
+  int tsID = streamptr->curTsID;
+  size_t index = (size_t)tsID;
 
   cdf_put_var1_double(fileID, lonID, &index, &xlon);
   cdf_put_var1_double(fileID, latID, &index, &xlat);
@@ -663,22 +679,17 @@ void cdfWriteGridTraj(stream_t *streamptr, int gridID)
 static
 void cdfReadGridTraj(stream_t *streamptr, int gridID)
 {
-  int tsID, fileID;
-  int lonID, latID, gridindex;
-  size_t index;
-  double xlon, xlat;
-  int vlistID;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  lonID = streamptr->xdimID[gridindex];
-  latID = streamptr->ydimID[gridindex];
+  int gridindex = vlistGridIndex(vlistID, gridID);
+  int lonID = streamptr->xdimID[gridindex];
+  int latID = streamptr->ydimID[gridindex];
 
-  tsID = streamptr->curTsID;
-  index = tsID;
+  int tsID = streamptr->curTsID;
+  size_t index = (size_t)tsID;
 
+  double xlon, xlat;
   cdf_get_var1_double(fileID, lonID, &index, &xlon);
   cdf_get_var1_double(fileID, latID, &index, &xlat);
 
@@ -790,10 +801,8 @@ void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nm
 #endif
 }
 
-
-int cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
-  int ierr = 0;
   int levelID, varID, tsID, recID, vrecID;
 
   if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
@@ -805,8 +814,6 @@ int cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
   levelID = streamptr->tsteps[tsID].records[recID].levelID;
 
   cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
-
-  return (ierr);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
@@ -814,9 +821,7 @@ static
 void cdfDefTimeValue(stream_t *streamptr, int tsID)
 {
   int fileID;
-  double timevalue;
   int ncvarid;
-  size_t index;
   taxis_t *taxis;
 
   fileID = streamptr->fileID;
@@ -832,9 +837,9 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       streamptr->ncmode = 2;
     }
 
-  index = tsID;
+  size_t index = (size_t)tsID;
 
-  timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
+  double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
   if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
 
   ncvarid = streamptr->basetime.ncvarid;
@@ -847,11 +852,11 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       ncvarid = streamptr->basetime.ncvarboundsid;
 
       timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
-      start[0] = tsID; count[0] = 1; start[1] = 0; count[1] = 1;
+      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] = tsID; count[0] = 1; start[1] = 1; count[1] = 1;
+      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
       cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
     }
 
@@ -934,7 +939,8 @@ void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
       cdiDecodeDate(rdate, &year, &month, &day);
       cdiDecodeTime(rtime, &hour, &minute, &second);
 
-      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
+      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;
@@ -951,7 +957,8 @@ void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
 
   if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
 
-  if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
+  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;
@@ -1097,7 +1104,6 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
   int gridID0, gridtype0, gridindex;
   int ngrids;
   int fileID;
-  int dimlen;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -1121,7 +1127,7 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
 
   if ( dimID == UNDEFID )
     {
-      dimlen = 2;
+      size_t dimlen = 2;
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
@@ -1149,7 +1155,6 @@ void cdfDefSP(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -1157,7 +1162,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID)/2;
+  size_t dimlen = (size_t)gridInqSize(gridID)/2;
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -1167,7 +1172,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_SPECTRAL )
             {
-              dimlen0 = gridInqSize(gridID0)/2;
+              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
                 {
                   dimID = streamptr->ydimID[index];
@@ -1207,7 +1212,6 @@ void cdfDefFC(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -1215,7 +1219,7 @@ void cdfDefFC(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID)/2;
+  size_t dimlen = (size_t)gridInqSize(gridID)/2;
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -1225,7 +1229,7 @@ void cdfDefFC(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_FOURIER )
             {
-              dimlen0 = gridInqSize(gridID0)/2;
+              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
               if ( dimlen == dimlen0 )
                 {
                   dimID = streamptr->ydimID[index];
@@ -1385,7 +1389,7 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
   checkname = TRUE;
   iz = 0;
 
-  while ( checkname )
+  do
     {
       strcpy(axisname2, axisname);
       if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%d", iz+1);
@@ -1423,9 +1427,9 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
         }
 
       if ( checkname ) iz++;
-
-      if ( iz > 99 ) break;
     }
+  while (checkname && iz <= 99);
+
 
   if ( iz ) sprintf(&axisname[strlen(axisname)], "_%d", iz+1);
 
@@ -1448,10 +1452,9 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
   int dimIDs[2];
   int ngrids = 0;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -1462,7 +1465,7 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqXsize(gridID);
+  size_t dimlen = (size_t)gridInqXsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, axisname);
@@ -1483,10 +1486,10 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqXsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
               if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, dimlen-1), gridInqXval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
                   {
                     dimID = streamptr->xdimID[index];
                     break;
@@ -1516,6 +1519,7 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
 
           if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
             {
+              size_t nvertex = 2;
               if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
                 cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
             }
@@ -1579,10 +1583,9 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
   int dimIDs[2];
   int ngrids = 0;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -1593,7 +1596,7 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
 
   if ( ndims ) ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqYsize(gridID);
+  size_t dimlen = (size_t)gridInqYsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqYname(gridID, axisname);
@@ -1614,10 +1617,10 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqYsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqYsize(gridID0);
               if ( dimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, dimlen-1), gridInqYval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) )
                   {
                     dimID = streamptr->ydimID[index];
                     break;
@@ -1647,6 +1650,7 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
 
           if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
             {
+              size_t nvertex = 2;
               if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
                 cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
             }
@@ -1730,11 +1734,10 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
   int dimIDs[3];
   int ngrids;
   int fileID;
-  int xdimlen, ydimlen, dimlen0;
   size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvertex = 4, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -1745,8 +1748,8 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  xdimlen = gridInqXsize(gridID);
-  ydimlen = gridInqYsize(gridID);
+  size_t xdimlen = (size_t)gridInqXsize(gridID);
+  size_t ydimlen = (size_t)gridInqYsize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, xaxisname);
@@ -1769,19 +1772,19 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
                gridtype0 == GRID_CURVILINEAR ||
                gridtype0 == GRID_GENERIC )
             {
-              dimlen0 = gridInqXsize(gridID0);
+              size_t dimlen0 = (size_t)gridInqXsize(gridID0);
               if ( xdimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
-                     IS_EQUAL(gridInqXval(gridID0, xdimlen-1), gridInqXval(gridID, xdimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)xdimlen-1), gridInqXval(gridID, (int)xdimlen-1)) )
                   {
                     xdimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
                     break;
                   }
-              dimlen0 = gridInqYsize(gridID0);
+              dimlen0 = (size_t)gridInqYsize(gridID0);
               if ( ydimlen == dimlen0 )
                 if ( IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) &&
-                     IS_EQUAL(gridInqYval(gridID0, xdimlen-1), gridInqYval(gridID, xdimlen-1)) )
+                     IS_EQUAL(gridInqYval(gridID0, (int)xdimlen-1), gridInqYval(gridID, (int)xdimlen-1)) )
                   {
                     ydimID = streamptr->ydimID[index];
                     ncyvarid = streamptr->ncyvarID[index];
@@ -1805,6 +1808,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
 
       if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
         {
+          size_t nvertex = 4;
           if ( nc_inq_dimid(fileID, "nv4", &nvdimID) != NC_NOERR )
             cdf_def_dim(fileID, "nv4", nvertex, &nvdimID);
         }
@@ -1815,7 +1819,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
       if ( gridInqXvalsPtr(gridID) )
         {
           cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(xstdname)) )
             cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
@@ -1834,7 +1838,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
               dimIDs[1] = xdimID;
               dimIDs[2] = nvdimID;
               cdf_def_var(fileID, xaxisname, (nc_type) xtype, 3, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
             }
@@ -1843,7 +1847,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
       if ( gridInqYvalsPtr(gridID) )
         {
           cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(ystdname)) )
             cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
@@ -1862,7 +1866,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
               dimIDs[1] = xdimID;
               dimIDs[2] = nvdimID;
               cdf_def_var(fileID, yaxisname, (nc_type) xtype, 3, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, xdimlen*ydimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
             }
@@ -1910,7 +1914,6 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
   int lwarn = TRUE;
 
@@ -1919,7 +1922,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
 
   for ( index = 0; index < ngrids; index++ )
     {
@@ -1929,7 +1932,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
             {
-              dimlen0 = gridInqSize(gridID0);
+              size_t dimlen0 = (size_t)gridInqSize(gridID0);
 
               if ( dimlen == dimlen0 )
                 {
@@ -1976,7 +1979,6 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   int vlistID;
 
   vlistID = streamptr->vlistID;
@@ -1984,7 +1986,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
 
   if ( gridInqYsize(gridID) == 0 )
     for ( index = 0; index < ngrids; index++ )
@@ -1995,7 +1997,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
             gridtype0 = gridInqType(gridID0);
             if ( gridtype0 == GRID_GENERIC )
               {
-                dimlen0 = gridInqSize(gridID0);
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
                 if ( dimlen == dimlen0 )
                   {
                     dimID = streamptr->xdimID[index];
@@ -2016,7 +2018,7 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
             gridtype0 = gridInqType(gridID0);
             if ( gridtype0 == GRID_GENERIC )
               {
-                dimlen0 = gridInqSize(gridID0);
+                size_t dimlen0 = (size_t)gridInqSize(gridID0);
                 if ( dimlen == dimlen0 )
                   {
                     dimID = streamptr->ydimID[index];
@@ -2130,11 +2132,10 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
   int dimID = UNDEFID;
   int ngrids;
   int fileID;
-  int dimlen, dimlen0;
   size_t len;
   int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
   int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
-  int nvertex, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int vlistID;
   int xtype = NC_DOUBLE;
 
@@ -2145,7 +2146,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
   ngrids = vlistNgrids(vlistID);
 
-  dimlen = gridInqSize(gridID);
+  size_t dimlen = (size_t)gridInqSize(gridID);
   gridindex = vlistGridIndex(vlistID, gridID);
 
   gridInqXname(gridID, xaxisname);
@@ -2165,11 +2166,11 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
           gridtype0 = gridInqType(gridID0);
           if ( gridtype0 == GRID_UNSTRUCTURED )
             {
-              dimlen0 = gridInqSize(gridID0);
+              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, dimlen-1), gridInqXval(gridID, dimlen-1)) )
+                     IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) )
 		  {
 		    dimID = streamptr->xdimID[index];
                     ncxvarid = streamptr->ncxvarID[index];
@@ -2197,7 +2198,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
 
       cdf_def_dim(fileID, axisname, dimlen, &dimID);
 
-      nvertex = gridInqNvertex(gridID);
+      size_t nvertex = (size_t)gridInqNvertex(gridID);
       if ( nvertex > 0 ) cdf_def_dim(fileID, vertname, nvertex, &nvdimID);
 
       cdfDefGridReference(streamptr, gridID);
@@ -2207,7 +2208,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
       if ( gridInqXvalsPtr(gridID) )
         {
           cdf_def_var(fileID, xaxisname, (nc_type) xtype, 1, &dimID, &ncxvarid);
-          cdfGridCompress(fileID, ncxvarid, dimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(xstdname)) )
             cdf_put_att_text(fileID, ncxvarid, "standard_name", len, xstdname);
@@ -2223,7 +2224,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               dimIDs[1] = nvdimID;
               strcat(xaxisname, "_vertices");
               cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncbxvarid);
-              cdfGridCompress(fileID, ncbxvarid, dimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
             }
@@ -2232,7 +2233,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
       if ( gridInqYvalsPtr(gridID) )
         {
           cdf_def_var(fileID, yaxisname, (nc_type) xtype, 1, &dimID, &ncyvarid);
-          cdfGridCompress(fileID, ncyvarid, dimlen, streamptr->filetype, streamptr->comptype);
+          cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
           if ( (len = strlen(ystdname)) )
             cdf_put_att_text(fileID, ncyvarid, "standard_name", len, ystdname);
@@ -2248,7 +2249,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
               dimIDs[1] = nvdimID;
               strcat(yaxisname, "_vertices");
               cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncbyvarid);
-              cdfGridCompress(fileID, ncbyvarid, dimlen, streamptr->filetype, streamptr->comptype);
+              cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
 
               cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
             }
@@ -2322,8 +2323,8 @@ void cdfDefVCT(stream_t *streamptr, int zaxisID)
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      cdf_def_dim(fileID, "nhym", mlev, &ncdimid);
-      cdf_def_dim(fileID, "nhyi", ilev, &ncdimid2);
+      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;
@@ -2362,7 +2363,7 @@ void cdfDefVCT(stream_t *streamptr, int zaxisID)
 
       for ( i = 0; i < mlev; i++ )
         {
-          start = 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;
@@ -2387,10 +2388,9 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
   int dimID = UNDEFID;
   int dimIDs[2];
   int fileID;
-  int dimlen;
   size_t len;
   int ncvarid = UNDEFID, ncbvarid = UNDEFID;
-  int nvertex = 2, nvdimID = UNDEFID;
+  int nvdimID = UNDEFID;
   int type;
   int nzaxis;
   int ilevel = 0;
@@ -2408,22 +2408,27 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
   nzaxis = vlistNzaxis(vlistID);
 
-  dimlen = zaxisInqSize(zaxisID);
+  size_t dimlen = (size_t)zaxisInqSize(zaxisID);
   type   = zaxisInqType(zaxisID);
 
-  if ( dimlen == 1 && type == ZAXIS_SURFACE            ) return;
-  if ( dimlen == 1 && type == ZAXIS_CLOUD_BASE         ) return;
-  if ( dimlen == 1 && type == ZAXIS_CLOUD_TOP          ) return;
-  if ( dimlen == 1 && type == ZAXIS_ISOTHERM_ZERO      ) return;
-  if ( dimlen == 1 && type == ZAXIS_TOA                ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEA_BOTTOM         ) return;
-  if ( dimlen == 1 && type == ZAXIS_ATMOSPHERE         ) return;
-  if ( dimlen == 1 && type == ZAXIS_MEANSEA            ) return;
-  if ( dimlen == 1 && type == ZAXIS_LAKE_BOTTOM        ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM    ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM_TA ) return;
-  if ( dimlen == 1 && type == ZAXIS_SEDIMENT_BOTTOM_TW ) return;
-  if ( dimlen == 1 && type == ZAXIS_MIX_LAYER          ) return;
+  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);
   /*
@@ -2588,6 +2593,7 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
 	  if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
             {
+              size_t nvertex = 2;
 	      if ( nc_inq_dimid(fileID, "nb2", &nvdimID) != NC_NOERR )
 		cdf_def_dim(fileID, "nb2", nvertex, &nvdimID);
 
@@ -2608,7 +2614,6 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 
           if ( ncbvarid != UNDEFID )
 	    {
-	      int i;
 	      double *zbounds, *lbounds, *ubounds;
 
 	      lbounds = (double *) malloc(dimlen*sizeof(double));
@@ -2618,7 +2623,7 @@ void cdfDefZaxis(stream_t *streamptr, int zaxisID)
 	      zaxisInqLbounds(zaxisID, lbounds);
 	      zaxisInqUbounds(zaxisID, ubounds);
 
-	      for ( i = 0; i < dimlen; ++i )
+	      for (size_t i = 0; i < dimlen; ++i )
 		{
 		  zbounds[2*i  ] = lbounds[i];
 		  zbounds[2*i+1] = ubounds[i];
@@ -2887,7 +2892,6 @@ int cdfDefVar(stream_t *streamptr, int varID)
   size_t chunks[4] = {0,0,0,0};
   int tableID;
   int ndims = 0;
-  int len;
   int tsteptype;
   int xtype, dtype;
   int gridtype, gridsize;
@@ -2895,8 +2899,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
   int tablenum;
   int vlistID;
   int dimorder[3];
-  int ixyz;
-  int iax = 0;
+  size_t iax = 0;
   char axis[5];
   int ensID, ensCount, forecast_type;
   int retval;
@@ -2919,8 +2922,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   chunktype = vlistInqVarChunkType(vlistID, varID);
 
-  ixyz    = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
+  vlistInqVarDimorder(vlistID, varID, &dimorder);
 
   gridsize  = gridInqSize(gridID);
   if ( gridsize > 1 ) lchunk = TRUE;
@@ -2937,14 +2939,11 @@ int cdfDefVar(stream_t *streamptr, int varID)
   zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
   zid = streamptr->zaxisID[zaxisindex];
 
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
   if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
 
   if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
     {
-      printf("xyz=%d  zid=%d  yid=%d  xid=%d\n", ixyz, zid, yid, xid);
+      printf("zid=%d  yid=%d  xid=%d\n", zid, yid, xid);
       Error("Internal problem, dimension order missing!");
     }
 
@@ -3176,7 +3175,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT  && gridtype != GRID_CURVILINEAR )
     {
-      len = strlen(gridNamePtr(gridtype));
+      size_t len = strlen(gridNamePtr(gridtype));
       if ( len > 0 )
         cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
     }
@@ -3361,9 +3360,8 @@ int cdfDefVar(stream_t *streamptr, int varID)
 }
 
 static
-void scale_add(long size, double *data, double addoffset, double scalefactor)
+void scale_add(size_t size, double *data, double addoffset, double scalefactor)
 {
-  long i;
   int laddoffset;
   int lscalefactor;
 
@@ -3372,7 +3370,7 @@ void scale_add(long size, double *data, double addoffset, double scalefactor)
 
   if ( laddoffset || lscalefactor )
     {
-      for ( i = 0; i < size; ++i )
+      for (size_t i = 0; i < size; ++i )
         {
           if ( lscalefactor ) data[i] *= scalefactor;
           if ( laddoffset )   data[i] += addoffset;
@@ -3381,44 +3379,20 @@ void scale_add(long size, double *data, double addoffset, double scalefactor)
 }
 #endif
 
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+#if defined (HAVE_LIBNETCDF)
+static
+void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
 {
-#if  defined  (HAVE_LIBNETCDF)
-  int fileID;
-  int gridID;
-  int zaxisID;
-  int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-  int ncvarid;
-  int tsID;
-  size_t size;
-  size_t start[5];
-  size_t count[5];
-  int ndims = 0;
-  int idim;
-  int tsteptype;
-  int gridindex, zaxisindex;
-  int vlistID;
-  int i;
-  double missval;
-  int laddoffset, lscalefactor;
-  double addoffset, scalefactor;
-
-  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  tsID = streamptr->curTsID;
+  int vlistID = streamptr->vlistID;
+  int tsID = streamptr->curTsID;
+  int gridID    = vlistInqVarGrid(vlistID, varID);
+  int zaxisID   = vlistInqVarZaxis(vlistID, varID);
+  int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+  int gridindex = vlistGridIndex(vlistID, gridID);
 
   if ( CDI_Debug ) Message("tsID = %d", tsID);
 
-  ncvarid = streamptr->vars[varID].ncvarid;
-
-  gridID    = vlistInqVarGrid(vlistID, varID);
-  zaxisID   = vlistInqVarZaxis(vlistID, varID);
-  tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
-  gridindex = vlistGridIndex(vlistID, gridID);
+  int xid = UNDEFID, yid = UNDEFID;
   if ( gridInqType(gridID) == GRID_TRAJECTORY )
     {
       cdfReadGridTraj(streamptr, gridID);
@@ -3428,89 +3402,139 @@ void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
       xid = streamptr->xdimID[gridindex];
       yid = streamptr->ydimID[gridindex];
     }
+  int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+  int zid = streamptr->zaxisID[zaxisindex];
 
-  zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-  zid = streamptr->zaxisID[zaxisindex];
-
-  if ( tsteptype != TSTEP_CONSTANT )
-    {
-      start[ndims] = tsID;
-      count[ndims] = 1;
-      ndims++;
-    }
-  if ( zid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = zaxisInqSize(zaxisID);
-      ndims++;
-    }
-  if ( yid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = gridInqYsize(gridID);
-      ndims++;
-    }
-  if ( xid != UNDEFID )
-    {
-      start[ndims] = 0;
-      count[ndims] = gridInqXsize(gridID);
-      ndims++;
-    }
+  int ndims = 0;
+#define addDimension(startCoord, length) do \
+    { \
+      (*start)[ndims] = startCoord; \
+      (*count)[ndims] = length; \
+      ndims++; \
+    } while(0)
+  if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+  if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
+  if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
+  if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
+#undef addDimension
+
+  assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+  assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
 
   if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
+    for (int idim = 0; idim < ndims; idim++)
       Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
+}
 
-  cdf_get_vara_double(fileID, ncvarid, start, count, data);
-
-  *nmiss = 0;
-  if ( vlistInqVarMissvalUsed(vlistID, varID) == TRUE  )
-    {
-      size    = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-      missval = vlistInqVarMissval(vlistID, varID);
-
-      for ( i = 0; i < (int) size; i++ )
-        if ( DBL_IS_EQUAL(data[i], missval) ) *nmiss += 1;
-    }
-
-  addoffset    = vlistInqVarAddoffset(vlistID, varID);
-  scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-  laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-  lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
-  if ( laddoffset || lscalefactor )
-    {
-      size    = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-      missval = vlistInqVarMissval(vlistID, varID);
+//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
+//Returns the number of missVals encountered.
+static
+size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissval, double missVal, double scaleFactor, double offset)
+ {
+  const bool haveOffset   = IS_NOT_EQUAL(offset, 0);
+  const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+  size_t missValCount = 0;
+
+  switch ((int)haveMissval | ((int)haveScaleFactor << 1) | ((int)haveOffset << 2))
+    {
+    case 7: /* haveMissval & haveScaleFactor & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 6: /* haveOffset & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 5: /* haveMissval & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] += offset;
+      break;
+    case 4: /* haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] += offset;
+      break;
+    case 3: /* haveMissval & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] *= scaleFactor;
+      break;
+    case 2: /* haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] *= scaleFactor;
+      break;
+    case 1: /* haveMissval */
+      for ( size_t i = 0; i < valueCount; i++ )
+        missValCount += DBL_IS_EQUAL(data[i], missVal);
+      break;
+    }
+
+  return missValCount;
+}
 
-      if ( *nmiss > 0 )
-        {
-          for ( i = 0; i < (int) size; i++ )
-            {
-              if ( !DBL_IS_EQUAL(data[i], missval) )
-                {
-                  if ( lscalefactor ) data[i] *= scalefactor;
-                  if ( laddoffset )   data[i] += addoffset;
-                }
-            }
-        }
-      else
-        {
-          for ( i = 0; i < (int) size; i++ )
-            {
-              if ( lscalefactor ) data[i] *= scalefactor;
-              if ( laddoffset )   data[i] += addoffset;
-            }
-        }
-    }
-#endif
+static
+size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissval, double missVal, double scaleFactor, double offset)
+ {
+  const bool haveOffset   = IS_NOT_EQUAL(offset, 0);
+  const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+  size_t missValCount = 0;
+
+  switch ((int)haveMissval | ((int)haveScaleFactor << 1) | ((int)haveOffset << 2))
+    {
+    case 7: /* haveMissval & haveScaleFactor & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 6: /* haveOffset & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] = data[i] * scaleFactor + offset;
+      break;
+    case 5: /* haveMissval & haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] += offset;
+      break;
+    case 4: /* haveOffset */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] += offset;
+      break;
+    case 3: /* haveMissval & haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        if ( DBL_IS_EQUAL(data[i], missVal) )
+          missValCount++;
+        else
+          data[i] *= scaleFactor;
+      break;
+    case 2: /* haveScaleFactor */
+      for ( size_t i = 0; i < valueCount; i++ )
+        data[i] *= scaleFactor;
+      break;
+    case 1: /* haveMissval */
+      for ( size_t i = 0; i < valueCount; i++ )
+        missValCount += DBL_IS_EQUAL(data[i], missVal);
+      break;
+    }
+
+  return missValCount;
 }
+#endif
 
 #if defined(HAVE_LIBNETCDF)
-static
-int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
+static void
+cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
 {
-  long i, j;
   const double *pdata_dp = (const double *) data;
   double *mdata_dp = NULL;
   double *sdata_dp = NULL;
@@ -3521,7 +3545,7 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
 
   /*  if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
     {
-      int laddoffset, lscalefactor;
+      bool laddoffset, lscalefactor;
       double addoffset, scalefactor;
       double missval;
 
@@ -3536,39 +3560,43 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
         {
           if ( memtype == MEMTYPE_FLOAT )
             {
-              mdata_sp = (float *) malloc(nvals*sizeof(float));
-              memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+              mdata_sp = (float *) malloc((size_t)nvals*sizeof(float));
+              memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof (float));
               pdata_sp = mdata_sp;
 
               if ( nmiss > 0 )
                 {
-                  for ( i = 0; i < nvals; i++ )
+                  for (long i = 0; i < nvals; i++ )
                     {
-                      if ( !DBL_IS_EQUAL(mdata_sp[i], missval) )
+                      double temp = mdata_sp[i];
+                      if ( !DBL_IS_EQUAL(temp, missval) )
                         {
-                          if ( laddoffset )   mdata_sp[i] -= addoffset;
-                          if ( lscalefactor ) mdata_sp[i] /= scalefactor;
+                          if ( laddoffset )   temp -= addoffset;
+                          if ( lscalefactor ) temp /= scalefactor;
+                          mdata_sp[i] = temp;
                         }
                     }
                 }
               else
                 {
-                  for ( i = 0; i < nvals; i++ )
+                  for (long i = 0; i < nvals; i++ )
                     {
-                      if ( laddoffset )   mdata_sp[i] -= addoffset;
-                      if ( lscalefactor ) mdata_sp[i] /= scalefactor;
+                      double temp = mdata_sp[i];
+                      if ( laddoffset )   temp -= addoffset;
+                      if ( lscalefactor ) temp /= scalefactor;
+                      mdata_sp[i] = temp;
                     }
                 }
             }
           else
             {
-              mdata_dp = (double *) malloc(nvals*sizeof(double));
-              memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+              mdata_dp = (double *) malloc((size_t)nvals * sizeof(double));
+              memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof(double));
               pdata_dp = mdata_dp;
 
               if ( nmiss > 0 )
                 {
-                  for ( i = 0; i < nvals; i++ )
+                  for (long i = 0; i < nvals; i++ )
                     {
                       if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
                         {
@@ -3579,7 +3607,7 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
                 }
               else
                 {
-                  for ( i = 0; i < nvals; i++ )
+                  for (long i = 0; i < nvals; i++ )
                     {
                       if ( laddoffset )   mdata_dp[i] -= addoffset;
                       if ( lscalefactor ) mdata_dp[i] /= scalefactor;
@@ -3595,12 +3623,12 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
             {
               if ( mdata_sp == NULL )
                 {
-                  mdata_sp = (float *) malloc(nvals*sizeof(float));
-                  memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+                  mdata_sp = (float *) malloc((size_t)nvals * sizeof(float));
+                  memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof(float));
                   pdata_sp = mdata_sp;
                 }
 
-              for ( i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
+              for (long i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
 
               if ( dtype == DATATYPE_UINT8 )
                 {
@@ -3608,7 +3636,7 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
                   cdf_inq_vartype(fileID, ncvarid, &xtype);
                   if ( xtype == NC_BYTE )
                     {
-                      for ( i = 0; i < nvals; ++i )
+                      for ( long i = 0; i < nvals; ++i )
                         if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
                     }
                 }
@@ -3617,12 +3645,12 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
             {
               if ( mdata_dp == NULL )
                 {
-                  mdata_dp = (double *) malloc(nvals*sizeof(double));
-                  memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+                  mdata_dp = (double *) malloc((size_t)nvals * sizeof (double));
+                  memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof (double));
                   pdata_dp = mdata_dp;
                 }
 
-              for ( i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
+              for (long i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
 
               if ( dtype == DATATYPE_UINT8 )
                 {
@@ -3630,7 +3658,7 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
                   cdf_inq_vartype(fileID, ncvarid, &xtype);
                   if ( xtype == NC_BYTE )
                     {
-                      for ( i = 0; i < nvals; ++i )
+                      for (long i = 0; i < nvals; ++i )
                         if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
                     }
                 }
@@ -3642,7 +3670,7 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
           double fmin, fmax;
           fmin =  1.0e200;
           fmax = -1.0e200;
-          for ( i = 0; i < nvals; ++i )
+          for ( long i = 0; i < nvals; ++i )
             {
               if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
                 {
@@ -3659,17 +3687,19 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
     {
       if ( memtype == MEMTYPE_FLOAT )
         {
-          sdata_sp = (float *) malloc(nvals*sizeof(float));
-          for ( j = 0; j < (long)ysize; ++j )
-            for ( i = 0; i < (long)xsize; ++i )
+          /* malloc and the loop imply nvals >= ysize * xsize,
+           * but that is not checked and the types don't match */
+          sdata_sp = (float *)xmalloc((size_t)nvals * sizeof (float));
+          for ( size_t j = 0; j < ysize; ++j )
+            for ( size_t i = 0; i < xsize; ++i )
               sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
           pdata_sp = sdata_sp;
         }
       else
         {
-          sdata_dp = (double *) malloc(nvals*sizeof(double));
-          for ( j = 0; j < (long)ysize; ++j )
-            for ( i = 0; i < (long)xsize; ++i )
+          sdata_dp = (double *)xmalloc((size_t)nvals * sizeof (double));
+          for ( size_t j = 0; j < ysize; ++j )
+            for ( size_t i = 0; i < xsize; ++i )
               sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
           pdata_dp = sdata_dp;
         }
@@ -3684,8 +3714,6 @@ int cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtyp
   if ( sdata_dp ) free(sdata_dp);
   if ( mdata_sp ) free(mdata_sp);
   if ( sdata_sp ) free(sdata_sp);
-
-  return (0);
 }
 #endif
 
@@ -3697,7 +3725,6 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int ntsteps;
   size_t xsize = 0, ysize = 0;
   size_t size;
   size_t start[5];
@@ -3716,8 +3743,8 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
   vlistID = streamptr->vlistID;
   fileID  = streamptr->fileID;
 
-  ntsteps = streamptr->ntsteps;
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+  long ntsteps = streamptr->ntsteps;
+  if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
 
   if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
@@ -3743,14 +3770,14 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = ntsteps - 1;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
   if ( zid != UNDEFID )
     {
       start[ndims] = 0;
-      count[ndims] = zaxisInqSize(zaxisID);
+      count[ndims] = (size_t)zaxisInqSize(zaxisID);
       ndims++;
     }
   if ( yid != UNDEFID )
@@ -3800,7 +3827,6 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int ntsteps;
   size_t xsize = 0, ysize = 0;
   size_t start[5];
   size_t count[5];
@@ -3820,9 +3846,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
   vlistID = streamInqVlist(streamID);
   fileID  = streamInqFileID(streamID);
 
-  ntsteps = streamptr->ntsteps;
+  long ntsteps = streamptr->ntsteps;
   if ( CDI_Debug )
-    Message("ntsteps = %d", ntsteps);
+    Message("ntsteps = %ld", ntsteps);
 
   if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
@@ -3848,34 +3874,37 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = ntsteps - 1;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
   if ( zid != UNDEFID )
     {
       int size = zaxisInqSize(zaxisID);
-      xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1] && rect[2][1] <= size);
-      start[ndims] = rect[2][0];
-      count[ndims] = rect[2][1] - rect[2][0] + 1;
+      xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
+              && rect[2][1] <= size);
+      start[ndims] = (size_t)rect[2][0];
+      count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
       ndims++;
     }
   if ( yid != UNDEFID )
     {
       size_t size;
       cdf_inq_dimlen(fileID, yid, &size);
-      xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1] && rect[1][1] <= (int)size);
-      start[ndims] = rect[1][0];
-      count[ndims] = rect[1][1] - rect[1][0] + 1;
+      xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
+              && rect[1][1] <= (int)size);
+      start[ndims] = (size_t)rect[1][0];
+      count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
       ndims++;
     }
   if ( xid != UNDEFID )
     {
       size_t size;
       cdf_inq_dimlen(fileID, xid, &size);
-      xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1] && rect[0][1] <= (int)size);
-      start[ndims] = rect[0][0];
-      count[ndims] = rect[0][1] - rect[0][0] + 1;
+      xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
+              && rect[0][1] <= (int)size);
+      start[ndims] = (size_t)rect[0][0];
+      count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
       ndims++;
     }
 
@@ -3900,8 +3929,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
 }
 #endif
 
+#if  defined  (HAVE_LIBNETCDF)
 static
-int set_validrange(long gridsize, double *data, double missval, double validmin, double validmax)
+int set_validrangeDP(long gridsize, double *data, double missval, double validmin, double validmax)
 {
   long i;
   int nmiss = 0;
@@ -3949,184 +3979,350 @@ int set_validrange(long gridsize, double *data, double missval, double validmin,
   return (nmiss);
 }
 
-
-int cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
+static
+int set_validrangeSP(long gridsize, float *data, double missval, double validmin, double validmax)
 {
-#if  defined  (HAVE_LIBNETCDF)
-  int fileID;
-  int gridID;
-  int zaxisID;
-  int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-  int ncvarid;
-  int tsID;
-  int gridsize, xsize, ysize;
-  size_t size;
-  size_t start[5];
-  size_t count[5];
-  int ndims = 0;
-  int nvdims;
-  int idim;
-  int tsteptype;
-  int gridindex;
-  int zaxisindex;
-  int vlistID;
-  int i, j;
-  int dimorder[3];
-  int ixyz;
-  int swapxy = FALSE;
-  int lvalidrange;
-  double validrange[2];
-  double missval;
-  int laddoffset, lscalefactor;
-  double addoffset, scalefactor;
-
-  if ( CDI_Debug )
-    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  tsID = streamptr->curTsID;
-  if ( CDI_Debug ) Message("tsID = %d", tsID);
-
-  ncvarid = streamptr->vars[varID].ncvarid;
-  cdf_inq_varndims(fileID, ncvarid, &nvdims);
-
-  gridID    = vlistInqVarGrid(vlistID, varID);
-  zaxisID   = vlistInqVarZaxis(vlistID, varID);
-  tsteptype = vlistInqVarTsteptype(vlistID, varID);
-  ixyz      = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
-
-  gridsize = gridInqSize(gridID);
-  xsize = gridInqXsize(gridID);
-  ysize = gridInqYsize(gridID);
-
-  streamptr->numvals += gridsize;
+  long i;
+  int nmiss = 0;
+  /*
+  for ( i = 0; i < gridsize; i++, data++ )
+    {
+      if ( IS_NOT_EQUAL(validmin, VALIDMISS) && (*data) < validmin ) *data = missval;
+      if ( IS_NOT_EQUAL(validmax, VALIDMISS) && (*data) > validmax ) *data = missval;
+      if ( DBL_IS_EQUAL((*data), missval) ) nmiss++;
+    }
+  */
+  // 21/01/2014 Florian Prill: SX-9 vectorization
 
-  gridindex = vlistGridIndex(vlistID, gridID);
-  if ( gridInqType(gridID) == GRID_TRAJECTORY )
+  if ( IS_NOT_EQUAL(validmin, VALIDMISS) && !IS_NOT_EQUAL(validmax, VALIDMISS) )
     {
-      cdfReadGridTraj(streamptr, gridID);
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if ( (*data) < validmin )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
     }
-  else if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
+  else if ( IS_NOT_EQUAL(validmax, VALIDMISS) && !IS_NOT_EQUAL(validmin, VALIDMISS))
     {
-      xid = streamptr->xdimID[gridindex];
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if ( (*data) > validmax )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
+    }
+  else if ( IS_NOT_EQUAL(validmin, VALIDMISS) && IS_NOT_EQUAL(validmax, VALIDMISS))
+    {
+      for ( i = 0; i < gridsize; i++, data++ )
+        {
+          if      ( (*data) < validmin )  { (*data) = missval; nmiss++; }
+          else if ( (*data) > validmax )  { (*data) = missval; nmiss++; }
+          else if ( DBL_IS_EQUAL((*data), missval) )  nmiss++;
+        } // i
     }
   else
     {
-      xid = streamptr->xdimID[gridindex];
-      yid = streamptr->ydimID[gridindex];
+      for ( i = 0; i < gridsize; i++, data++ )
+        if ( DBL_IS_EQUAL((*data), missval) ) nmiss++;
     }
 
-  zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
-  zid = streamptr->zaxisID[zaxisindex];
+  return (nmiss);
+}
+#endif
 
-  int skipdim = 0;
-  if ( xid == -1 && yid == -1 && nvdims == 3 )
-    {
-      int dimids[3];
-      cdf_inq_vardimid(fileID, ncvarid, dimids);
-      size = 0;
-      if ( zid == dimids[2] )
+#if  defined  (HAVE_LIBNETCDF)
+static
+size_t min_size(size_t a, size_t b)
+{
+  return a < b ? a : b;
+}
+
+static
+void transpose2dArrayDP(size_t inWidth, size_t inHeight, double* data)
+{
+  const size_t cacheBlockSize = 32;    // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+                                       // which should be a decent compromise on many architectures.
+  double (*temp)[inWidth] = malloc(inHeight*sizeof(*temp));
+  double (*out)[inHeight] = (double (*)[inHeight])data;
+  memcpy(temp, data, inHeight*sizeof(*temp));
+  for ( size_t yBlock = 0; yBlock < inHeight; yBlock++ )
+    {
+      for ( size_t xBlock = 0; xBlock < inWidth; xBlock++ )
         {
-          cdf_inq_dimlen(fileID, dimids[1], &size);
-          if ( size == 1 ) skipdim = 1;
+          for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+            {
+              for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+                {
+                  out[x][y] = temp[y][x];
+                }
+            }
         }
-      else if ( zid == dimids[1] )
+    }
+  free(temp);
+}
+
+static
+void transpose2dArraySP(size_t inWidth, size_t inHeight, float* data)
+{
+  const size_t cacheBlockSize = 32;    // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+                                       // which should be a decent compromise on many architectures.
+  float (*temp)[inWidth] = malloc(inHeight*sizeof(*temp));
+  float (*out)[inHeight] = (float (*)[inHeight])data;
+  memcpy(temp, data, inHeight*sizeof(*temp));
+  for ( size_t yBlock = 0; yBlock < inHeight; yBlock++ )
+    {
+      for ( size_t xBlock = 0; xBlock < inWidth; xBlock++ )
         {
-          cdf_inq_dimlen(fileID, dimids[2], &size);
-          if ( size == 1 ) skipdim = 2;
+          for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+            {
+              for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+                {
+                  out[x][y] = temp[y][x];
+                }
+            }
         }
     }
-  /*
-  printf("2 %p %d %d %s\n", streamptr, zaxisindex, streamptr->zaxisID[zaxisindex], vlistInqVarNamePtr(vlistID, varID));
-  */
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
+  free(temp);
+}
 
-  if ( (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID ) swapxy = TRUE;
-  /*
-  printf("swapxy %d\n", swapxy);
-  printf("ixyz %d\n", ixyz);
-  printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
-  */
+static
+void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
+{
+  int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
+  int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
 
-  if ( tsteptype != TSTEP_CONSTANT )
+  (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
+  switch ( gridInqType(gridId) )
     {
-      start[ndims] = tsID;
-      count[ndims] = 1;
-      ndims++;
+      case GRID_TRAJECTORY:
+        cdfReadGridTraj(streamptr, gridId);
+        break;
+
+      case GRID_UNSTRUCTURED:
+        (*outDimIds)[0] = streamptr->xdimID[gridindex];
+        break;
+
+      default:
+        (*outDimIds)[0] = streamptr->xdimID[gridindex];
+        (*outDimIds)[1] = streamptr->ydimID[gridindex];
+        break;
     }
 
-  if ( skipdim == 1 )
+  int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
+  int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
+  (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
+}
+
+static
+int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
+{
+  if((*dimIds)[0] != UNDEFID) return 0;
+  if((*dimIds)[1] != UNDEFID) return 0;
+  int nvdims;
+  cdf_inq_varndims(fileId, ncvarid, &nvdims);
+  if(nvdims != 3) return 0;
+
+  int varDimIds[3];
+  cdf_inq_vardimid(fileId, ncvarid, varDimIds);
+  size_t size = 0;
+  if ( (*dimIds)[2] == varDimIds[2] )
     {
-      start[ndims] = 0;
-      count[ndims] = 1;
-      ndims++;
+      cdf_inq_dimlen(fileId, varDimIds[1], &size);
+      if ( size == 1 ) return 1;
     }
+  else if ( (*dimIds)[2] == varDimIds[1] )
+    {
+      cdf_inq_dimlen(fileId, varDimIds[2], &size);
+      if ( size == 1 ) return 2;
+    }
+  return 0;
+}
+
+
+static
+void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
+{
+  int tsID = streamptr->curTsID;
+  if ( CDI_Debug ) Message("tsID = %d", tsID);
+
+  int fileId = streamptr->fileID;
+  int vlistId = streamptr->vlistID;
+  int ncvarid = streamptr->vars[varId].ncvarid;
+
+  int gridId = vlistInqVarGrid(vlistId, varId);
+  int tsteptype = vlistInqVarTsteptype(vlistId, varId);
+  int gridsize = gridInqSize(gridId);
+
+  streamptr->numvals += gridsize;
+
+  int dimIds[3];    //this array joins the old variables xid, yid, and zid
+  cdfInqDimIds(streamptr, varId, &dimIds);
+
+  int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
+
+  int dimorder[3];
+  vlistInqVarDimorder(vlistId, varId, &dimorder);
+
+  *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
+
+  int ndims = 0;
+
+#define addDimension(startIndex, extent) do {   \
+      (*start)[ndims] = startIndex; \
+      (*count)[ndims] = extent; \
+      ndims++; \
+  } while(0)
+
+  if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+  if ( skipdim == 1 ) addDimension(0, 1);
 
   for ( int id = 0; id < 3; ++id )
     {
-      if ( dimorder[id] == 3 && zid != UNDEFID )
-        {
-          start[ndims] = levelID;
-          count[ndims] = 1;
-          ndims++;
-        }
-      else if ( dimorder[id] == 2 && yid != UNDEFID )
-        {
-          start[ndims] = 0;
-          cdf_inq_dimlen(fileID, yid, &size);
-          count[ndims] = size;
-          ndims++;
-        }
-      else if ( dimorder[id] == 1 && xid != UNDEFID )
+      size_t size;
+      int curDimId = dimIds[dimorder[id]-1];
+      if ( curDimId == UNDEFID ) continue;
+      switch ( dimorder[id] )
         {
-          start[ndims] = 0;
-          cdf_inq_dimlen(fileID, xid, &size);
-          count[ndims] = size;
-          ndims++;
+          Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+          case 1:
+          case 2:
+            cdf_inq_dimlen(fileId, curDimId, &size);
+            addDimension(0, size);
+            break;
+
+          case 3:
+            addDimension((size_t)levelId, 1);
+            break;
+
+          default:
+            Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
         }
     }
 
-  if ( skipdim == 2 )
-    {
-      start[ndims] = 0;
-      count[ndims] = 1;
-      ndims++;
-    }
+  if ( skipdim == 2 ) addDimension(0, 1);
+
+  assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+  assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+
+#undef addDimension
 
   if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
+    for (int idim = 0; idim < ndims; idim++)
       Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
 
+  int nvdims;
+  cdf_inq_varndims(fileId, ncvarid, &nvdims);
+
   if ( nvdims != ndims )
-    Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistID, varID));
+    Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
+}
+#endif
 
-  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+  size_t start[4];
+  size_t count[4];
+  cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+  cdf_get_vara_double(fileID, ncvarid, start, count, data);
+
+  size_t size = (size_t)gridInqSize(gridID)*zaxisInqSize(zaxisID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      float *data_fp = (float *) data;
-      cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
-      for ( i = gridsize-1; i >=0; i-- )
-        data[i] = (double) data_fp[i];
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeDP(size, data, missval, validrange[0], validrange[1]);
+      else
+        *nmiss = cdfDoInputDataTransformationDP(size, data, haveMissval, missval, 1, 0);
     }
-  else
-    cdf_get_vara_double(fileID, ncvarid, start, count, data);
 
-  if ( swapxy )
+  double addoffset   = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationDP(size, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
+
+
+void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+  size_t start[4];
+  size_t count[4];
+  cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+  cdf_get_vara_float(fileID, ncvarid, start, count, data);
+
+  size_t size = (size_t)gridInqSize(gridID)*zaxisInqSize(zaxisID);
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      double *tdata;
-      tdata = (double *) malloc(gridsize*sizeof(double));
-      memcpy(tdata, data, gridsize*sizeof(double));
-      for ( j = 0; j < ysize; ++j )
-        for ( i = 0; i < xsize; ++i )
-          data[j*xsize+i] = tdata[i*ysize+j];
-      free(tdata);
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeSP(size, data, missval, validrange[0], validrange[1]);
+      else
+        *nmiss = cdfDoInputDataTransformationSP(size, data, haveMissval, missval, 1, 0);
     }
 
-  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+  double addoffset    = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor  = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationSP(size, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
+
+void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  int i;
+  size_t start[4];
+  size_t count[4];
+
+  if ( CDI_Debug )
+    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID = streamptr->fileID;
+
+  bool swapxy;
+  cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+  int gridId = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridId);
+  int xsize = gridInqXsize(gridId);
+  int ysize = gridInqYsize(gridId);
+
+  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+    {
+      float *data_fp = malloc(gridsize*sizeof(*data_fp));
+      cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
+      for ( i = 0; i < gridsize; i++ )
+        data[i] = (double) data_fp[i];
+      free(data_fp);
+    }
+  else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
     {
       nc_type xtype;
       cdf_inq_vartype(fileID, ncvarid, &xtype);
@@ -4136,62 +4332,99 @@ int cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data,
             if ( data[i] < 0 ) data[i] += 256;
         }
     }
+  else
+    {
+      cdf_get_vara_double(fileID, ncvarid, start, count, data);
+    }
+
+  if ( swapxy ) transpose2dArrayDP(xsize, ysize, data);
 
   *nmiss = 0;
-  if ( vlistInqVarMissvalUsed(vlistID, varID) == TRUE )
+  double missval = vlistInqVarMissval(vlistID, varID);
+  const bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
     {
-      missval = vlistInqVarMissval(vlistID, varID);
-
-      lvalidrange = vlistInqVarValidrange(vlistID, varID, validrange);
-      // printf("readvarslice: validrange %d %g %g\n", lvalidrange, validrange[0], validrange[1]);
-      if ( lvalidrange )
-        {
-          *nmiss = set_validrange(gridsize, data, missval, validrange[0], validrange[1]);
-        }
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeDP(gridsize, data, missval, validrange[0], validrange[1]);
       else
-        {
-          double *data_ptr = data;
-          for ( i = 0; i < gridsize; i++, data_ptr++ )
-            if ( DBL_IS_EQUAL((*data_ptr), missval) ) (*nmiss)++;
-        }
+        *nmiss = cdfDoInputDataTransformationDP(gridsize, data, haveMissval, missval, 1, 0);
     }
 
-  addoffset    = vlistInqVarAddoffset(vlistID, varID);
-  scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-  laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-  lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+  double addoffset = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void) cdfDoInputDataTransformationDP(gridsize, data, haveMissval, missval, scalefactor, addoffset);
+#endif
+}
 
-  if ( laddoffset || lscalefactor )
-    {
-      missval = vlistInqVarMissval(vlistID, varID);
 
-      if ( *nmiss > 0 )
+void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
+{
+#if  defined  (HAVE_LIBNETCDF)
+  int i;
+  size_t start[4];
+  size_t count[4];
+
+  if ( CDI_Debug )
+    Message("streamID = %d  varID = %d  levelID = %d", streamptr->self, varID, levelID);
+
+  int vlistID = streamptr->vlistID;
+  int fileID = streamptr->fileID;
+
+  bool swapxy;
+  cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+  int ncvarid = streamptr->vars[varID].ncvarid;
+  int gridId = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridId);
+  int xsize = gridInqXsize(gridId);
+  int ysize = gridInqYsize(gridId);
+
+  if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
+    {
+      double *data_dp = malloc(gridsize*sizeof(*data_dp));
+      cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
+      for ( i = 0; i < gridsize; i++ )
+        data[i] = (float) data_dp[i];
+      free(data_dp);
+    }
+  else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+    {
+      nc_type xtype;
+      cdf_inq_vartype(fileID, ncvarid, &xtype);
+      if ( xtype == NC_BYTE )
         {
           for ( i = 0; i < gridsize; i++ )
-            {
-              if ( !DBL_IS_EQUAL(data[i], missval) )
-                {
-                  if ( lscalefactor ) data[i] *= scalefactor;
-                  if ( laddoffset )   data[i] += addoffset;
-                }
-            }
+            if ( data[i] < 0 ) data[i] += 256;
         }
+    }
+  else
+    {
+      cdf_get_vara_float(fileID, ncvarid, start, count, data);
+    }
+
+  if ( swapxy ) transpose2dArraySP(xsize, ysize, data);
+
+  *nmiss = 0;
+  double missval = vlistInqVarMissval(vlistID, varID);
+  bool haveMissval = vlistInqVarMissvalUsed(vlistID, varID);
+  if ( haveMissval )
+    {
+      double validrange[2];
+      if ( vlistInqVarValidrange(vlistID, varID, validrange) )
+        *nmiss = set_validrangeSP(gridsize, data, missval, validrange[0], validrange[1]);
       else
-        {
-          for ( i = 0; i < gridsize; i++ )
-            {
-              if ( lscalefactor ) data[i] *= scalefactor;
-              if ( laddoffset )   data[i] += addoffset;
-            }
-        }
+        *nmiss = cdfDoInputDataTransformationSP(gridsize, data, haveMissval, missval, 1, 0);
     }
 
+  double addoffset = vlistInqVarAddoffset(vlistID, varID);
+  double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+  (void ) cdfDoInputDataTransformationSP(gridsize, data, haveMissval, missval, scalefactor, addoffset);
 #endif
-  return (0);
 }
 
 
-int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
 #if  defined  (HAVE_LIBNETCDF)
   int fileID;
@@ -4199,7 +4432,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int zaxisID;
   int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
   int ncvarid;
-  int ntsteps;
   long nvals;
   size_t xsize = 0, ysize = 0;
   size_t start[5];
@@ -4209,7 +4441,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int tsteptype;
   int gridindex, zaxisindex;
   int dimorder[3];
-  int ixyz;
   int swapxy = FALSE;
   int dtype;
   int vlistID;
@@ -4220,8 +4451,8 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   vlistID = streamptr->vlistID;
   fileID  = streamptr->fileID;
 
-  ntsteps = streamptr->ntsteps;
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+  long ntsteps = streamptr->ntsteps;
+  if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
 
   if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
 
@@ -4230,8 +4461,8 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   gridID    = vlistInqVarGrid(vlistID, varID);
   zaxisID   = vlistInqVarZaxis(vlistID, varID);
   tsteptype = vlistInqVarTsteptype(vlistID, varID);
-  ixyz      = vlistInqVarXYZ(vlistID, varID);
-  if ( ixyz == 0 ) ixyz = 321; // ZYX
+  vlistInqVarDimorder(vlistID, varID, &dimorder);
+
 
   gridindex = vlistGridIndex(vlistID, gridID);
   if ( gridInqType(gridID) == GRID_TRAJECTORY )
@@ -4247,20 +4478,15 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
   zid = streamptr->zaxisID[zaxisindex];
 
-  dimorder[0] = ixyz/100;
-  dimorder[1] = (ixyz-dimorder[0]*100)/10;
-  dimorder[2] = (ixyz-dimorder[0]*100-dimorder[1]*10);
-
   if ( (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID ) swapxy = TRUE;
   /*
   printf("swapxy %d\n", swapxy);
-  printf("ixyz %d\n", ixyz);
   printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
   */
 
   if ( tsteptype != TSTEP_CONSTANT )
     {
-      start[ndims] = ntsteps - 1;
+      start[ndims] = (size_t)ntsteps - 1;
       count[ndims] = 1;
       ndims++;
     }
@@ -4269,7 +4495,7 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
     {
       if ( dimorder[id] == 3 && zid != UNDEFID )
         {
-          start[ndims] = levelID;
+          start[ndims] = (size_t)levelID;
           count[ndims] = 1;
           ndims++;
         }
@@ -4302,7 +4528,6 @@ int cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
 
 #endif
-  return (0);
 }
 
 #if  defined  (HAVE_LIBNETCDF)
@@ -4328,7 +4553,8 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nrecs;
 
-      if ( nrecs > 0 ) records = (record_t *) malloc(nrecs*sizeof(record_t));
+      if ( nrecs > 0 )
+        records = (record_t *)xmalloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -4336,7 +4562,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
       streamptr->tsteps[tsID].curRecID   = UNDEFID;
 
       nvrecs = nrecs; /* use all records at first timestep */
-      if ( nvrecs > 0 ) recIDs = (int *) malloc(nvrecs*sizeof(int));
+      if ( nvrecs > 0 ) recIDs = (int *)xmalloc((size_t)nvrecs * sizeof (int));
       streamptr->tsteps[tsID].recIDs     = recIDs;
       for ( recID = 0; recID < nvrecs; recID++ )
         recIDs[recID] = recID;
@@ -4349,8 +4575,8 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
           for ( levelID = 0; levelID < nlev; levelID++ )
             {
               recordInitEntry(&records[recID]);
-              records[recID].varID   = varID;
-              records[recID].levelID = levelID;
+              records[recID].varID   = (short)varID;
+              records[recID].levelID = (short)levelID;
               recID++;
             }
         }
@@ -4372,7 +4598,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nvrecs;
 
-      records = (record_t *) malloc(nrecs*sizeof(record_t));
+      records = (record_t *) malloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nvrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -4381,11 +4607,11 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       memcpy(streamptr->tsteps[tsID].records,
              streamptr->tsteps[0].records,
-             nrecs*sizeof(record_t));
+             (size_t)nrecs * sizeof (record_t));
 
       if ( nvrecs )
         {
-          recIDs = (int *) malloc(nvrecs*sizeof(int));
+          recIDs = (int *) malloc((size_t)nvrecs * sizeof (int));
           streamptr->tsteps[tsID].recIDs     = recIDs;
           vrecID = 0;
           for ( recID = 0; recID < nrecs; recID++ )
@@ -4407,7 +4633,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       streamptr->nrecs += nvrecs;
 
-      records = (record_t *) malloc(nrecs*sizeof(record_t));
+      records = (record_t *)xmalloc((size_t)nrecs * sizeof (record_t));
       streamptr->tsteps[tsID].records    = records;
       streamptr->tsteps[tsID].nrecs      = nvrecs;
       streamptr->tsteps[tsID].nallrecs   = nrecs;
@@ -4416,14 +4642,14 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
 
       memcpy(streamptr->tsteps[tsID].records,
              streamptr->tsteps[0].records,
-             nrecs*sizeof(record_t));
+             (size_t)nrecs * sizeof (record_t));
 
-      recIDs = (int *) malloc(nvrecs*sizeof(int));
+      recIDs = (int *) malloc((size_t)nvrecs * sizeof(int));
       streamptr->tsteps[tsID].recIDs     = recIDs;
 
       memcpy(streamptr->tsteps[tsID].recIDs,
              streamptr->tsteps[1].recIDs,
-             nvrecs*sizeof(int));
+             (size_t)nvrecs * sizeof (int));
     }
 }
 #endif
@@ -4697,14 +4923,14 @@ int unitsIsPressure(const char *units)
 }
 
 static
-int isGaussGrid(long ysize, double yinc, double *yvals)
+int isGaussGrid(size_t ysize, double yinc, double *yvals)
 {
   int lgauss = FALSE;
-  long i;
   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);
@@ -4773,7 +4999,7 @@ void printNCvars(ncvar_t *ncvars, int nvars, const char *oname)
   char axis[7];
   int ncvarid, i;
   int ndim;
-  int iaxis[] = {'t', 'z', 'y', 'x'};
+  static const char iaxis[] = {'t', 'z', 'y', 'x'};
 
   fprintf(stderr, "%s:\n", oname);
 
@@ -4882,7 +5108,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               if ( storage_in == NC_CHUNKED )
                 {
                   ncvars[ncvarid].chunked = 1;
-                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = chunks[i];
+                  for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
                   if ( CDI_Debug )
                     {
                       fprintf(stderr, "\nchunking %d %d %d\nchunks ", storage_in, NC_CONTIGUOUS, NC_CHUNKED);
@@ -4928,15 +5154,15 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
           cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
           cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
 
-          if ( strcmp(attname, "long_name") == 0 && atttype == NC_CHAR )
+          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 && atttype == NC_CHAR )
+          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 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
             }
@@ -4944,7 +5170,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
             {
               ncvars[ncvarid].calendar = TRUE;
             }
-          else if ( strcmp(attname, "param") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
             {
 	      char paramstr[32];
 	      int pnum = 0, pcat = 255, pdis = 255;
@@ -4953,12 +5179,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "code") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
             {
               cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
               if ( tablenum > 0 )
@@ -4970,13 +5196,13 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 }
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "trunc_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               if ( memcmp(attstring, "Triangular", attlen) == 0 )
                 ncvars[ncvarid].gridtype = GRID_SPECTRAL;
             }
-          else if ( strcmp(attname, "grid_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -5019,7 +5245,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "level_type") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -5058,19 +5284,19 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "trunc_count") == 0 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
             {
               cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
             }
-          else if ( strcmp(attname, "truncation") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
 	      /*
@@ -5080,7 +5306,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      */
 	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "scale_factor") == 0 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
 	      /*
@@ -5090,7 +5316,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	      */
 	      /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "climatology") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
             {
               int status, ncboundsid;
 
@@ -5108,7 +5334,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
             }
-          else if ( strcmp(attname, "bounds") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "bounds") == 0 && xtypeIsText(atttype) )
             {
               int status, ncboundsid;
 
@@ -5125,7 +5351,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
             }
-          else if ( strcmp(attname, "cell_measures") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
             {
               char *pstring, *cell_measures = NULL, *cell_var = NULL;
 
@@ -5190,7 +5416,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
           */
-          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && atttype == NC_CHAR )
+          else if ( (strcmp(attname, "associate")  == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
             {
               int status;
               char *pstring, *varname = NULL;
@@ -5228,7 +5454,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( (strcmp(attname, "auxiliary_variable") == 0) && atttype == NC_CHAR )
+          else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
             {
               int status;
               char *pstring, *varname = NULL;
@@ -5266,7 +5492,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "grid_mapping") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
             {
               int status;
               int nc_gmap_id;
@@ -5284,7 +5510,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 
               cdfSetVar(ncvars, ncvarid, TRUE);
             }
-          else if ( strcmp(attname, "positive") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -5299,13 +5525,13 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                   ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
                 }
             }
-          else if ( strcmp(attname, "_FillValue") == 0 && atttype != NC_CHAR )
+          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 && atttype != NC_CHAR )
+          else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
             {
 	      cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
 	      ncvars[ncvarid].defmissval = TRUE;
@@ -5368,7 +5594,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                     }
                 }
             }
-          else if ( strcmp(attname, "_Unsigned") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
               strtolower(attstring);
@@ -5384,7 +5610,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
                 }
 	      /* cdfSetVar(ncvars, ncvarid, TRUE); */
             }
-          else if ( strcmp(attname, "cdi") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
             {
 	      cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 	      strtolower(attstring);
@@ -5395,7 +5621,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 		  cdfSetVar(ncvars, ncvarid, FALSE);
 		}
             }
-          else if ( strcmp(attname, "axis") == 0 && atttype == NC_CHAR )
+          else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
             {
               cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 	      attlen = strlen(attstring);
@@ -5425,12 +5651,12 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  if ( (int) attstring[attlen] == 't' )
 			    {
 			      if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
-			      cdfSetDim(ncvars, ncvarid, attlen, T_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS);
 			    }
 			  else if ( (int) attstring[attlen] == 'z' )
 			    {
 			      ncvars[ncvarid].zdim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, Z_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -5441,7 +5667,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  else if ( (int) attstring[attlen] == 'y' )
 			    {
 			      ncvars[ncvarid].ydim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, Y_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -5452,7 +5678,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 			  else if ( (int) attstring[attlen] == 'x' )
 			    {
 			      ncvars[ncvarid].xdim = dimidsp[attlen];
-			      cdfSetDim(ncvars, ncvarid, attlen, X_AXIS);
+			      cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS);
 
 			      if ( ncvars[ncvarid].ndims == 1 )
 				{
@@ -5487,7 +5713,8 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
 	  else
 	    {
 	      if ( ncvars[ncvarid].natts == 0 )
-		ncvars[ncvarid].atts = (int *) malloc(nvatts*sizeof(int));
+		ncvars[ncvarid].atts
+                  = (int *)xmalloc((size_t)nvatts * sizeof (int));
 
 	      ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
 	      /*
@@ -5946,7 +6173,27 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		    }
 		}
 
-	      if ( xvarid != 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 )
 		{
                   skipvar = TRUE;
 		  islon = ncvars[xvarid].islon;
@@ -6143,10 +6390,10 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	    case GRID_UNSTRUCTURED:
 	    case GRID_CURVILINEAR:
 	      {
-		grid.size  = size;
-		grid.xsize = xsize;
-		grid.ysize = ysize;
-                grid.np    = np;
+		grid.size  = (int)size;
+		grid.xsize = (int)xsize;
+		grid.ysize = (int)ysize;
+                grid.np    = (int)np;
 		if ( xvarid != UNDEFID )
 		  {
 		    grid.xdef  = 1;
@@ -6192,13 +6439,13 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	      }
 	    case GRID_SPECTRAL:
 	      {
-		grid.size = size;
+		grid.size = (int)size;
 		grid.lcomplex = 1;
 		break;
 	      }
 	    case GRID_FOURIER:
 	      {
-		grid.size = size;
+		grid.size = (int)size;
 		break;
 	      }
 	    case GRID_TRAJECTORY:
@@ -6213,8 +6460,8 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	  if ( grid.size == 0 )
 	    {
 	      if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
-		   (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS &&
-		    ncvars[ncvarid].dimtype[1] == Z_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;
@@ -6500,7 +6747,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 /* 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, double *vct)
+		      size_t vctsize, double *vct, char *uuidOfVGrid)
 {
   int ncvarid, ncvarid2;
   int i, ilev, ndims;
@@ -6535,12 +6782,12 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 	  if ( zdimid != UNDEFID )
 	    {
 	      zvarid = ncdims[zdimid].ncvarid;
-	      zsize  = ncdims[zdimid].len;
+	      zsize  = (int)ncdims[zdimid].len;
 	    }
 
 	  if ( CDI_Debug ) Message("nlevs = %d", zsize);
 
-	  zvar = (double *) malloc(zsize*sizeof(double));
+	  zvar = (double *)xmalloc((size_t)zsize * sizeof (double));
 
 	  zaxisType = UNDEFID;
 
@@ -6570,15 +6817,15 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		  nbdims = ncvars[ncvars[zvarid].bounds].ndims;
 		  if ( nbdims == 2 )
 		    {
-		      nlevel  = ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
-		      nvertex = ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
+		      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 )
 			{
 			  double *zbounds;
 			  with_bounds = TRUE;
-			  zbounds = (double *) malloc(2*nlevel*sizeof(double));
-			  lbounds = (double *) malloc(nlevel*sizeof(double));
-			  ubounds = (double *) malloc(nlevel*sizeof(double));
+			  zbounds = (double *) malloc(2*(size_t)nlevel*sizeof(double));
+			  lbounds = (double *) malloc((size_t)nlevel*sizeof(double));
+			  ubounds = (double *) malloc((size_t)nlevel*sizeof(double));
 			  cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
 			  for ( i = 0; i < nlevel; ++i )
 			    {
@@ -6613,12 +6860,18 @@ void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
 		}
 	      else
 		{
-		  for ( ilev = 0; ilev < (int)zsize; ilev++ ) zvar[ilev] = ilev + 1;
+		  for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
 		}
 	    }
 
       	  ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds,
-						vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+						(int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+
+	  if ( uuidOfVGrid[0] != 0 )
+            {
+              // printf("uuidOfVGrid: defined\n");
+              zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid);
+            }
 
           if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
 
@@ -6667,8 +6920,8 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
     {
       int index;
       varinfo_t **varInfo;
-      varInfo    = (varinfo_t **) malloc(nvars*sizeof(varinfo_t *));
-      varInfo[0] = (varinfo_t *)  malloc(nvars*sizeof(varinfo_t));
+      varInfo    = (varinfo_t **)xmalloc((size_t)nvars * sizeof (varinfo_t *));
+      varInfo[0] = (varinfo_t *)xmalloc((size_t)nvars * sizeof (varinfo_t));
 
       for ( index = 1; index < nvars; index++ )
 	varInfo[index] = varInfo[0] + index;
@@ -6679,7 +6932,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 	  varInfo[varID]->ncvarid = ncvarid;
 	  strcpy(varInfo[varID]->name, ncvars[ncvarid].name);
 	}
-      qsort(varInfo[0], nvars, sizeof(varinfo_t), cmpvarname);
+      qsort(varInfo[0], (size_t)nvars, sizeof(varinfo_t), cmpvarname);
       for ( varID = 0; varID < nvars; varID++ )
 	{
 	  varids[varID] = varInfo[varID]->ncvarid;
@@ -6806,7 +7059,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
           ncvars[ncvarid].ensdata = NULL;
         }
 
-      if ( ncvars[ncvarid].extra != NULL && ncvars[ncvarid].extra[0] != 0 )
+      if ( ncvars[ncvarid].extra[0] != 0 )
         {
           vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
         }
@@ -6834,11 +7087,12 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 	      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;
 		  attint = (int *) malloc(attlen*sizeof(int));
-		  cdfGetAttInt(ncid, ncvarid, attname, attlen, attint);
+		  cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
 		  if ( attrtype == NC_SHORT )
 		    vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint);
 		  else
@@ -6851,7 +7105,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 		{
 		  double *attflt;
 		  attflt = (double *) malloc(attlen*sizeof(double));
-		  cdfGetAttDouble(ncid, ncvarid, attname, attlen, attflt);
+		  cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
 		  if ( attrtype == NC_FLOAT )
 		    vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt);
 		  else
@@ -6860,7 +7114,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 		    printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attflt[0]);
 		  free(attflt);
 		}
-	      else if ( attrtype == NC_CHAR )
+	      else if ( xtypeIsText(attrtype) )
 		{
 		  cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
 		  vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring);
@@ -6959,7 +7213,7 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
 
 static
 void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts,
-                            int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid,
+                            int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid, char *uuidOfVGrid,
                             char *gridfile, int *number_of_grid_used, char *fcreftime)
 {
   nc_type xtype;
@@ -6974,7 +7228,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
       cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
       cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
 
-      if ( xtype == NC_CHAR )
+      if ( xtypeIsText(xtype) )
 	{
 	  cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen-1, attstring);
 
@@ -7030,6 +7284,11 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
                   str2uuid(attstring, uuidOfHGrid);
                   //   printf("uuid: %d %s\n", attlen, attstring);
 		}
+	      else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
+		{
+                  attstring[36] = 0;
+                  str2uuid(attstring, uuidOfVGrid);
+		}
 	      else
 		{
                   if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
@@ -7052,7 +7311,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
             {
               int *attint;
               attint = (int *) malloc(attlen*sizeof(int));
-              cdfGetAttInt(fileID, NC_GLOBAL, attname, attlen, attint);
+              cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
               if ( xtype == NC_SHORT )
                 vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint);
               else
@@ -7064,7 +7323,7 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
 	{
 	  double *attflt;
 	  attflt = (double *) malloc(attlen*sizeof(double));
-	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, attlen, attflt);
+	  cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
 	  if ( xtype == NC_FLOAT )
 	    vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt);
 	  else
@@ -7137,7 +7396,7 @@ void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid,
         if ( ncvarid != streamptr->basetime.ncvarid &&
              ncvars[ncvarid].ndims == 1 &&
              timedimid == ncvars[ncvarid].dimids[0] &&
-             ncvars[ncvarid].xtype != NC_CHAR &&
+             !xtypeIsText(ncvars[ncvarid].xtype) &&
              isTimeAxisUnits(ncvars[ncvarid].units) )
           {
             ncvars[ncvarid].isvar = FALSE;
@@ -7161,7 +7420,7 @@ void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid,
             if ( ncvarid != streamptr->basetime.ncvarid &&
                  ncvars[ncvarid].ndims == 2 &&
                  timedimid == ncvars[ncvarid].dimids[0] &&
-                 ncvars[ncvarid].xtype == NC_CHAR &&
+                 !xtypeIsText(ncvars[ncvarid].xtype) &&
                  ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
               {
                 streamptr->basetime.ncvarid = ncvarid;
@@ -7235,11 +7494,13 @@ int cdfInqContents(stream_t *streamptr)
   int format = 0;
   int ucla_les = FALSE;
   char uuidOfHGrid[17];
+  char uuidOfVGrid[17];
   char gridfile[8912];
   char fcreftime[CDI_MAX_NAME];
   int number_of_grid_used = UNDEFID;
 
   uuidOfHGrid[0] = 0;
+  uuidOfVGrid[0] = 0;
   gridfile[0]    = 0;
   fcreftime[0]   = 0;
 
@@ -7264,13 +7525,13 @@ int cdfInqContents(stream_t *streamptr)
     }
 
   /* alloc ncdims */
-  ncdims = (ncdim_t *) malloc(ndims*sizeof(ncdim_t));
+  ncdims = (ncdim_t *)xmalloc((size_t)ndims * sizeof (ncdim_t));
   init_ncdims(ndims, ncdims);
 
   if ( nvars > 0 )
     {
       /* alloc ncvars */
-      ncvars = (ncvar_t *) malloc(nvars*sizeof(ncvar_t));
+      ncvars = (ncvar_t *)xmalloc((size_t)nvars * sizeof (ncvar_t));
       init_ncvars(nvars, ncvars);
 
       for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
@@ -7311,7 +7572,8 @@ int cdfInqContents(stream_t *streamptr)
     }
 
   /* scan global attributes */
-  scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, uuidOfHGrid, gridfile, &number_of_grid_used, fcreftime);
+  scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, 
+                         uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used, fcreftime);
 
   /* find time dim */
   if ( unlimdimid >= 0 )
@@ -7418,7 +7680,7 @@ int cdfInqContents(stream_t *streamptr)
 	  continue;
 	}
 
-      if ( ncvars[ncvarid].xtype == NC_CHAR )
+      if ( xtypeIsText(ncvars[ncvarid].xtype) )
 	{
 	  ncvars[ncvarid].isvar = 0;
 	  continue;
@@ -7558,13 +7820,13 @@ int cdfInqContents(stream_t *streamptr)
 
 
   /* define all zaxes */
-  define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct);
+  define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
 
 
   if ( vct ) free(vct);
 
   /* select vars */
-  varids = (int *) malloc(nvars*sizeof(int));
+  varids = (int *)xmalloc((size_t)nvars * sizeof (int));
   nvarids = 0;
   for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
     if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
@@ -7585,7 +7847,7 @@ int cdfInqContents(stream_t *streamptr)
   if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
     ntsteps = 1;
 
-  streamptr->ntsteps = ntsteps;
+  streamptr->ntsteps = (long)ntsteps;
 
   /* define all data variables */
   define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
@@ -7629,10 +7891,9 @@ int cdfInqContents(stream_t *streamptr)
   if ( ncvarid != UNDEFID )
     {
       taxis_t *taxis = &streamptr->tsteps[0].taxis;
-
-      taxis->name = strdup(ncvars[ncvarid].name);
+      ptaxisDefName(taxis, ncvars[ncvarid].name);
       if ( ncvars[ncvarid].longname[0] )
-        taxis->longname = strdup(ncvars[ncvarid].longname);
+        ptaxisDefLongname(taxis, ncvars[ncvarid].longname);
     }
 
   if ( ncvarid != UNDEFID )
@@ -7711,6 +7972,63 @@ int cdfInqContents(stream_t *streamptr)
   return (0);
 }
 
+#if  defined  (HAVE_LIBNETCDF)
+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;
+}
+#endif
 
 int cdfInqTimestep(stream_t * streamptr, int tsID)
 {
@@ -7718,7 +8036,6 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
 #if  defined  (HAVE_LIBNETCDF)
   double timevalue;
   int fileID;
-  size_t index;
   taxis_t *taxis;
 
   if ( CDI_Debug ) Message("streamID = %d  tsID = %d", streamptr->self, tsID);
@@ -7739,31 +8056,23 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
       if ( nctimevarid != UNDEFID )
 	{
 	  fileID = streamptr->fileID;
-	  index  = tsID;
+	  size_t index  = (size_t)tsID;
 
 	  if ( streamptr->basetime.lwrf )
 	    {
-	      size_t start[2], count[2];
-	      char stvalue[32];
-	      start[0] = index; 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;
-	      }
+              wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
 	    }
 	  else
 	    {
-	      cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
-              if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
-
+#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);
 	    }
 
@@ -7771,13 +8080,13 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
 	  if ( nctimeboundsid != UNDEFID )
 	    {
 	      size_t start[2], count[2];
-	      start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
+              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;
+              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;
 
@@ -7787,7 +8096,7 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
           int leadtimeid = streamptr->basetime.leadtimeid;
           if ( leadtimeid != UNDEFID )
             {
-	      cdf_get_var1_double(fileID, leadtimeid, &index, &timevalue);
+              timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
               cdiSetForecastPeriod(timevalue, taxis);
             }
 	}
diff --git a/libcdi/src/stream_cdf.h b/libcdi/src/stream_cdf.h
index 166aecd..08b71fb 100644
--- a/libcdi/src/stream_cdf.h
+++ b/libcdi/src/stream_cdf.h
@@ -10,18 +10,21 @@ int    cdfInqHistorySize(stream_t *streamptr);
 void   cdfInqHistoryString(stream_t *streamptr, char *history);
 
 void   cdfEndDef(stream_t * streamptr);
-int    cdfDefRecord(stream_t * streamptr);
+void   cdfDefRecord(stream_t * streamptr);
 
-int    cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
 
-int    cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
 void   cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
 
 void   cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss);
+void   cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss);
+
 void   cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
 
-int    cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
-int    cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
+void   cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
+void   cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss);
+void   cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
 
 void   cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
                            const int rect[][2], const void *data, int nmiss);
diff --git a/libcdi/src/stream_cgribex.c b/libcdi/src/stream_cgribex.c
index 16b1c29..f17295a 100644
--- a/libcdi/src/stream_cgribex.c
+++ b/libcdi/src/stream_cgribex.c
@@ -25,6 +25,7 @@ typedef struct {
   int level1;
   int level2;
   int ltype;
+  int tsteptype;
 } compvar_t;
 
 
@@ -61,7 +62,7 @@ int cgribexGetIsRotated(int *isec2)
     {
       isRotated = 1;
     }
- 
+
   return (isRotated);
 }
 
@@ -92,13 +93,14 @@ int cgribexGetTimeUnit(int *isec1)
 
   switch ( ISEC1_TimeUnit )
     {
-    case ISEC1_TABLE4_MINUTE:  timeunit = TUNIT_MINUTE;  break;
-    case ISEC1_TABLE4_QUARTER: timeunit = TUNIT_QUARTER; break;
-    case ISEC1_TABLE4_HOUR:    timeunit = TUNIT_HOUR;    break;
-    case ISEC1_TABLE4_3HOURS:  timeunit = TUNIT_3HOURS;  break;
-    case ISEC1_TABLE4_6HOURS:  timeunit = TUNIT_6HOURS;  break;
-    case ISEC1_TABLE4_12HOURS: timeunit = TUNIT_12HOURS; break;
-    case ISEC1_TABLE4_DAY:     timeunit = TUNIT_DAY;     break;
+    case ISEC1_TABLE4_MINUTE:    timeunit = TUNIT_MINUTE;    break;
+    case ISEC1_TABLE4_QUARTER:   timeunit = TUNIT_QUARTER;   break;
+    case ISEC1_TABLE4_30MINUTES: timeunit = TUNIT_30MINUTES; break;
+    case ISEC1_TABLE4_HOUR:      timeunit = TUNIT_HOUR;      break;
+    case ISEC1_TABLE4_3HOURS:    timeunit = TUNIT_3HOURS;    break;
+    case ISEC1_TABLE4_6HOURS:    timeunit = TUNIT_6HOURS;    break;
+    case ISEC1_TABLE4_12HOURS:   timeunit = TUNIT_12HOURS;   break;
+    case ISEC1_TABLE4_DAY:       timeunit = TUNIT_DAY;       break;
     default:
       if ( lprint )
 	{
@@ -140,7 +142,7 @@ int cgribexGetTsteptype(int timerange)
     default:
       if ( lprint )
 	{
-	  Message("GRIB time range %d unsupported!", timerange);
+	  Message("Time range indicator %d unsupported, set to 0!", timerange);
 	  lprint = FALSE;
 	}
       break;
@@ -152,9 +154,8 @@ int cgribexGetTsteptype(int timerange)
 static
 void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, int iret)
 {
-  int gridtype;
-
-  gridtype = cgribexGetGridType(isec2);
+  int compyinc = TRUE;
+  int gridtype = cgribexGetGridType(isec2);
 
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
     {
@@ -164,6 +165,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
       gridtype = GRID_GAUSSIAN;
       ISEC2_NumLon = nlon;
       ISEC4_NumValues = nlon*ISEC2_NumLat;
+      compyinc = FALSE;
     }
 
   memset(grid, 0, sizeof(grid_t));
@@ -220,10 +222,9 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
 	grid->ydef  = 0;
 	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
 	  {
-	    if ( grid->ysize > 1 )
+	    if ( grid->ysize > 1 && compyinc )
 	      {
                 int recompinc = TRUE;
-
 		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
                   {
                     if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
@@ -359,62 +360,55 @@ static
 void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, double *fsec2, double *fsec3,
 		      int *isec4, long recsize, off_t position, int datatype, int comptype, int lmv, int iret)
 {
-  int zaxistype;
-  int gridID = CDI_UNDEFID, varID;
+  int varID;
   int levelID = 0;
-  int tsID, recID;
-  int level1, level2;
-  int numavg;
-  int tsteptype;
-  int lbounds = 0;
-  record_t *record;
   grid_t grid;
-  int vlistID;
 
-  vlistID = streamptr->vlistID;
-  tsID    = streamptr->curTsID;
-  recID   = recordNewEntry(streamptr, tsID);
-  record  = &streamptr->tsteps[tsID].records[recID];
+  int vlistID = streamptr->vlistID;
+  int tsID    = streamptr->curTsID;
+  int recID   = recordNewEntry(streamptr, tsID);
+  record_t *record  = &streamptr->tsteps[tsID].records[recID];
 
-  tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
-  numavg    = ISEC1_AvgNum;
+  int tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
+  int numavg    = ISEC1_AvgNum;
 
-  level1  = ISEC1_Level1;
-  level2  = ISEC1_Level2;
+  int level1  = ISEC1_Level1;
+  int level2  = ISEC1_Level2;
 
   /* fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, ISEC1_LevelType); */
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = ISEC1_LevelType;
+  record->size      = (size_t)recsize;
+  record->position  = position;
+  record->param     = param;
+  record->ilevel    = level1;
+  record->ilevel2   = level2;
+  record->ltype     = ISEC1_LevelType;
+  record->tsteptype = tsteptype;
 
   cgribexGetGrid(streamptr, isec2, isec4, &grid, iret);
 
-  gridID = varDefGrid(vlistID, grid, 0);
+  int gridID = varDefGrid(vlistID, grid, 0);
 
-  zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
+  int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
 
   if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
     {
-      int vctsize = ISEC2_NumVCP;
+      size_t vctsize = (size_t)ISEC2_NumVCP;
       double *vctptr = &fsec2[10];
 
       varDefVCT(vctsize, vctptr);
     }
 
-  lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
+  int lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
 
   if ( datatype > 32 ) datatype = DATATYPE_PACK32;
   if ( datatype <  0 ) datatype = DATATYPE_PACK;
 
   varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, 0, 0,
-	       datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   varDefCompType(varID, comptype);
 
@@ -513,30 +507,38 @@ void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
 }
 
 static
-compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype)
+compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int trange)
 {
   compvar_t compVar;
+  int tsteptype = cgribexGetTsteptype(trange);
 
-  compVar.param  = param;
-  compVar.level1 = level1;
-  compVar.level2 = level2;
-  compVar.ltype  = leveltype;
+  compVar.param     = param;
+  compVar.level1    = level1;
+  compVar.level2    = level2;
+  compVar.ltype     = leveltype;
+  compVar.tsteptype = tsteptype;
 
   return (compVar);
 }
 
 static
-int cgribexVarCompare(compvar_t compVar, record_t record)
+int cgribexVarCompare(compvar_t compVar, record_t record, int flag)
 {
-  int rstatus;
   compvar_t compVar0;
 
-  compVar0.param  = record.param;
-  compVar0.level1 = record.ilevel;
-  compVar0.level2 = record.ilevel2;
-  compVar0.ltype  = record.ltype;
+  compVar0.param     = record.param;
+  compVar0.level1    = record.ilevel;
+  compVar0.level2    = record.ilevel2;
+  compVar0.ltype     = record.ltype;
+  compVar0.tsteptype = record.tsteptype;
 
-  rstatus = memcmp(&compVar0, &compVar, sizeof(compvar_t));
+  if ( flag == 0 )
+    {
+      if ( compVar0.tsteptype == TSTEP_INSTANT  && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
+      if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT  ) compVar0.tsteptype = TSTEP_INSTANT;
+    }
+
+  int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar_t));
 
   return (rstatus);
 }
@@ -553,7 +555,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
   int lmv = 0, iret = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int rstatus;
   int fileID;
   int param = 0;
@@ -619,13 +621,13 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      if ( recsize > buffersize )
+      if ( (size_t)recsize > buffersize )
 	{
-	  buffersize = recsize;
+	  buffersize = (size_t)recsize;
 	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
-      readsize = recsize;
+      readsize = (size_t)recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
@@ -634,16 +636,16 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	{
 	  comptype = COMPRESS_SZIP;
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
 
       nrecs_scanned++;
       cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			  (int *) gribbuffer, recsize, &lmv, &iret);
+			  (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
       param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -674,11 +676,11 @@ int cgribexScanTimestep1(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
 	  for ( recID = 0; recID < nrecs; recID++ )
 	    {
-	      if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID]) == 0 ) break;
+	      if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
 	    }
 
 	  if ( cdiInventoryMode == 1 )
@@ -746,8 +748,8 @@ int cgribexScanTimestep1(stream_t * streamptr)
       taxis->unit  = tunit;
     }
 
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -766,7 +768,7 @@ int cgribexScanTimestep1(stream_t * streamptr)
     streamptr->tsteps[0].recIDs[recID] = recID;
 
   streamptr->record->buffer     = gribbuffer;
-  streamptr->record->buffersize = buffersize;
+  streamptr->record->buffersize = (size_t)buffersize;
 
   if ( streamptr->ntsteps == -1 )
     {
@@ -806,7 +808,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
   int lmv = 0, iret = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int param = 0;
   int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -877,28 +879,28 @@ int cgribexScanTimestep2(stream_t * streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      if ( recsize > buffersize )
+      if ( (size_t)recsize > buffersize )
 	{
-	  buffersize = recsize;
-	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
+	  buffersize = (size_t)recsize;
+	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
-      readsize = recsize;
+      readsize = (size_t)recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
       if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
 
       cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			  (int *) gribbuffer, recsize, &lmv, &iret);
+			  (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
       nrecs_scanned++;
 
@@ -953,11 +955,11 @@ int cgribexScanTimestep2(stream_t * streamptr)
       datetime.date  = vdate;
       datetime.time  = vtime;
 
-      compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+      compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
       for ( recID = 0; recID < nrecords; recID++ )
 	{
-	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	}
 
       if ( recID == nrecords )
@@ -997,9 +999,9 @@ int cgribexScanTimestep2(stream_t * streamptr)
       if ( CDI_Debug )
 	Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
 
-      streamptr->tsteps[tsID].records[recID].size = recsize;
+      streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
 
-      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
@@ -1063,31 +1065,26 @@ int cgribexScanTimestep(stream_t * streamptr)
 {
   int rstatus = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
-  int *isec0, *isec1, *isec2, *isec3, *isec4;
   double fsec2[512], fsec3[2], *fsec4 = NULL;
   int lmv = 0, iret = 0;
   long recsize = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int param = 0;
   int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
   DateTime datetime, datetime0;
-  int tsID;
   int vrecID, recID;
   int warn_numavg = TRUE;
   size_t readsize;
   int taxisID = -1;
-  taxis_t *taxis;
-  int vlistID;
   int rindex, nrecs = 0;
   int nrecs_scanned;
   long unzipsize;
   compvar_t compVar;
   char paramstr[32];
 
-  vlistID = streamptr->vlistID;
   /*
   if ( CDI_Debug )
     {
@@ -1097,14 +1094,14 @@ int cgribexScanTimestep(stream_t * streamptr)
       Message("nts = %d", streamptr->ntsteps);
     }
   */
-  isec0 = streamptr->record->sec0;
-  isec1 = streamptr->record->sec1;
-  isec2 = streamptr->record->sec2;
-  isec3 = streamptr->record->sec3;
-  isec4 = streamptr->record->sec4;
+  int *isec0 = streamptr->record->sec0;
+  int *isec1 = streamptr->record->sec1;
+  int *isec2 = streamptr->record->sec2;
+  int *isec3 = streamptr->record->sec3;
+  int *isec4 = streamptr->record->sec4;
 
-  tsID  = streamptr->rtsteps;
-  taxis = &streamptr->tsteps[tsID].taxis;
+  int tsID  = streamptr->rtsteps;
+  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -1116,7 +1113,7 @@ int cgribexScanTimestep(stream_t * streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -1137,15 +1134,15 @@ int cgribexScanTimestep(stream_t * streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  if ( recsize > buffersize )
+	  if ( recsize > 0 && (size_t)recsize > buffersize )
 	    {
-	      buffersize = recsize;
+	      buffersize = (size_t)recsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 
 	  if ( rindex >= nrecs ) break;
 
-	  readsize = recsize;
+	  readsize = (size_t)recsize;
 	  rstatus = gribRead(fileID, gribbuffer, &readsize);
 	  if ( rstatus )
 	    {
@@ -1157,15 +1154,15 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
 	    {
 	      unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	      if ( (long) buffersize < unzipsize )
+	      if ( buffersize < (size_t)unzipsize )
 		{
-		  buffersize = unzipsize;
+		  buffersize = (size_t)unzipsize;
 		  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 		}
 	    }
 
 	  cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
-			      (int *) gribbuffer, recsize, &lmv, &iret);
+			      (int *) gribbuffer, (int)recsize, &lmv, &iret);
 
           nrecs_scanned++;
 
@@ -1183,6 +1180,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 
 	  if ( rindex == 0 )
 	    {
+              int vlistID = streamptr->vlistID;
 	      taxisID = vlistInqTaxis(vlistID);
 	      if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
 		{
@@ -1221,12 +1219,12 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType);
+	  compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
 
 	  for ( vrecID = 0; vrecID < nrecs; vrecID++ )
 	    {
 	      recID   = streamptr->tsteps[1].recIDs[vrecID];
-	      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	      if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	    }
 
 	  if ( vrecID == nrecs )
@@ -1268,7 +1266,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	  if ( CDI_Debug )
             Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
 
-	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+	  if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	    {
 	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		      tsID, recID,
@@ -1278,7 +1276,7 @@ int cgribexScanTimestep(stream_t * streamptr)
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
-	  streamptr->tsteps[tsID].records[recID].size = recsize;
+	  streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
 
 	  rindex++;
 	}
@@ -1322,7 +1320,7 @@ int cgribexScanTimestep(stream_t * streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  rstatus = streamptr->ntsteps;
+  rstatus = (int)streamptr->ntsteps;
 #endif
 
   return (rstatus);
@@ -1333,62 +1331,20 @@ int cgribexScanTimestep(stream_t * streamptr)
 #endif
 
 int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval)
+		  int unreduced, int *nmiss, double missval)
 {
   int status = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
   int iret = 0, iword = 0;
   int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
-  int izip;
-  long unzipsize;
   double fsec2[512], fsec3[2];
   char hoper[2];
 
-  *zip = 0;
-
   if ( unreduced ) strcpy(hoper, "R");
   else             strcpy(hoper, "D");
 
   FSEC3_MissVal = missval;
 
-  if ( (izip = gribGetZip(gribsize, gribbuffer, &unzipsize)) > 0 )
-    {
-      *zip = izip;
-      if ( izip == 128 ) /* szip */
-	{
-	  unsigned char *itmpbuffer = NULL;
-	  size_t itmpbuffersize = 0;
-
-	  if ( unzipsize < (long) gribsize )
-	    {
-	      fprintf(stderr, "Decompressed size smaller than compressed size (in %d; out %ld)!\n",
-		      gribsize, unzipsize);
-	      return (status);
-	    }
-
-	  if ( itmpbuffersize < (size_t) gribsize )
-	    {
-	      itmpbuffersize = gribsize;
-	      itmpbuffer = (unsigned char *) realloc(itmpbuffer, itmpbuffersize);
-	    }
-
-	  memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
-
-	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-
-	  gribsize = gribUnzip(gribbuffer, unzipsize, itmpbuffer, gribsize);
-
-	  if ( gribsize <= 0 )
-	    Error("Decompression problem!");
-
-	  free(itmpbuffer);
-	}
-      else
-	{
-	  Error("Decompression for %d not implemented!", izip);
-	}
-    }
-
   gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, data,
 	   gridsize, (int *) gribbuffer, gribsize, &iword, hoper, &iret);
 
@@ -1568,14 +1524,15 @@ int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
 
   switch (timeunit)
     {
-    case TUNIT_MINUTE:  factor =    60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE;  break;
-    case TUNIT_QUARTER: factor =   900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER; break;
-    case TUNIT_HOUR:    factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;    break;
-    case TUNIT_3HOURS:  factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS;  break;
-    case TUNIT_6HOURS:  factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS;  break;
-    case TUNIT_12HOURS: factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS; break;
-    case TUNIT_DAY:     factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY;     break;
-    default:            factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;    break;
+    case TUNIT_MINUTE:    factor =    60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE;    break;
+    case TUNIT_QUARTER:   factor =   900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER;   break;
+    case TUNIT_30MINUTES: factor =  1800; ISEC1_TimeUnit = ISEC1_TABLE4_30MINUTES; break;
+    case TUNIT_HOUR:      factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;      break;
+    case TUNIT_3HOURS:    factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS;    break;
+    case TUNIT_6HOURS:    factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS;    break;
+    case TUNIT_12HOURS:   factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS;   break;
+    case TUNIT_DAY:       factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY;       break;
+    default:              factor =  3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR;      break;
     }
 
   return (factor);
@@ -1588,7 +1545,7 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
   int timerange = 0;
   int timeunit = TUNIT_HOUR;
 
-  if ( taxisID != -1 ) 
+  if ( taxisID != -1 )
     {
       timetype = taxisInqType(taxisID);
       timeunit = taxisInqTunit(taxisID);
@@ -2170,6 +2127,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 static
 void cgribexDefMask(int *isec3)
 {
+  UNUSED(isec3);
 }
 
 static
@@ -2224,23 +2182,25 @@ void cgribexDefEnsembleVar(int *isec1, int vlistID, int varID)
 #endif
 
 
-size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg,
 		     long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize)
 {
   size_t nbytes = 0;
 #if  defined  (HAVE_LIBCGRIBEX)
-  long gribsize;
+  int gribsize;
   int iret = 0, iword = 0;
   int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
+  float fsec2f[512], fsec3f[2];
   double fsec2[512], fsec3[2];
   int datatype;
   int param;
 
   memset(isec1, 0, 256*sizeof(int));
   fsec2[0] = 0; fsec2[1] = 0;
+  fsec2f[0] = 0; fsec2f[1] = 0;
 
-  gribsize = gribbuffersize / sizeof(int);
+  gribsize = (int)(gribbuffersize / sizeof(int));
   param    = vlistInqVarParam(vlistID, varID);
 
   cgribexDefaultSec0(isec0);
@@ -2277,12 +2237,22 @@ size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
     }
   //printf("isec4[16] %d\n", isec4[16]);
 
-  gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
-	   datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
+  if ( memtype == MEMTYPE_FLOAT )
+    {
+      for ( int i = 0; i < ISEC2_NumVCP; ++i ) fsec2f[10+i] = fsec2[10+i];
+      fsec3f[ 1] = fsec3[ 1];
+    }
+
+  if ( memtype == MEMTYPE_FLOAT )
+    gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
+             (int)datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
+  else
+    gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
+             (int)datasize, (int *) gribbuffer, gribsize, &iword, "C", &iret);
 
   if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
 
-  nbytes = iword*sizeof(int);
+  nbytes = (size_t)iword * sizeof (int);
 #else
   Error("CGRIBEX support not compiled in!");
 #endif
diff --git a/libcdi/src/stream_cgribex.h b/libcdi/src/stream_cgribex.h
index 8a8ae79..6fef957 100644
--- a/libcdi/src/stream_cgribex.h
+++ b/libcdi/src/stream_cgribex.h
@@ -6,9 +6,9 @@ int cgribexScanTimestep2(stream_t * streamptr);
 int cgribexScanTimestep(stream_t * streamptr);
 
 int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval);
+		  int unreduced, int *nmiss, double missval);
 
-size_t cgribexEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
 		     long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize);
 
diff --git a/libcdi/src/stream_ext.c b/libcdi/src/stream_ext.c
index 02a55b6..69f2e52 100644
--- a/libcdi/src/stream_ext.c
+++ b/libcdi/src/stream_ext.c
@@ -11,6 +11,8 @@
 #include "file.h"
 #include "cdi.h"
 #include "cdi_int.h"
+#include "stream_ext.h"
+#include "stream_fcommon.h"
 #include "varscan.h"
 #include "datetime.h"
 #include "extra.h"
@@ -106,7 +108,7 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -129,7 +131,8 @@ int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = extRead(fileID, extp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Failed to read EXTRA record");
 
   extInqHeader(extp, header);
   extInqDataDP(extp, data);
@@ -159,48 +162,19 @@ int extReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	    (*nmiss)++;
 	  }
     }
-
-  return (1);
 }
 
 
-int extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
 }
 
 
-int extDefRecord(stream_t *streamptr)
+void extDefRecord(stream_t *streamptr)
 {
   int gridID;
   int header[4];
-  int status = 0;
   int pdis, pcat, pnum;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
 
@@ -215,30 +189,24 @@ int extDefRecord(stream_t *streamptr)
   extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
 
   extDefHeader(extp, header);
-
-  return (status);
 }
 
 
-int extWriteRecord(stream_t *streamptr, const double *data)
+void extWriteRecord(stream_t *streamptr, const double *data)
 {
-  int status = 0;
   int fileID = streamptr->fileID;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
 
   extDefDataDP(extp, data);
-
   extWrite(fileID, extp);
-
-  return (status);
 }
 
 static
 void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
-		  long recsize, off_t position, int prec, int number)
+		  size_t recsize, off_t position, int prec, int number)
 {
   int leveltype;
-  int gridID = UNDEFID;
+  int gridID = CDI_UNDEFID;
   int levelID = 0;
   int tsID, recID, varID;
   record_t *record;
@@ -270,10 +238,10 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
   leveltype = ZAXIS_GENERIC;
 
   varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
-	       extInqDatatype(prec, number), &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -283,33 +251,6 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
 	    varID, gridID, levelID);
 }
 
-
-void extCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
-		  int level, int xysize)
-{
-  int varID = 0;
-  int levelID = 0;
-  record_t *record;
-
-  record  = &streamptr->tsteps[tsID].records[recID];
-
-  if ( param != (*record).param || level != (*record).ilevel )
-    Error("inconsistent timestep");
-
-  (*record).position = position;
-  /*
-  varID   = (*record).varID;
-  levelID = (*record).levelID;
-
-  streamptr->vars[varID].level[levelID] = recID;
-
-  streamptr->tsteps[tsID].nallrecs++;
-  streamptr->nrecs++;
-  */
-  if ( CDI_Debug )
-    Message("varID = %d levelID = %d", varID, levelID);
-}
-
 static
 void extScanTimestep1(stream_t *streamptr)
 {
@@ -391,7 +332,7 @@ void extScanTimestep1(stream_t *streamptr)
       if ( CDI_Debug )
 	Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
 
-      extAddRecord(streamptr, param, rlevel, rxysize, recsize, recpos, extp->prec, extp->number);
+      extAddRecord(streamptr, param, rlevel, rxysize, (size_t)recsize, recpos, extp->prec, extp->number);
     }
 
   streamptr->rtsteps = 1;
@@ -400,8 +341,8 @@ void extScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -413,10 +354,10 @@ void extScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-      (record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+        (record_t *)xrealloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -455,7 +396,6 @@ int extScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -480,7 +420,7 @@ int extScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -503,7 +443,7 @@ int extScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       extInqHeader(extp, header);
 
@@ -527,7 +467,7 @@ int extScanTimestep2(stream_t *streamptr)
       nextstep = FALSE;
       for ( recID = 0; recID < nrecords; recID++ )
 	{
-	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
+	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
 	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
 
 	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
@@ -622,23 +562,20 @@ int extInqContents(stream_t *streamptr)
 }
 
 static
-int extScanTimestep(stream_t *streamptr)
+long extScanTimestep(stream_t *streamptr)
 {
   int header[4];
   int status;
   int fileID;
-  int tsID;
   // int rxysize = 0;
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
   off_t recpos = 0;
   int recID;
-  taxis_t *taxis;
   int rindex, nrecs = 0;
   extcompvar_t compVar, compVar0;
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
-
+  /*
   if ( CDI_Debug )
     {
       Message("streamID = %d", streamptr->self);
@@ -646,12 +583,10 @@ int extScanTimestep(stream_t *streamptr)
       Message("rts = %d", streamptr->rtsteps);
       Message("nts = %d", streamptr->ntsteps);
     }
+  */
 
-  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;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -660,7 +595,7 @@ int extScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -677,7 +612,7 @@ int extScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  extInqHeader(extp, header);
 
@@ -699,9 +634,7 @@ int extScanTimestep(stream_t *streamptr)
 	      taxis->vdate = vdate;
 	      taxis->vtime = vtime;
 	    }
-	  /*
-	  extCmpRecord(streamptr, tsID, nrecs, recpos, param, rlevel, rxysize);
-	  */
+
 	  compVar.param  = param;
           compVar.level  = rlevel;
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
@@ -713,7 +646,7 @@ int extScanTimestep(stream_t *streamptr)
 		      tsID, recID,
 		      streamptr->tsteps[tsID].records[recID].param, param,
 		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	      Error("Invalid, unsupported or inconsistent record structure");
+	      Error("Invalid, unsupported or inconsistent record structure!");
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
@@ -751,7 +684,8 @@ int extScanTimestep(stream_t *streamptr)
 
 int extInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  int nrecs;
+  long ntsteps;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
diff --git a/libcdi/src/stream_ext.h b/libcdi/src/stream_ext.h
index 4fe4918..89c8e2e 100644
--- a/libcdi/src/stream_ext.h
+++ b/libcdi/src/stream_ext.h
@@ -9,10 +9,10 @@ int    extInqContents(stream_t *streamptr);
 int    extInqTimestep(stream_t *streamptr, int tsID);
 
 int    extInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    extDefRecord(stream_t *streamptr);
-int    extCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    extReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    extWriteRecord(stream_t *streamptr, const double *data);
+void   extDefRecord(stream_t *streamptr);
+void   extCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   extReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   extWriteRecord(stream_t *streamptr, const double *data);
 
 void   extReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   extWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/libcdi/src/stream_fcommon.c b/libcdi/src/stream_fcommon.c
new file mode 100644
index 0000000..bd335c5
--- /dev/null
+++ b/libcdi/src/stream_fcommon.c
@@ -0,0 +1,42 @@
+#include <stdlib.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 = xmalloc(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/libcdi/src/stream_fcommon.h b/libcdi/src/stream_fcommon.h
new file mode 100644
index 0000000..a4b12e7
--- /dev/null
+++ b/libcdi/src/stream_fcommon.h
@@ -0,0 +1,23 @@
+#ifndef STREAM_FCOMMON_H
+#define STREAM_FCOMMON_H
+
+#include "cdi_int.h"
+
+enum {
+  SINGLE_PRECISION = 4,
+  DOUBLE_PRECISION = 8,
+};
+
+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/libcdi/src/stream_grb.c b/libcdi/src/stream_grb.c
index 76e24a6..5cf0f08 100644
--- a/libcdi/src/stream_grb.c
+++ b/libcdi/src/stream_grb.c
@@ -9,6 +9,7 @@
 #include "cdi.h"
 #include "cdi_int.h"
 #include "stream_cgribex.h"
+#include "stream_grb.h"
 #include "stream_gribapi.h"
 #include "file.h"
 #include "cgribex.h"  /* gribZip gribGetZip gribGinfo */
@@ -182,16 +183,14 @@ int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
 }
 */
 
-int grbDefRecord(stream_t * streamptr)
+void grbDefRecord(stream_t * streamptr)
 {
-  int status = 0;
-
-  return (status);
+  UNUSED(streamptr);
 }
 
 static
 int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-	      int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID)
+	      int unreduced, int *nmiss, double missval, int vlistID, int varID)
 {
   int status = 0;
 
@@ -203,61 +202,101 @@ int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *dat
       if ( cdiNAdditionalGRIBKeys > 0 )
 	Error("CGRIBEX decode does not support reading of additional GRIB keys!");
 #endif
-      status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval);
+      status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval);
     }
   else
 #endif
     {
-      status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval, vlistID, varID);
+      status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval, vlistID, varID);
     }
 
   return (status);
 }
 
 
-int grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
+int grbUnzipRecord(unsigned char *gribbuffer, size_t *gribsize)
 {
-  int status = 0;
-  unsigned char *gribbuffer;
-  int fileID;
-  int recID, vrecID, tsID, gridID, varID;
-  long recsize;
-  off_t recpos;
-  int gridsize;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
+  int zip = 0;
+  int izip;
+  size_t igribsize;
+  size_t ogribsize;
+  long unzipsize;
+
+  igribsize = *gribsize;
+  ogribsize = *gribsize;
 
-  filetype = streamptr->filetype;
+  if ( (izip = gribGetZip(igribsize, gribbuffer, &unzipsize)) > 0 )
+    {
+      zip = izip;
+      if ( izip == 128 ) /* szip */
+	{
+	  unsigned char *itmpbuffer = NULL;
+	  size_t itmpbuffersize = 0;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
+	  if ( unzipsize < (long) igribsize )
+	    {
+	      fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
+	      return (0);
+	    }
 
-  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;
-  recsize = streamptr->tsteps[tsID].records[recID].size;
-  varID   = streamptr->tsteps[tsID].records[recID].varID;
+	  if ( itmpbuffersize < igribsize )
+	    {
+	      itmpbuffersize = igribsize;
+	      itmpbuffer = (unsigned char *) realloc(itmpbuffer, itmpbuffersize);
+	    }
 
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
+	  memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
+
+	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+
+	  ogribsize = gribUnzip(gribbuffer, unzipsize, itmpbuffer, igribsize);
+
+	  free(itmpbuffer);
+
+	  if ( ogribsize <= 0 ) Error("Decompression problem!");
+	}
+      else
+	{
+	  Error("Decompression for %d not implemented!", izip);
+	}
+    }
+
+  *gribsize = ogribsize;
+
+  return zip;
+}
+
+
+void grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
+{
+  int filetype = streamptr->filetype;
+
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
+
+  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];
+  off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+  size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+  int varID   = streamptr->tsteps[tsID].records[recID].varID;
+
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
 
   streamptr->numvals += gridsize;
 
   fileSetPos(fileID, recpos, SEEK_SET);
 
-  fileRead(fileID, gribbuffer, (size_t) recsize);
+  if (fileRead(fileID, gribbuffer, recsize) != recsize)
+    Error("Failed to read GRIB record");
 
-  missval = vlistInqVarMissval(vlistID, varID);
+  double missval = vlistInqVarMissval(vlistID, varID);
 
-  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
+  streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
 
-  streamptr->tsteps[tsID].records[recID].zip = zip;
-
-  return (status);
+  grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
 }
 
 static
@@ -383,54 +422,44 @@ int grbInqTimestep(stream_t * streamptr, int tsID)
 
 void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
 {
-  int fileID;
-  int levelID, nlevs, gridID, gridsize;
-  unsigned char *gribbuffer;
-  int tsID, recID;
-  long recsize;
-  off_t recpos, currentfilepos;
-  int imiss;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
+  int filetype = streamptr->filetype;
 
-  filetype = streamptr->filetype;
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
+  int vlistID = streamptr->vlistID;
+  int fileID  = streamptr->fileID;
+  int tsID    = streamptr->curTsID;
 
-  vlistID  = streamptr->vlistID;
-  fileID   = streamptr->fileID;
-  tsID     = streamptr->curTsID;
-
-  nlevs    = streamptr->vars[varID].nlevs;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
+  int nlevs    = streamptr->vars[varID].nlevs;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
 
   if ( CDI_Debug )
     Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
 
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
   *nmiss = 0;
-  for ( levelID = 0; levelID < nlevs; levelID++ )
+  for (int levelID = 0; levelID < nlevs; levelID++ )
     {
-      recID   = streamptr->vars[varID].level[levelID];
-      recpos  = streamptr->tsteps[tsID].records[recID].position;
-      recsize = streamptr->tsteps[tsID].records[recID].size;
+      int recID   = streamptr->vars[varID].level[levelID];
+      off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+      size_t recsize = streamptr->tsteps[tsID].records[recID].size;
 
       fileSetPos(fileID, recpos, SEEK_SET);
 
       fileRead(fileID, gribbuffer, recsize);
 
-      missval = vlistInqVarMissval(vlistID, varID);
+      double missval = vlistInqVarMissval(vlistID, varID);
 
-      grbDecode(filetype, gribbuffer, recsize, &data[levelID*gridsize], gridsize,
-		streamptr->unreduced, &imiss, &zip, missval, vlistID, varID);
+      int imiss;
 
-      *nmiss += imiss;
+      streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+      grbDecode(filetype, gribbuffer, (int)recsize, &data[levelID*gridsize], gridsize,
+		streamptr->unreduced, &imiss, missval, vlistID, varID);
 
-      streamptr->tsteps[tsID].records[recID].zip = zip;
+      *nmiss += imiss;
     }
 
   fileSetPos(fileID, currentfilepos, SEEK_SET);
@@ -439,36 +468,25 @@ void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
 
 void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss)
 {
-  int fileID;
-  int gridID, gridsize;
-  unsigned char *gribbuffer;
-  long recsize;
-  off_t recpos, currentfilepos;
-  int tsID, recID;
-  int vlistID;
-  int zip;
-  int filetype;
-  double missval;
+  int filetype = streamptr->filetype;
 
-  filetype = streamptr->filetype;
+  unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
 
-  gribbuffer = (unsigned char *) streamptr->record->buffer;
-
-  vlistID  = streamptr->vlistID;
-  gridID   = vlistInqVarGrid(vlistID, varID);
-  gridsize = gridInqSize(gridID);
-  tsID     = streamptr->curTsID;
+  int vlistID = streamptr->vlistID;
+  int gridID   = vlistInqVarGrid(vlistID, varID);
+  int gridsize = gridInqSize(gridID);
+  int tsID = streamptr->curTsID;
 
   if ( CDI_Debug )
     Message("gridID = %d gridsize = %d", gridID, gridsize);
 
-  fileID = streamptr->fileID;
+  int fileID = streamptr->fileID;
 
-  currentfilepos = fileGetPos(fileID);
+  off_t currentfilepos = fileGetPos(fileID);
 
-  recID   = streamptr->vars[varID].level[levelID];
-  recpos  = streamptr->tsteps[tsID].records[recID].position;
-  recsize = streamptr->tsteps[tsID].records[recID].size;
+  int recID   = streamptr->vars[varID].level[levelID];
+  off_t recpos  = streamptr->tsteps[tsID].records[recID].position;
+  size_t recsize = streamptr->tsteps[tsID].records[recID].size;
 
   if ( recsize == 0 )
     Error("Internal problem! Recordsize is zero for record %d at timestep %d",
@@ -478,41 +496,43 @@ void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *dat
 
   fileRead(fileID, gribbuffer, recsize);
 
-  missval = vlistInqVarMissval(vlistID, varID);
+  double missval = vlistInqVarMissval(vlistID, varID);
 
-  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
+  streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
 
-  fileSetPos(fileID, currentfilepos, SEEK_SET);
+  grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
 
-  streamptr->tsteps[tsID].records[recID].zip = zip;
+  fileSetPos(fileID, currentfilepos, SEEK_SET);
 }
 
 static
-size_t grbEncode(int filetype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		 int date, int time, int tsteptype, int numavg,
-		 long datasize, const double *data, int nmiss, unsigned char **gribbuffer,
-		 int ljpeg, void *gribContainer)
+		 size_t datasize, const double *data, int nmiss, unsigned char **gribbuffer,
+		 int comptype, void *gribContainer)
 {
   size_t nbytes;
-  size_t gribbuffersize;
 
 #if  defined  (HAVE_LIBCGRIBEX)
   if ( filetype == FILETYPE_GRB )
     {
-      gribbuffersize = datasize*4+3000;
+      size_t gribbuffersize = datasize*4+3000;
       *gribbuffer = (unsigned char *) malloc(gribbuffersize);
 
-      nbytes = cgribexEncode(varID, levelID, vlistID, gridID, zaxisID,
+      nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
 			     date, time, tsteptype, numavg,
-			     datasize, data, nmiss, *gribbuffer, gribbuffersize);
+			     (long)datasize, data, nmiss, *gribbuffer, gribbuffersize);
     }
   else
 #endif
     {
+      if ( memtype == MEMTYPE_FLOAT ) Error("gribapiEncode() not implemented for memtype float!");
+
+      size_t gribbuffersize;
       nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
 			     date, time, tsteptype, numavg,
-			     datasize, data, nmiss, gribbuffer, &gribbuffersize,
-			     ljpeg, gribContainer);
+			     (long)datasize, data, nmiss, gribbuffer, &gribbuffersize,
+			     comptype, gribContainer);
     }
 
   return (nbytes);
@@ -533,7 +553,7 @@ size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
 
   if ( filetype == FILETYPE_GRB )
     {
-      nbytes = gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
+      nbytes = (size_t)gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
     }
   else
     {
@@ -548,14 +568,13 @@ size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
 }
 
 
-int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
 {
   size_t nwrite;
   int fileID;
   int gridID;
   int zaxisID;
   unsigned char *gribbuffer = NULL;
-  long datasize;
   int tsID;
   int vlistID;
   int date, time;
@@ -563,12 +582,8 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   int numavg = 0;
   size_t nbytes;
   int filetype;
-  int ljpeg = 0;
-  int ljpeg_warn = 1;
   void *gc = NULL;
 
-  if ( memtype == MEMTYPE_FLOAT ) Error("grb_write_var_slice not implemented for memtype float!");
-
   filetype  = streamptr->filetype;
   fileID    = streamptr->fileID;
   vlistID   = streamptr->vlistID;
@@ -576,6 +591,8 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   zaxisID   = vlistInqVarZaxis(vlistID, varID);
   tsteptype = vlistInqVarTsteptype(vlistID, varID);
 
+  int comptype  = streamptr->comptype;
+
   tsID      = streamptr->curTsID;
   date      = streamptr->tsteps[tsID].taxis.vdate;
   time      = streamptr->tsteps[tsID].taxis.vtime;
@@ -585,7 +602,7 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
   if ( CDI_Debug )
     Message("gridID = %d zaxisID = %d", gridID, zaxisID);
 
-  datasize = gridInqSize(gridID);
+  size_t datasize = (size_t)gridInqSize(gridID);
   /*
   gribbuffersize = datasize*4+3000;
   gribbuffer = (unsigned char *) malloc(gribbuffersize);
@@ -606,23 +623,19 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
 #endif
     }
 
-  if ( streamptr->comptype == COMPRESS_JPEG )
+  if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
+
+  if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
     {
-      if ( filetype == FILETYPE_GRB2 )
-	{
-	  ljpeg = 1;
-	}
-      else
-	{
-	  if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
-	  ljpeg_warn = 0;
-	}
+      static int ljpeg_warn = 1;
+      if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
+      ljpeg_warn = 0;
     }
 
-  nbytes = grbEncode(filetype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg, 
-		     datasize, (const double*) data, nmiss, &gribbuffer, ljpeg, gc);
+  nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
+		     datasize, (const double*) data, nmiss, &gribbuffer, comptype, gc);
 
-  if ( streamptr->comptype == COMPRESS_SZIP )
+  if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
     nbytes = grbSzip(filetype, gribbuffer, nbytes);
 
   {
@@ -633,11 +646,13 @@ int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype
     nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
   }
 
-  if ( nwrite != nbytes ) perror(__func__);
+  if ( nwrite != nbytes )
+    {
+      perror(__func__);
+      Error("Failed to write GRIB slice!");
+    }
 
   if ( gribbuffer ) free(gribbuffer);
-
-  return ((int)nwrite);
 }
 
 
@@ -662,103 +677,88 @@ void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data
 }
 
 
-int grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
+void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  size_t gribbuffersize;
-  off_t recpos;
-  size_t nwrite;
-  unsigned char *gribbuffer;
-  int filetype;
-  size_t nbytes;
-  long unzipsize;
-  int izip;
-
-  filetype = streamptr1->filetype;
+  int filetype = streamptr1->filetype;
 
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
+  int fileID1 = streamptr1->fileID;
+  int fileID2 = streamptr2->fileID;
 
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
+  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;
 
   fileSetPos(fileID1, recpos, SEEK_SET);
 
-  gribbuffersize = recsize == (recsize>>3)<<3 ? recsize : (1+(recsize>>3))<<3;
+  /* round up recsize to next multiple of 8 */
+  size_t gribbuffersize = ((recsize + 7U) & ~7U);
 
-  gribbuffer = (unsigned char *) malloc(gribbuffersize);
+  unsigned char *gribbuffer = xmalloc(gribbuffersize);
 
-  fileRead(fileID1, gribbuffer, recsize);
+  if (fileRead(fileID1, gribbuffer, recsize) != recsize)
+    Error("Could not read GRIB record for copying!");
 
-  nbytes = recsize;
+  size_t nbytes = recsize;
 
-  izip = gribGetZip(recsize, gribbuffer, &unzipsize);
+  if ( filetype == FILETYPE_GRB )
+    {
+      long unzipsize;
+      int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
 
-  if ( izip == 0 )
-    if ( streamptr2->comptype == COMPRESS_SZIP )
-      nbytes = grbSzip(filetype, gribbuffer, nbytes);
+      if ( izip == 0 )
+        if ( streamptr2->comptype == COMPRESS_SZIP )
+          nbytes = grbSzip(filetype, gribbuffer, nbytes);
+    }
 
   while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
 
-  nwrite = fileWrite(fileID2, gribbuffer, nbytes);
-  if ( nwrite != nbytes ) perror(__func__);
+  size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
+  if ( nwrite != nbytes )
+    {
+      perror(__func__);
+      Error("Could not write record for copying!");
+    }
 
   free(gribbuffer);
-
-  return ((int)nwrite);
 }
 
 
-int grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
+void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
 {
-  int status = 0;
   int varID, levelID;
 
   varID   = streamptr->record->varID;
   levelID = streamptr->record->levelID;
 
-  status = grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-
-  return (status);
+  grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
 }
 
 
-void streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
+void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
 {
-  int recID, vrecID, tsID;
-  int filetype;
-  void *gribbuffer;
-  long gribbuffersize;
-  off_t recpos;
-  int zip;
-  stream_t *streamptr;
-
-  streamptr = stream_to_pointer(streamID);
+  stream_t *streamptr = stream_to_pointer(streamID);
 
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
+  int filetype = streamptr->filetype;
 
   if ( filetype == FILETYPE_GRB )
     {
-      tsID    = streamptr->curTsID;
-      vrecID  = streamptr->tsteps[tsID].curRecID;
-      recID   = streamptr->tsteps[tsID].recIDs[vrecID];
-      recpos  = streamptr->tsteps[tsID].records[recID].position;
-      zip     = streamptr->tsteps[tsID].records[recID].zip;
+      int tsID     = streamptr->curTsID;
+      int vrecID   = streamptr->tsteps[tsID].curRecID;
+      int recID    = streamptr->tsteps[tsID].recIDs[vrecID];
+      off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+      int zip      = streamptr->tsteps[tsID].records[recID].zip;
 
-      gribbuffer = streamptr->record->buffer;
-      gribbuffersize = streamptr->record->buffersize;
+      void *gribbuffer = streamptr->record->buffer;
+      size_t gribbuffersize = streamptr->record->buffersize;
 
       if ( zip > 0 )
 	Error("Compressed GRIB records unsupported!");
       else
-	gribGinfo(recpos, gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
+        grib_info_for_grads(recpos, (long)gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
     }
 }
 /*
diff --git a/libcdi/src/stream_grb.h b/libcdi/src/stream_grb.h
index ba5bd77..13b802c 100644
--- a/libcdi/src/stream_grb.h
+++ b/libcdi/src/stream_grb.h
@@ -7,16 +7,16 @@ int   grbInqContents(stream_t * streamptr);
 int   grbInqTimestep(stream_t * streamptr, int tsID);
 
 int   grbInqRecord(stream_t * streamptr, int *varID, int *levelID);
-int   grbDefRecord(stream_t * streamptr);
-int   grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
-int   grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
-int   grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
+void  grbDefRecord(stream_t * streamptr);
+void  grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
+void  grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
+void  grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
 
 void  grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss);
 void  grb_write_var(stream_t * streamptr, int varID, int memtype, const void *data, int nmiss);
 
 void  grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss);
-int   grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
+void  grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
 
 int   grib1ltypeToZaxisType(int grib_ltype);
 int   grib2ltypeToZaxisType(int grib_ltype);
diff --git a/libcdi/src/stream_gribapi.c b/libcdi/src/stream_gribapi.c
index af78517..081c718 100644
--- a/libcdi/src/stream_gribapi.c
+++ b/libcdi/src/stream_gribapi.c
@@ -28,6 +28,7 @@ typedef struct {
   int level1;
   int level2;
   int ltype;
+  int tsteptype;
   char name[32];
 } compvar2_t;
 
@@ -175,11 +176,10 @@ double timeunit_factor(int tu1, int tu2)
 static
 int gribapiGetTimeUnits(grib_handle *gh)
 {
-  int status;
   int timeunits = -1;
   long unitsOfTime = -1;
 
-  status = grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
+  grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
 
   GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
 
@@ -193,18 +193,17 @@ int gribapiGetEndStep(grib_handle *gh, int startStep, int timeunits)
 {
   int endStep = startStep;
   int timeunits2 = timeunits;
-  int status;
-  long unitsOfTime;
-  long lpar;
 
-  status = grib_get_long(gh, "stepUnits", &unitsOfTime);
+  long unitsOfTime;
+  int status = grib_get_long(gh, "stepUnits", &unitsOfTime);
   if ( status == 0 ) timeunits2 = getTimeunits(unitsOfTime);
   //timeunits2 = gribapiGetTimeUnits(gh);
 
+  long lpar;
   status = grib_get_long(gh, "endStep", &lpar);
 
   if ( status == 0 )
-    endStep = (int) ((lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
+    endStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
   // printf("%d %d %d %d %d %g\n", startStep, endStep, lpar, timeunits, timeunits2, timeunit_factor(timeunits, timeunits2));
 
   return (endStep);
@@ -257,7 +256,7 @@ int gribapiGetTsteptype(grib_handle *gh)
 	  else if ( strncmp("ratio",   stepType, len) == 0 ) tsteptype = TSTEP_RATIO;
 	  else if ( lprint )
 	    {
-	      Message("stepType %s unsupported, set to instant!", stepType);
+	      Message("Time stepType %s unsupported, set to instant!", stepType);
 	      lprint = FALSE;
 	    }
 
@@ -341,30 +340,33 @@ int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
 	cdiDecodeDate(rdate, &ryear, &rmonth, &rday);
 	cdiDecodeTime(rtime, &rhour, &rminute, &rsecond);
 
-	encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
+        if ( rday > 0 )
+          {
+            encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
 
-	addsec = 0;
-	switch ( timeUnits )
-	  {
-	  case TUNIT_SECOND:  addsec =         time_period; break;
-	  case TUNIT_MINUTE:  addsec =    60 * time_period; break;
-	  case TUNIT_HOUR:    addsec =  3600 * time_period; break;
-	  case TUNIT_3HOURS:  addsec = 10800 * time_period; break;
-	  case TUNIT_6HOURS:  addsec = 21600 * time_period; break;
-	  case TUNIT_12HOURS: addsec = 43200 * time_period; break;
-	  case TUNIT_DAY:     addsec = 86400 * time_period; break;
-	  default:
-	    if ( lprint )
-	      {
-	        Warning("Time unit %d unsupported", timeUnits);
-		lprint = FALSE;
-	      }
-	    break;
-	  }
+            addsec = 0;
+            switch ( timeUnits )
+              {
+              case TUNIT_SECOND:  addsec =         time_period; break;
+              case TUNIT_MINUTE:  addsec =    60 * time_period; break;
+              case TUNIT_HOUR:    addsec =  3600 * time_period; break;
+              case TUNIT_3HOURS:  addsec = 10800 * time_period; break;
+              case TUNIT_6HOURS:  addsec = 21600 * time_period; break;
+              case TUNIT_12HOURS: addsec = 43200 * time_period; break;
+              case TUNIT_DAY:     addsec = 86400 * time_period; break;
+              default:
+                if ( lprint )
+                  {
+                    Warning("Time unit %d unsupported", timeUnits);
+                    lprint = FALSE;
+                  }
+                break;
+              }
 
-	julday_add_seconds(addsec, &julday, &secofday);
+            julday_add_seconds(addsec, &julday, &secofday);
 
-	decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
+            decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
+          }
 
 	*vdate = cdiEncodeDate(ryear, rmonth, rday);
 	*vtime = cdiEncodeTime(rhour, rminute, rsecond);
@@ -378,14 +380,9 @@ static
 void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 {
   long editionNumber;
-  int gridtype;
-  size_t datasize;
-  long numberOfPoints;
-  long lpar;
-
   GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
 
-  gridtype = gribapiGetGridType(gh);
+  int gridtype = gribapiGetGridType(gh);
   /*
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -396,7 +393,9 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
   */
   memset(grid, 0, sizeof(grid_t));
 
+  size_t datasize;
   GRIB_CHECK(grib_get_size(gh, "values", &datasize), 0);
+  long numberOfPoints;
   GRIB_CHECK(grib_get_long(gh, "numberOfPoints", &numberOfPoints), 0);
 
   switch (gridtype)
@@ -404,23 +403,25 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
       {
-	int nlon, nlat;
-
+        long lpar;
 	GRIB_CHECK(grib_get_long(gh, "Ni", &lpar), 0);
-	nlon = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlon = (int)lpar;
 	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
-	nlat = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlat = (int)lpar;
 
 	if ( gridtype == GRID_GAUSSIAN )
           {
             GRIB_CHECK(grib_get_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar), 0);
-            grid->np = lpar;
+            grid->np = (int)lpar;
           }
 
 	if ( numberOfPoints != nlon*nlat )
-	  Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat);
+	  Error("numberOfPoints (%ld) and gridSize (%d) differ!", numberOfPoints, nlon*nlat);
 
-	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size  = (int)numberOfPoints;
 	grid->xsize = nlon;
 	grid->ysize = nlat;
 	grid->xinc  = 0;
@@ -474,23 +475,27 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       }
     case GRID_GAUSSIAN_REDUCED:
       {
-	int nlat, i;
 	size_t dummy;
 	long *pl;
 
+        long lpar;
         GRIB_CHECK(grib_get_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar), 0);
-        grid->np = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+        grid->np = (int)lpar;
 
 	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
-	nlat = lpar;
+        /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */
+	int nlat = (int)lpar;
 
-	grid->size   = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size   = (int)numberOfPoints;
 
-        grid->rowlon = (int *) malloc(nlat*sizeof(int));
-        pl          = (long *) malloc(nlat*sizeof(long));
-	dummy       = nlat;
+        grid->rowlon = (int *) malloc((size_t)nlat * sizeof (int));
+        pl          = (long *) malloc((size_t)nlat * sizeof (long));
+	dummy       = (size_t)nlat;
 	GRIB_CHECK(grib_get_long_array(gh, "pl", pl, &dummy), 0);
-	for ( i = 0; i < nlat; ++i ) grid->rowlon[i] = pl[i];
+        /* 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;
@@ -544,6 +549,7 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     case GRID_LCC:
       {
 	int nlon, nlat;
+        long lpar;
 
 	GRIB_CHECK(grib_get_long(gh, "Nx", &lpar), 0);
 	nlon = lpar;
@@ -586,19 +592,28 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 	grid->lcomplex = 0;
 	if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1;
 
-	grid->size  = datasize;
+        /* FIXME: assert(datasize >= INT_MIN && datasize <= INT_MAX) */
+	grid->size  = (int)datasize;
+        long lpar;
 	GRIB_CHECK(grib_get_long(gh, "J", &lpar), 0);
-	grid->trunc = lpar;
+        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+	grid->trunc = (int)lpar;
 
 	break;
       }
     case GRID_GME:
       {
-	grid->size  = numberOfPoints;
-	if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->nd  = lpar;
-	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->ni  = lpar;
-	if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->ni2 = lpar;
-	if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->ni3 = lpar;
+        /* 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;
 
 	break;
       }
@@ -609,11 +624,16 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         size_t len = sizeof(reference_link);
         reference_link[0] = 0;
 
-    	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+    	grid->size  = (int)numberOfPoints;
+        long lpar;
         if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 )
           {
-            grid->number   = lpar;
-            if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 ) grid->position = lpar;
+            /* 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_string(gh, "gridDescriptionFile", reference_link, &len) == 0 )
               {
@@ -632,11 +652,14 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
     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;
 
-	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = lpar;
-	if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = lpar;
-
-	grid->size  = numberOfPoints;
+        /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */
+	grid->size  = (int)numberOfPoints;
 
 	if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size )
 	  {
@@ -678,16 +701,13 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
 static
 void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2)
 {
-  int status;
-  long lpar;
-  double dlevel;
-
   *leveltype = 0;
-  *lbounds = 0;
-  *level1  = 0;
-  *level2  = 0;
+  *lbounds   = 0;
+  *level1    = 0;
+  *level2    = 0;
 
-  status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
+  long lpar;
+  int status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
   if ( status == 0 )
     {
       *leveltype = (int) lpar;
@@ -702,6 +722,7 @@ void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
 
       if ( *lbounds == 0 )
 	{
+          double dlevel;
 	  GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0);
 	  if ( *leveltype == 100 ) dlevel *= 100;
 	  if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;
@@ -713,9 +734,9 @@ void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       else
 	{
 	  GRIB_CHECK(grib_get_long(gh, "topLevel", &lpar), 0);
-	  *level1 = lpar;
+	  *level1 = (int)lpar;
 	  GRIB_CHECK(grib_get_long(gh, "bottomLevel", &lpar), 0);
-	  *level2 = lpar;
+	  *level2 = (int)lpar;
 	}
     }
 }
@@ -740,14 +761,15 @@ double grib2ScaleFactor(long factor)
 }
 
 static
-void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2, int *level_sf, int *level_unit)
+void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1, 
+                   int *level2, int *level_sf, int *level_unit)
 {
   int status;
-  int leveltype2 = -1;
   long lpar;
   long factor;
 
-  *leveltype  = 0;
+  *leveltype1 = 0;
+  *leveltype2 = -1;
   *lbounds    = 0;
   *level1     = 0;
   *level2     = 0;
@@ -760,25 +782,26 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       long llevel;
       double dlevel1 = 0, dlevel2 = 0;
 
-      *leveltype = (int) lpar;
+      *leveltype1 = (int) lpar;
 
       status = grib_get_long(gh, "typeOfSecondFixedSurface", &lpar);
-      if ( status == 0 ) leveltype2 = lpar;
+      /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+      if ( status == 0 ) *leveltype2 = (int)lpar;
 
-      if ( *leveltype != 255 && leveltype2 != 255 && leveltype2 > 0 ) *lbounds = 1;
-      if ( *leveltype == GRIB2_LTYPE_REFERENCE && leveltype2 == 1 ) *lbounds = 0;
+      if ( *leveltype1 != 255 && *leveltype2 != 255 && *leveltype2 > 0 ) *lbounds = 1;
+      if ( *leveltype1 == GRIB2_LTYPE_REFERENCE && *leveltype2 == 1 ) *lbounds = 0;
 
-      if ( *leveltype == GRIB2_LTYPE_LANDDEPTH )
+      if ( *leveltype1 == GRIB2_LTYPE_LANDDEPTH )
         {
           *level_sf = 1000;
           *level_unit = CDI_UNIT_M;
         }
-      else if ( *leveltype == GRIB2_LTYPE_ISOBARIC )
+      else if ( *leveltype1 == GRIB2_LTYPE_ISOBARIC )
         {
           *level_sf = 1000;
           *level_unit = CDI_UNIT_PA;
         }
-      else if ( *leveltype == GRIB2_LTYPE_SIGMA )
+      else if ( *leveltype1 == GRIB2_LTYPE_SIGMA )
         {
           *level_sf = 1000;
           *level_unit = 0;
@@ -789,12 +812,12 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
       if ( llevel != GRIB_MISSING_LONG )
         {
           if ( factor != GRIB_MISSING_LONG )
-            dlevel1 = llevel*grib2ScaleFactor(factor);
+            dlevel1 = (double)llevel * grib2ScaleFactor(factor);
           else
-            dlevel1 = llevel;
+            dlevel1 = (double)llevel;
         }
 
-      if ( *level_sf != 0 ) dlevel1 *= (*level_sf);
+      if ( *level_sf != 0 ) dlevel1 *= (double)(*level_sf);
 
       if ( *lbounds == 1 )
 	{
@@ -803,9 +826,9 @@ void grib2GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, i
           if ( llevel != GRIB_MISSING_LONG )
             {
               if ( factor != GRIB_MISSING_LONG )
-                dlevel2 = llevel*grib2ScaleFactor(factor);
+                dlevel2 = (double)llevel * grib2ScaleFactor(factor);
               else
-                dlevel2 = llevel;
+                dlevel2 = (double)llevel;
             }
 
           if ( *level_sf != 0 ) dlevel2 *= (*level_sf);
@@ -829,8 +852,8 @@ void gribapiGetString(grib_handle *gh, const char *key, char *string, size_t len
 #if  defined  (HAVE_LIBGRIB_API)
 static
 void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
-		      long recsize, off_t position, int datatype, int comptype, size_t len, const char *varname,
-                      int leveltype, int lbounds, int level1, int level2, int level_sf, int level_unit)
+		      size_t recsize, off_t position, int datatype, int comptype, size_t len, const char *varname,
+                      int leveltype1, int leveltype2, int lbounds, int level1, int level2, int level_sf, int level_unit)
 {
   long editionNumber;
   int zaxistype;
@@ -859,21 +882,22 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
 
   GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
 
-  // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype);
+  // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype1);
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = leveltype;
+  (*record).size      = recsize;
+  (*record).position  = position;
+  (*record).param     = param;
+  (*record).ilevel    = level1;
+  (*record).ilevel2   = level2;
+  (*record).ltype     = leveltype1;
+  (*record).tsteptype = tsteptype;
   memcpy((*record).varname, varname, len);
 
   gribapiGetGrid(gh, &grid);
 
   gridID = varDefGrid(vlistID, grid, 0);
 
-  zaxistype = gribapiGetZaxisType(editionNumber, leveltype);
+  zaxistype = gribapiGetZaxisType(editionNumber, leveltype1);
 
   switch (zaxistype)
     {
@@ -885,13 +909,14 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
         double *vctptr;
 
         GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
-        vctsize = lpar;
+        /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+        vctsize = (int)lpar;
         if ( vctsize > 0 )
           {
             vctptr = (double *) malloc(vctsize*sizeof(double));
-            dummy = vctsize;
+            dummy = (size_t)vctsize;
             GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
-            varDefVCT(vctsize, vctptr);
+            varDefVCT((size_t)vctsize, vctptr);
             free(vctptr);
           }
         break;
@@ -944,11 +969,11 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
   // fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units);
 
   varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, level_sf, level_unit,
-	       datatype, &varID, &levelID, tsteptype, numavg, leveltype,
+	       datatype, &varID, &levelID, tsteptype, numavg, leveltype1, leveltype2,
 	       varname, stdname, longname, units);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   varDefCompType(varID, comptype);
 
@@ -971,6 +996,11 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
   if ( status == 0 )
     varDefTypeOfGeneratingProcess(varID, (int) typeOfGeneratingProcess);
 
+  long productDefinitionTemplate = 0;
+  status = grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate);
+  if ( status == 0 )
+    varDefProductDefinitionTemplate(varID, (int) productDefinitionTemplate);
+
   int    i;
   long   lval;
   double dval;
@@ -1012,9 +1042,10 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
       status = grib_get_long(gh, "generatingProcessIdentifier", &processID);
       if ( status == 0 )
 	{
-	  modelID = modelInq(varInqInst(varID), processID, NULL);
+          /* FIXME: assert(processID >= INT_MIN && processID <= INT_MAX) */
+	  modelID = modelInq(varInqInst(varID), (int)processID, NULL);
 	  if ( modelID == CDI_UNDEFID )
-	    modelID = modelDef(varInqInst(varID), processID, NULL);
+	    modelID = modelDef(varInqInst(varID), (int)processID, NULL);
 	  varDefModel(varID, modelID);
 	}
     }
@@ -1070,17 +1101,18 @@ int gribapiGetParam(grib_handle *gh)
 }
 
 static
-compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, char *name)
+compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, int tsteptype, char *name)
 {
   compvar2_t compVar;
   size_t maxlen = sizeof(compVar.name);
   size_t len = strlen(name);
   if ( len > maxlen ) len = maxlen;
 
-  compVar.param  = param;
-  compVar.level1 = level1;
-  compVar.level2 = level2;
-  compVar.ltype  = leveltype;
+  compVar.param     = param;
+  compVar.level1    = level1;
+  compVar.level2    = level2;
+  compVar.ltype     = leveltype;
+  compVar.tsteptype = tsteptype;
   memset(compVar.name, 0, maxlen);
   memcpy(compVar.name, name, len);
 
@@ -1088,19 +1120,25 @@ compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype, char
 }
 
 static
-int gribapiVarCompare(compvar2_t compVar, record_t record)
+int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
 {
-  int rstatus;
   compvar2_t compVar0;
   size_t maxlen = sizeof(compVar.name);
 
-  compVar0.param  = record.param;
-  compVar0.level1 = record.ilevel;
-  compVar0.level2 = record.ilevel2;
-  compVar0.ltype  = record.ltype;
+  compVar0.param     = record.param;
+  compVar0.level1    = record.ilevel;
+  compVar0.level2    = record.ilevel2;
+  compVar0.ltype     = record.ltype;
+  compVar0.tsteptype = record.tsteptype;
   memcpy(compVar0.name, record.varname, maxlen);
 
-  rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
+  if ( flag == 0 )
+    {
+      if ( compVar0.tsteptype == TSTEP_INSTANT  && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
+      if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT  ) compVar0.tsteptype = TSTEP_INSTANT;
+    }
+
+  int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
 
   return (rstatus);
 }
@@ -1114,7 +1152,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 #if  defined  (HAVE_LIBGRIB_API)
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int rstatus;
   int status;
   int fileID;
@@ -1129,7 +1167,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   int nrecords, nrecs, recID;
   int nrecs_scanned = 0;
   int datatype;
-  long recsize = 0;
+  size_t recsize = 0;
   int warn_time = TRUE;
   // int warn_numavg = TRUE;
   int taxisID = -1;
@@ -1140,7 +1178,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   long editionNumber;
   long lpar;
   size_t len;
@@ -1148,6 +1186,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
   int lieee = FALSE;
   int lbounds;
   int level_sf, level_unit;
+  int tsteptype;
   char paramstr[32];
   char varname[256];
 
@@ -1166,7 +1205,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
     {
       level1 = 0;
       level2 = 0;
-      recsize = gribGetSize(fileID);
+      recsize = (size_t)gribGetSize(fileID);
       recpos  = fileGetPos(fileID);
 
       if ( recsize == 0 )
@@ -1187,13 +1226,13 @@ int gribapiScanTimestep1(stream_t * streamptr)
       lieee = FALSE;
 
       comptype = COMPRESS_NONE;
-      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+      if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  comptype = COMPRESS_SZIP;
 	  unzipsize += 100;
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
@@ -1213,7 +1252,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
 	  param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	  grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	  grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
           level_sf = 0;
           level_unit = 0;
 	}
@@ -1232,7 +1271,7 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
 	  param = gribapiGetParam(gh);
 
-	  grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	  grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	}
 
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -1243,9 +1282,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
       if ( len > 32 ) len = 32;
       //printf("param = %s  name = %s   l1 = %d  l2 = %d\n", paramstr, varname, level1, level2);
 
+      tsteptype = gribapiGetTsteptype(gh);
       gribapiGetValidityDateTime(gh, &vdate, &vtime);
       /*
-      printf("%d %d %d\n", vdate, vtime, leveltype);
+      printf("%d %d %d\n", vdate, vtime, leveltype1);
       */
       if ( lieee )
         {
@@ -1280,10 +1320,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+	  compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
 	  for ( recID = 0; recID < nrecs; recID++ )
-            if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID]) == 0 ) break;
+            if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
 
 	  if ( cdiInventoryMode == 1 )
 	    {
@@ -1338,10 +1378,10 @@ int gribapiScanTimestep1(stream_t * streamptr)
 
       if ( CDI_Debug )
 	Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
-                nrecs, (int)recpos, varname, paramstr, leveltype, level1, level2, vdate, vtime);
+                nrecs, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
 
       gribapiAddRecord(streamptr, param, gh, recsize, recpos, datatype, comptype, len, varname,
-                       leveltype, lbounds, level1, level2, level_sf, level_unit);
+                       leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit);
 
       grib_handle_delete(gh);
       gh = NULL;
@@ -1369,8 +1409,8 @@ int gribapiScanTimestep1(stream_t * streamptr)
       taxis->type  = TAXIS_ABSOLUTE;
     }
 
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -1426,7 +1466,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 #if  defined  (HAVE_LIBGRIB_API)
   off_t recpos = 0;
   unsigned char *gribbuffer = NULL;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int rtabnum = 0;
   int rcode = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -1437,7 +1477,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   size_t readsize;
   int nrecords, nrecs, recID, rindex;
   int nrecs_scanned = 0;
-  long recsize = 0;
+  size_t recsize = 0;
   //  int warn_numavg = TRUE;
   int tsteptype;
   int taxisID = -1;
@@ -1446,7 +1486,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   int param = 0;
   long editionNumber;
   long lpar;
@@ -1493,7 +1533,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
     {
       if ( rindex > nrecords ) break;
 
-      recsize = gribGetSize(fileID);
+      recsize = (size_t)gribGetSize(fileID);
       recpos  = fileGetPos(fileID);
       if ( recsize == 0 )
 	{
@@ -1503,19 +1543,19 @@ int gribapiScanTimestep2(stream_t * streamptr)
       if ( recsize > buffersize )
 	{
 	  buffersize = recsize;
-	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
+	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	}
 
       readsize = recsize;
       rstatus = gribRead(fileID, gribbuffer, &readsize);
       if ( rstatus ) break;
 
-      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+      if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	{
 	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	  if ( (long) buffersize < unzipsize )
+	  if ( buffersize < (size_t)unzipsize )
 	    {
-	      buffersize = unzipsize;
+	      buffersize = (size_t)unzipsize;
 	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 	    }
 	}
@@ -1535,7 +1575,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 
 	  param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	  grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	  grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
           level_sf = 0;
           level_unit = 0;
 	}
@@ -1543,7 +1583,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
 	{
 	  param = gribapiGetParam(gh);
 
-	  grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	  grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	}
 
       cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -1592,10 +1632,10 @@ int gribapiScanTimestep2(stream_t * streamptr)
       datetime.date  = vdate;
       datetime.time  = vtime;
 
-      compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+      compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
       for ( recID = 0; recID < nrecords; recID++ )
-        if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+        if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 
       if ( recID == nrecords )
 	{
@@ -1620,11 +1660,11 @@ int gribapiScanTimestep2(stream_t * streamptr)
 
       if ( CDI_Debug )
 	Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
-                nrecs_scanned, (int)recpos, varname, paramstr, leveltype, level1, level2, vdate, vtime);
+                nrecs_scanned, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
 
       streamptr->tsteps[tsID].records[recID].size = recsize;
 
-      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	{
 	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		  tsID, recID,
@@ -1694,10 +1734,10 @@ int gribapiScanTimestep(stream_t * streamptr)
 {
   int rstatus = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  long recsize = 0;
+  size_t recsize = 0;
   off_t recpos = 0;
   unsigned char *gribbuffer;
-  long buffersize = 0;
+  size_t buffersize = 0;
   int fileID;
   int rtabnum = 0;
   int rcode = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
@@ -1714,7 +1754,7 @@ int gribapiScanTimestep(stream_t * streamptr)
   long unzipsize;
   compvar2_t compVar;
   grib_handle *gh = NULL;
-  int leveltype;
+  int leveltype1, leveltype2 = -1;
   int param = 0;
   long editionNumber;
   long lpar;
@@ -1760,7 +1800,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	{
 	  if ( rindex > nrecs ) break;
 
-	  recsize = gribGetSize(fileID);
+	  recsize = (size_t)gribGetSize(fileID);
 	  recpos  = fileGetPos(fileID);
 	  if ( recsize == 0 )
 	    {
@@ -1785,12 +1825,12 @@ int gribapiScanTimestep(stream_t * streamptr)
 	      break;
 	    }
 
-	  if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
+	  if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
 	    {
 	      unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-	      if ( (long) buffersize < unzipsize )
+	      if ( buffersize < (size_t)unzipsize )
 		{
-		  buffersize = unzipsize;
+		  buffersize = (size_t)unzipsize;
 		  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
 		}
 	    }
@@ -1810,7 +1850,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 
 	      param = cdiEncodeParam(rcode, rtabnum, 255);
 
-	      grib1GetLevel(gh, &leveltype, &lbounds, &level1, &level2);
+	      grib1GetLevel(gh, &leveltype1, &lbounds, &level1, &level2);
               level_sf = 0;
               level_unit = 0;
 	    }
@@ -1818,7 +1858,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	    {
 	      param = gribapiGetParam(gh);
 
-	      grib2GetLevel(gh, &leveltype, &lbounds, &level1, &level2, &level_sf, &level_unit);
+	      grib2GetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit);
 	    }
 
           cdiParamToString(param, paramstr, sizeof(paramstr));
@@ -1868,12 +1908,14 @@ int gribapiScanTimestep(stream_t * streamptr)
 	  datetime.date  = vdate;
 	  datetime.time  = vtime;
 
-	  compVar = gribapiVarSet(param, level1, level2, leveltype, varname);
+          int tsteptype = gribapiGetTsteptype(gh);
+
+	  compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname);
 
 	  for ( vrecID = 0; vrecID < nrecs; vrecID++ )
 	    {
 	      recID   = streamptr->tsteps[1].recIDs[vrecID];
-	      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) == 0 ) break;
+	      if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
 	    }
 
 	  if ( vrecID == nrecs )
@@ -1905,7 +1947,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 	  if ( CDI_Debug )
 	    Message("%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
 
-	  if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID]) != 0 )
+	  if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
 	    {
 	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
 		      tsID, recID,
@@ -1967,7 +2009,7 @@ int gribapiScanTimestep(stream_t * streamptr)
       streamptr->ntsteps = tsID;
     }
 
-  rstatus = streamptr->ntsteps;
+  rstatus = (int)streamptr->ntsteps;
 #else
   Error("GRIB_API support not compiled in!");
 #endif
@@ -1980,7 +2022,7 @@ int gribapiScanTimestep(stream_t * streamptr)
 #endif
 
 int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID)
+		  int unreduced, int *nmiss, double missval, int vlistID, int varID)
 {
   int status = 0;
 #if  defined  (HAVE_LIBGRIB_API)
@@ -1989,6 +2031,9 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
   size_t datasize, dummy, recsize;
   grib_handle *gh = NULL;
 
+  UNUSED(vlistID);
+  UNUSED(varID);
+
   if ( unreduced )
     {
       static int lwarn = 1;
@@ -2000,7 +2045,7 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
 	}
     }
 
-  recsize = gribsize;
+  recsize = (size_t)gribsize;
   gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
   GRIB_CHECK(my_grib_set_double(gh, "missingValue", missval), 0);
 
@@ -2145,7 +2190,7 @@ int getTimeunitFactor(int timeunit)
 }
 
 static
-void gribapiDefStepUnits(grib_handle *gh, int timeunit, int gcinit)
+void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
 {
   long unitsOfTime;
 
@@ -2164,12 +2209,14 @@ void gribapiDefStepUnits(grib_handle *gh, int timeunit, int gcinit)
   if ( !gcinit )
     {
       GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
+      if ( proDefTempNum == 8 || proDefTempNum == 11 )
+        GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
       GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
     }
 }
 
 static
-int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gcinit)
+int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
 {
   long proDefTempNum = 0;
   size_t len = 64;
@@ -2190,6 +2237,14 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gc
     default:             strcpy(stepType, "instant"); proDefTempNum = 0; break;
     }
 
+  if ( typeOfGeneratingProcess == 4 )
+    {
+      if ( proDefTempNum == 8 ) proDefTempNum = 11;
+      else                      proDefTempNum = 1;
+    }
+
+  if ( productDefinitionTemplate != -1 ) proDefTempNum = productDefinitionTemplate;
+
   if ( !gcinit )
     {
       if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "productDefinitionTemplateNumber", proDefTempNum), 0);
@@ -2201,9 +2256,9 @@ int gribapiDefSteptype(int editionNumber, grib_handle *gh, int tsteptype, int gc
 }
 
 static
-void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int tsteptype, int gcinit)
+void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
 {
-  (void ) gribapiDefSteptype(editionNumber, gh, tsteptype, gcinit);
+  (void ) gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
   if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 0), 0);
   if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
@@ -2214,7 +2269,7 @@ void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int tim
 
 static
 int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rtime, int vdate, int vtime,
-                          int tsteptype, int timeunit, int calendar, int gcinit)
+                          int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int timeunit, int calendar, int gcinit)
 {
   int status = -1;
   int year, month, day, hour, minute, second;
@@ -2238,9 +2293,9 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
 
   if ( !(int) fmod(days*86400.0 + secs, factor) )
     {
-      int proDefTempNum = gribapiDefSteptype(editionNumber, gh, tsteptype, gcinit);
+      int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
-      gribapiDefStepUnits(gh, timeunit, gcinit);
+      gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
 
       endStep = (int) ((days*86400.0 + secs)/factor);
 
@@ -2264,10 +2319,13 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
 }
 
 static
-void gribapiDefTime(int editionNumber, int typeOfGeneratingProcess, grib_handle *gh , int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
+void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOfGeneratingProcess, grib_handle *gh,
+                    int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
 {
   int taxistype = -1;
 
+  UNUSED(numavg);
+
   if ( taxisID != -1 ) taxistype = taxisInqType(taxisID);
 
   if ( typeOfGeneratingProcess == 196 )
@@ -2291,19 +2349,19 @@ void gribapiDefTime(int editionNumber, int typeOfGeneratingProcess, grib_handle
       int timeunit = taxisInqTunit(taxisID);
 
       status = gribapiDefDateTimeRel(editionNumber, gh, rdate, rtime, vdate, vtime,
-                                     tsteptype, timeunit, calendar, gcinit);
+                                     productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, timeunit, calendar, gcinit);
 
       if ( status != 0 ) taxistype = TAXIS_ABSOLUTE;
     }
 
   if ( taxistype == TAXIS_ABSOLUTE )
     {
-      gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, tsteptype, gcinit);
+      gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
     }
 }
 
 static
-void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, int lieee, int datatype, int nmiss, int gcinit)
+void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
 {
   int gridtype;
   int status;
@@ -2311,6 +2369,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
   size_t len;
   char *mesg;
 
+  UNUSED(nmiss);
+
   gridtype = gridInqType(gridID);
 
   if ( editionNumber <= 1 )
@@ -2358,17 +2418,22 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 
   if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
     {
-      if ( editionNumber != 2 || lieee ) { ljpeg = 0; }
+      if ( editionNumber != 2 || lieee ) { comptype = 0; }
 
-      if ( ljpeg )
+      if ( comptype )
         {
-          if ( nmiss > 0 ) ljpeg = 0;
+          //if ( nmiss > 0 ) comptype = 0;
 
-          if ( ljpeg )
+          if ( comptype == COMPRESS_JPEG )
             {
               mesg = "grid_jpeg"; len = strlen(mesg);
               GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
             }
+          else if ( comptype == COMPRESS_SZIP )
+            {
+              mesg = "grid_szip"; len = strlen(mesg);
+              GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+            }
           else
             {
               mesg = "grid_simple"; len = strlen(mesg);
@@ -2522,7 +2587,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 	/* South -> North */
 	//if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
 
-        if ( editionNumber != 2 ) { lieee = 0; ljpeg = 0; }
+        if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
 
         if ( lieee )
           {
@@ -2534,15 +2599,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int ljpeg, i
 	    else
 	      GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
           }
-        else if ( ljpeg )
+        else if ( comptype )
 	  {
-            if ( nmiss > 0 ) ljpeg = 0;
+            //if ( nmiss > 0 ) comptype = 0;
 
-            if ( ljpeg )
+            if ( comptype == COMPRESS_JPEG )
               {
                 mesg = "grid_jpeg"; len = strlen(mesg);
                 GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
               }
+            else if ( comptype == COMPRESS_SZIP )
+              {
+                mesg = "grid_szip"; len = strlen(mesg);
+                GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+              }
             else
               {
                 mesg = "grid_simple"; len = strlen(mesg);
@@ -2688,6 +2758,7 @@ static
 void getLevelFactor(double level, long *factor, long *out_scaled_value)
 {
   double scaled_value  = level;
+  /* FIXME: lround might be better here */
   long   iscaled_value = (long) round(scaled_value);
   long   i;
 
@@ -2695,7 +2766,8 @@ void getLevelFactor(double level, long *factor, long *out_scaled_value)
   for ( i=0; (fabs(scaled_value - (double) iscaled_value) >= eps) && i < 7; i++ )
     {
       scaled_value *= 10.;
-      iscaled_value = round(scaled_value);
+      /* FIXME: lround might be better here */
+      iscaled_value = (long)round(scaled_value);
     }
 
   (*factor)           = i;
@@ -2709,13 +2781,13 @@ void gribapiDefLevelType(grib_handle *gh, int gcinit, const char *keyname, long
 }
 
 static
-void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype, int lbounds, double level, double dlevel1, double dlevel2)
+void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, int lbounds, double level, double dlevel1, double dlevel2)
 {
   long scaled_level;
   long factor;
 
-  gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype);
-  if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype);
+  gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype1);
+  if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype2);
 
   if ( !lbounds ) dlevel1 = level;
 
@@ -2731,22 +2803,19 @@ void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype, int lbounds, dou
     }
 }
 
+int zaxisInqLtype2(int zaxisID);
+
 static
 void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit)
 {
-  double level;
   int lbounds = 0;
-  int zaxistype, ltype;
   static int warning = 1;
-  char uuid[17];
-  size_t len;
-  double scalefactor;
   double dlevel1 = 0, dlevel2 = 0;
 
-
-  zaxistype = zaxisInqType(zaxisID);
-  ltype = zaxisInqLtype(zaxisID);
-  level = zaxisInqLevel(zaxisID, levelID);
+  int zaxistype = zaxisInqType(zaxisID);
+  int ltype = zaxisInqLtype(zaxisID);
+  int ltype2 = zaxisInqLtype2(zaxisID);
+  double level = zaxisInqLevel(zaxisID, levelID);
 
   if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
     {
@@ -2783,7 +2852,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
         else
           gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", zaxisTypeToGrib2ltype(zaxistype));
 
-        GRIB_CHECK(my_grib_set_long(gh, "level", level), 0);
+        GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
 
 	break;
       }
@@ -2861,7 +2930,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 warning = 0;
               }
             GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
-            GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), vctsize), 0);
+            GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
           }
 
 	break;
@@ -2895,7 +2964,8 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 	  }
 	else
 	  {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, lbounds, level, dlevel1, dlevel2);
+            if ( ltype2 == -1 ) ltype2 = GRIB2_LTYPE_ISOBARIC;
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, ltype2, lbounds, level, dlevel1, dlevel2);
 	  }
 
 	break;
@@ -2906,7 +2976,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
           ; // not available
 	else
           {
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
           }
 
 	break;
@@ -2919,6 +2989,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 
 	if ( editionNumber <= 1 )
 	  {
+            double scalefactor;
 	    if      ( memcmp(units, "mm", 2) == 0 ) scalefactor =   0.1;
 	    else if ( memcmp(units, "cm", 2) == 0 ) scalefactor =   1; // cm
 	    else if ( memcmp(units, "dm", 2) == 0 ) scalefactor =  10;
@@ -2929,6 +3000,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
 	  }
 	else
 	  {
+            double scalefactor;
 	    if      ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.001;
 	    else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 0.01;
 	    else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 0.1;
@@ -2938,13 +3010,14 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
             dlevel1 *= scalefactor;
             dlevel2 *= scalefactor;
 
-            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
+            grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
 	  }
 
 	break;
       }
     case ZAXIS_REFERENCE:
       {
+        char uuid[16];
         int number;
 
         if ( !gcinit )
@@ -2964,7 +3037,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
-                len = 16;
+                size_t len = 16;
                 zaxisInqUUID(zaxisID, uuid);
                 if (grib_set_bytes(gh, "uuidOfVGrid", (unsigned char *) uuid, &len) != 0)
                   Warning("Can't write UUID!");
@@ -2983,7 +3056,7 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
                 GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
                 GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
-                len = 16;
+                size_t len = 16;
                 zaxisInqUUID(zaxisID, uuid);
                 if (grib_set_bytes(gh, "uuidOfVGrid", (unsigned char *) uuid, &len) != 0)
                   Warning("Can't write UUID!");
@@ -3042,7 +3115,7 @@ void gribHandleDelete(void *gh)
 size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
 		     long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
-		     int ljpeg, void *gribContainer)
+		     int comptype, void *gribContainer)
 {
   size_t nbytes = 0;
 #if  defined  (HAVE_LIBGRIB_API)
@@ -3053,6 +3126,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
   int lieee = FALSE;
   /*  int ensID, ensCount, forecast_type; *//* Ensemble Data */
   int typeOfGeneratingProcess;
+  int productDefinitionTemplate;
   long bitsPerValue;
   long editionNumber = 2;
   char name[256];
@@ -3063,6 +3137,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
   param    = vlistInqVarParam(vlistID, varID);
   datatype = vlistInqVarDatatype(vlistID, varID);
   typeOfGeneratingProcess = vlistInqVarTypeOfGeneratingProcess(vlistID, varID);
+  productDefinitionTemplate = vlistInqVarProductDefinitionTemplate(vlistID, varID);
 
   vlistInqVarName(vlistID, varID, name);
 
@@ -3080,10 +3155,6 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       if ( ! gc->init ) GRIB_CHECK(my_grib_set_long(gh, "typeOfGeneratingProcess", typeOfGeneratingProcess), 0);
     }
 
-  if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
-  if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
-
-  if ( ! gc->init ) gribapiDefParam(editionNumber, gh, param, name);
   /*
   if( vlistInqVarEnsemble( vlistID,  varID, &ensID, &ensCount, &forecast_type ) )
     {
@@ -3093,7 +3164,12 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
     }
   */
 
-  gribapiDefTime(editionNumber, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+  gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+
+  if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
+  if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
+
+  if ( ! gc->init ) gribapiDefParam(editionNumber, gh, param, name);
 
   if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = TRUE;
 
@@ -3104,9 +3180,9 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       GRIB_CHECK(my_grib_set_long(gh, "bitsPerValue", bitsPerValue), 0);
     }
 
-  gribapiDefGrid(editionNumber, gh, gridID, ljpeg, lieee, datatype, nmiss, gc->init);
+  gribapiDefGrid((int)editionNumber, gh, gridID, comptype, lieee, datatype, nmiss, gc->init);
 
-  gribapiDefLevel(editionNumber, gh, param, zaxisID, levelID, gc->init);
+  gribapiDefLevel((int)editionNumber, gh, param, zaxisID, levelID, gc->init);
 
   /* ---------------------------------- */
   /* Local change: 2013-01-28, FP (DWD) */
@@ -3114,29 +3190,37 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 
   vlist_t *vlistptr;
   vlistptr = vlist_to_pointer(vlistID);
-  if (!gc->init) {
-    int i;
-    for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  //if (!gc->init)
+  {
+    for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
       {
-	int ret = my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_dbl_keyword[i],
-                                  vlistptr->vars[varID].opt_grib_dbl_val[i]);
-	if (ret != 0) {
-	    fprintf(stderr, "key \"%s\"  :   value = %g\n",
-                    vlistptr->vars[varID].opt_grib_dbl_keyword[i],
-		    vlistptr->vars[varID].opt_grib_dbl_val[i]);
-	}
-	GRIB_CHECK(ret, 0);
+        if ( vlistptr->vars[varID].opt_grib_dbl_update[i] )
+          {
+            vlistptr->vars[varID].opt_grib_dbl_update[i] = FALSE;
+            int ret = my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_dbl_keyword[i],
+                                         vlistptr->vars[varID].opt_grib_dbl_val[i]);
+            if (ret != 0) {
+              fprintf(stderr, "key \"%s\"  :   value = %g\n",
+                      vlistptr->vars[varID].opt_grib_dbl_keyword[i],
+                      vlistptr->vars[varID].opt_grib_dbl_val[i]);
+            }
+            GRIB_CHECK(ret, 0);
+          }
       }
-    for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+    for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
       {
-	int ret = my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_int_keyword[i],
-	                        vlistptr->vars[varID].opt_grib_int_val[i]);
-	if (ret != 0) {
-	    fprintf(stderr, "key \"%s\"  :   value = %d\n",
-		    vlistptr->vars[varID].opt_grib_int_keyword[i],
-		    vlistptr->vars[varID].opt_grib_int_val[i]);
-	}
-	GRIB_CHECK(ret, 0);
+        if ( vlistptr->vars[varID].opt_grib_int_update[i] )
+          {
+            vlistptr->vars[varID].opt_grib_int_update[i] = FALSE;
+            int ret = my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_int_keyword[i],
+                                       vlistptr->vars[varID].opt_grib_int_val[i]);
+            if (ret != 0) {
+              fprintf(stderr, "key \"%s\"  :   value = %d\n",
+                      vlistptr->vars[varID].opt_grib_int_keyword[i],
+                      vlistptr->vars[varID].opt_grib_int_val[i]);
+            }
+            GRIB_CHECK(ret, 0);
+          }
       }
   }
 
@@ -3147,7 +3231,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       GRIB_CHECK(my_grib_set_double(gh, "missingValue", vlistInqVarMissval(vlistID, varID)), 0);
     }
 
-  GRIB_CHECK(grib_set_double_array(gh, "values", data, datasize), 0);
+  GRIB_CHECK(grib_set_double_array(gh, "values", data, (size_t)datasize), 0);
 
   /* get the size of coded message  */
   GRIB_CHECK(grib_get_message(gh, (const void **)&dummy, &recsize), 0);
diff --git a/libcdi/src/stream_gribapi.h b/libcdi/src/stream_gribapi.h
index 11bb7aa..d3ff963 100644
--- a/libcdi/src/stream_gribapi.h
+++ b/libcdi/src/stream_gribapi.h
@@ -6,7 +6,7 @@ int gribapiScanTimestep2(stream_t * streamptr);
 int gribapiScanTimestep(stream_t * streamptr);
 
 int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
-		  int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID);
+		  int unreduced, int *nmiss, double missval, int vlistID, int varID);
 
 size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
 		     int vdate, int vtime, int tsteptype, int numavg, 
diff --git a/libcdi/src/stream_ieg.c b/libcdi/src/stream_ieg.c
index f08214e..080bd2c 100644
--- a/libcdi/src/stream_ieg.c
+++ b/libcdi/src/stream_ieg.c
@@ -3,6 +3,7 @@
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <float.h>
 #include <math.h>
@@ -16,6 +17,8 @@
 #include "varscan.h"
 #include "datetime.h"
 #include "ieg.h"
+#include "stream_fcommon.h"
+#include "stream_ieg.h"
 #include "vlist.h"
 
 
@@ -98,7 +101,7 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -120,7 +123,8 @@ int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = iegRead(fileID, iegp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Could not read IEG record!");
 
   iegInqDataDP(iegp, data);
 
@@ -137,8 +141,6 @@ int iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	data[i] = missval;
 	(*nmiss)++;
       }
-
-  return (1);
 }
 
 static
@@ -418,8 +420,8 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 	else
 	  {
 	    IEG_G_Size(gdb) += (vctsize*4);
-	    memcpy(vct, zaxisInqVctPtr(zaxisID), vctsize/2*sizeof(double));
-	    memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, vctsize/2*sizeof(double));
+	    memcpy(vct, zaxisInqVctPtr(zaxisID), (size_t)vctsize/2*sizeof(double));
+	    memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, (size_t)vctsize/2*sizeof(double));
 	  }
 	break;
       }
@@ -524,41 +526,14 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 }
 
 
-int iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "IEG");
 }
 
 
-int iegDefRecord(stream_t *streamptr)
+void iegDefRecord(stream_t *streamptr)
 {
-  int status = 0;
   int vlistID;
   int gridID;
   int date, time;
@@ -598,15 +573,12 @@ int iegDefRecord(stream_t *streamptr)
   datatype = streamptr->record->prec;
 
   iegp->dprec = iegDefDatatype(datatype);
-
-  return (status);
 }
 
 
-int iegWriteRecord(stream_t *streamptr, const double *data)
+void iegWriteRecord(stream_t *streamptr, const double *data)
 {
   int fileID;
-  int status = 0;
   int i, gridsize, gridID;
   double refval;
   iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
@@ -625,13 +597,11 @@ int iegWriteRecord(stream_t *streamptr, const double *data)
   iegDefDataDP(iegp, data);
 
   iegWrite(fileID, iegp);
-
-  return (status);
 }
 
 static
 void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
-		  long recsize, off_t position, int prec)
+		  size_t recsize, off_t position, int prec)
 {
   int leveltype;
   int gridID = UNDEFID;
@@ -662,12 +632,12 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
       if ( IEG_P_LevelType(pdb) == 100 ) level1 *= 100;
     }
 
-  (*record).size     = recsize;
-  (*record).position = position;
-  (*record).param    = param;
-  (*record).ilevel   = level1;
-  (*record).ilevel2  = level2;
-  (*record).ltype    = IEG_P_LevelType(pdb);
+  record->size     = recsize;
+  record->position = position;
+  record->param    = param;
+  record->ilevel   = level1;
+  record->ilevel2  = level2;
+  record->ltype    = IEG_P_LevelType(pdb);
 
   if ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 )
     gridtype = GRID_LONLAT;
@@ -697,7 +667,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
 	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 )
 	      {
 		grid.xinc = xinc;
@@ -751,12 +721,11 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
 
   if ( leveltype == ZAXIS_HYBRID )
     {
-      int i;
       double tmpvct[100];
-      int vctsize = IEG_G_NumVCP(gdb);
+      size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
 
-      for ( i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
-      for ( 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);
     }
@@ -766,10 +735,10 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
   datatype = iegInqDatatype(prec);
 
   varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
-	       datatype, &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  record->varID   = (short)varID;
+  record->levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -838,7 +807,7 @@ void iegScanTimestep1(stream_t *streamptr)
   DateTime datetime, datetime0;
   int tsID;
   int varID;
-  long recsize;
+  size_t recsize;
   off_t recpos;
   int nrecords, nrecs, recID;
   int taxisID = -1;
@@ -867,7 +836,7 @@ void iegScanTimestep1(stream_t *streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       prec   = iegp->dprec;
       rcode  = IEG_P_Parameter(iegp->ipdb);
@@ -920,8 +889,8 @@ void iegScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -933,10 +902,11 @@ void iegScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-	(record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+	(record_t *)xrealloc(streamptr->tsteps[0].records,
+                             (size_t)nrecords * sizeof (record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -974,7 +944,7 @@ int iegScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
+  size_t recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -999,7 +969,7 @@ int iegScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = (int *)xmalloc((size_t)nrecords * sizeof(int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -1022,7 +992,7 @@ int iegScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       rcode  = IEG_P_Parameter(iegp->ipdb);
       tabnum = IEG_P_CodeTable(iegp->ipdb);
@@ -1146,7 +1116,7 @@ int iegInqContents(stream_t *streamptr)
 }
 
 static
-int iegScanTimestep(stream_t *streamptr)
+long iegScanTimestep(stream_t *streamptr)
 {
   int status;
   int fileID;
@@ -1154,7 +1124,7 @@ int iegScanTimestep(stream_t *streamptr)
   int tabnum;
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
+  size_t recsize = 0;
   off_t recpos = 0;
   int recID;
   taxis_t *taxis;
@@ -1183,7 +1153,8 @@ int iegScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs
+        = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -1200,7 +1171,7 @@ int iegScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  rcode  = IEG_P_Parameter(iegp->ipdb);
 	  tabnum = IEG_P_CodeTable(iegp->ipdb);
@@ -1275,7 +1246,7 @@ int iegScanTimestep(stream_t *streamptr)
 
 int iegInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  int nrecs;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
@@ -1283,7 +1254,7 @@ int iegInqTimestep(stream_t *streamptr, int tsID)
   if ( CDI_Debug )
     Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
 
-  ntsteps = UNDEFID;
+  long ntsteps = UNDEFID;
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = iegScanTimestep(streamptr);
 
diff --git a/libcdi/src/stream_ieg.h b/libcdi/src/stream_ieg.h
index 860cedb..2012792 100644
--- a/libcdi/src/stream_ieg.h
+++ b/libcdi/src/stream_ieg.h
@@ -9,10 +9,10 @@ int    iegInqContents(stream_t *streamptr);
 int    iegInqTimestep(stream_t *streamptr, int tsID);
 
 int    iegInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    iegDefRecord(stream_t *streamptr);
-int    iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    iegReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    iegWriteRecord(stream_t *streamptr, const double *data);
+void   iegDefRecord(stream_t *streamptr);
+void   iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   iegReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   iegWriteRecord(stream_t *streamptr, const double *data);
 
 void   iegReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   iegWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/libcdi/src/stream_record.c b/libcdi/src/stream_record.c
index 1e86e8e..c3e8739 100644
--- a/libcdi/src/stream_record.c
+++ b/libcdi/src/stream_record.c
@@ -19,25 +19,22 @@
 
 void recordInitEntry(record_t *record)
 {
-  (*record).position = CDI_UNDEFID;
-  (*record).size     = 0;
-  (*record).param    = 0;
-  (*record).ilevel   = CDI_UNDEFID;
-  (*record).used     = FALSE;
-  (*record).varID    = CDI_UNDEFID;
-  (*record).levelID  = CDI_UNDEFID;
-  memset((*record).varname, 0, sizeof((*record).varname));
+  record->position = CDI_UNDEFID;
+  record->size     = 0;
+  record->param    = 0;
+  record->ilevel   = CDI_UNDEFID;
+  record->used     = FALSE;
+  record->varID    = CDI_UNDEFID;
+  record->levelID  = CDI_UNDEFID;
+  memset(record->varname, 0, sizeof(record->varname));
 }
 
 
 int recordNewEntry(stream_t *streamptr, int tsID)
 {
   int recordID = 0;
-  int recordSize;
-  record_t *records;
-
-  recordSize = streamptr->tsteps[tsID].recordSize;
-  records    = streamptr->tsteps[tsID].records;
+  int recordSize = streamptr->tsteps[tsID].recordSize;
+  record_t *records = streamptr->tsteps[tsID].records;
   /*
     Look for a free slot in record.
     (Create the table the first time through).
@@ -46,7 +43,7 @@ int recordNewEntry(stream_t *streamptr, int tsID)
     {
       int i;
       recordSize = 1;   /*  <<<<----  */
-      records = (record_t *) malloc(recordSize*sizeof(record_t));
+      records = (record_t *)xmalloc((size_t)recordSize * sizeof (record_t));
       if ( records == NULL )
 	{
           Message("recordSize = %d", recordSize);
@@ -72,7 +69,8 @@ int recordNewEntry(stream_t *streamptr, int tsID)
       int i;
 
       recordSize = 2*recordSize;
-      records    = (record_t *) realloc(records, recordSize*sizeof(record_t));
+      records    = (record_t *)xrealloc(records,
+                                        (size_t)recordSize * sizeof (record_t));
       if ( records == NULL )
 	{
           Message("recordSize = %d", recordSize);
@@ -120,95 +118,46 @@ void cdiInitRecord(stream_t *streamptr)
 
 void streamInqRecord(int streamID, int *varID, int *levelID)
 {
-  /* int rec = 0; */
-  int recID, tsID, rindex;
-  int lindex;
-  stream_t *streamptr;
-
   check_parg(varID);
   check_parg(levelID);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
   cdiDefAccesstype(streamID, TYPE_REC);
 
   if ( ! streamptr->record ) cdiInitRecord(streamptr);
 
-  tsID   = streamptr->curTsID;
-  rindex = streamptr->tsteps[tsID].curRecID + 1;
+  int tsID   = streamptr->curTsID;
+  int rindex = streamptr->tsteps[tsID].curRecID + 1;
 
   if ( rindex >= streamptr->tsteps[tsID].nrecs )
     Error("record %d not available at timestep %d", rindex+1, tsID+1);
 
-  recID  = streamptr->tsteps[tsID].recIDs[rindex];
+  int recID  = streamptr->tsteps[tsID].recIDs[rindex];
 
   if ( recID == -1 || recID >= streamptr->tsteps[tsID].nallrecs )
     Error("Internal problem! tsID = %d recID = %d", tsID, recID);
 
   *varID   = streamptr->tsteps[tsID].records[recID].varID;
-  lindex   = streamptr->tsteps[tsID].records[recID].levelID;
+  int lindex = streamptr->tsteps[tsID].records[recID].levelID;
 
   *levelID = streamptr->vars[*varID].lindex[lindex];
 
   if ( CDI_Debug )
-    Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n",
-	    tsID, recID, *varID, *levelID);
+    Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n", tsID, recID, *varID, *levelID);
 
   streamptr->curTsID = tsID;
   streamptr->tsteps[tsID].curRecID = rindex;
-
-  /*
-  rec = recID + 1;
-  filetype = streamptr->filetype;
-
-  switch ( filetype )
-    {
-    case FILETYPE_GRB:
-      {
-        rec = grbInqRecord(streamID, varID, levelID);
-	break;
-      }
-    case FILETYPE_SRV:
-      {
-        rec = srvInqRecord(streamptr, varID, levelID);
-	break;
-      }
-#if  defined  (HAVE_LIBNETCDF)
-    case FILETYPE_NC:
-    case FILETYPE_NC2:
-    case FILETYPE_NC4:
-    case FILETYPE_NC4C:
-      {
-	rec = cdfInqRecord(streamID, varID, levelID);
-	break;
-      }
-#endif
-    default:
-      {
-	Error("%s support not compiled in!", strfiletype(filetype));
-	break;
-      }
-    }
-  */
 }
 
 
 void streamDefRecord(int streamID, int varID, int levelID)
 {
-  int status = 0;
-  int filetype;
-  int param, gridID, zaxisID, level;
-  int tsID;
-  int vlistID;
-  stream_t *streamptr;
-
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  tsID = streamptr->curTsID;
+  int tsID = streamptr->curTsID;
 
   if ( tsID == CDI_UNDEFID )
     {
@@ -218,11 +167,11 @@ void streamDefRecord(int streamID, int varID, int levelID)
 
   if ( ! streamptr->record ) cdiInitRecord(streamptr);
 
-  vlistID = streamptr->vlistID;
-  gridID  = vlistInqVarGrid(vlistID, varID);
-  zaxisID = vlistInqVarZaxis(vlistID, varID);
-  param   = vlistInqVarParam(vlistID, varID);
-  level   = (int) zaxisInqLevel(zaxisID, levelID);
+  int vlistID = streamptr->vlistID;
+  int gridID  = vlistInqVarGrid(vlistID, varID);
+  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+  int param   = vlistInqVarParam(vlistID, varID);
+  int level   = (int) zaxisInqLevel(zaxisID, levelID);
 
   streamptr->record->varID    = varID;
   streamptr->record->levelID  = levelID;
@@ -234,182 +183,127 @@ void streamDefRecord(int streamID, int varID, int levelID)
   streamptr->record->zaxisID  = zaxisID;
   streamptr->record->prec     = vlistInqVarDatatype(vlistID, varID);
 
-  filetype = streamptr->filetype;
-
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-        status = grbDefRecord(streamptr);
-	break;
-      }
+      grbDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-        status = srvDefRecord(streamptr);
-	break;
-      }
+      srvDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-        status = extDefRecord(streamptr);
-	break;
-      }
+      extDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-        status = iegDefRecord(streamptr);
-	break;
-      }
+      iegDefRecord(streamptr);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-	if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
-	status = cdfDefRecord(streamptr);
-	break;
-      }
+      if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+      cdfDefRecord(streamptr);
+      break;
 #endif
     default:
-      {
-	Error("%s support not compiled in!", strfiletype(filetype));
-	break;
-      }
+      Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+      break;
     }
 }
 
 
 void streamReadRecord(int streamID, double *data, int *nmiss)
 {
-  int status = 0;
-  int filetype;
-  stream_t *streamptr;
-
   check_parg(data);
   check_parg(nmiss);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
-
   *nmiss = 0;
 
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-        status = grbReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      grbReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-        status = srvReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      srvReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-        status = extReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      extReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-        status = iegReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      iegReadRecord(streamptr, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        /* FIXME: return value not inspected */
-	status = cdfReadRecord(streamptr, data, nmiss);
-	break;
-      }
+      cdfReadRecord(streamptr, data, nmiss);
+      break;
 #endif
     default:
       {
-	Error("%s support not compiled in!", strfiletype(filetype));
+	Error("%s support not compiled in!", strfiletype(streamptr->filetype));
 	break;
       }
     }
 }
 
-
-void stream_write_record(int streamID, int memtype, const void *data, int nmiss)
+static void
+stream_write_record(int streamID, int memtype, const void *data, int nmiss)
 {
-  int status = 0;
-  int filetype;
-  stream_t *streamptr;
-
   check_parg(data);
 
-  streamptr = stream_to_pointer(streamID);
-
+  stream_t *streamptr = stream_to_pointer(streamID);
   stream_check_ptr(__func__, streamptr);
 
-  filetype = streamptr->filetype;
-
-  switch (filetype)
+  switch (streamptr->filetype)
     {
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        status = grb_write_record(streamptr, memtype, data, nmiss);
-	break;
-      }
+      grb_write_record(streamptr, memtype, data, nmiss);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
-        status = srvWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
+      srvWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
-        status = extWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
+      extWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
-        status = iegWriteRecord(streamptr, (const double*) data);
-	break;
-      }
+      if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
+      iegWriteRecord(streamptr, (const double *)data);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
@@ -423,7 +317,7 @@ void stream_write_record(int streamID, int memtype, const void *data, int nmiss)
 #endif
     default:
       {
-	Error("%s support not compiled in!", strfiletype(filetype));
+	Error("%s support not compiled in!", strfiletype(streamptr->filetype));
 	break;
       }
     }
@@ -443,19 +337,15 @@ void streamWriteRecordF(int streamID, const float *data, int nmiss)
 
 void streamCopyRecord(int streamID2, int streamID1)
 {
-  int status = 0;
-  int filetype = CDI_UNDEFID, filetype1, filetype2;
-  stream_t *streamptr1;
-  stream_t *streamptr2;
-
-  streamptr1 = stream_to_pointer(streamID1);
-  streamptr2 = stream_to_pointer(streamID2);
+  stream_t *streamptr1 = stream_to_pointer(streamID1);
+  stream_t *streamptr2 = stream_to_pointer(streamID2);
 
   stream_check_ptr(__func__, streamptr1);
   stream_check_ptr(__func__, streamptr2);
 
-  filetype1 = streamptr1->filetype;
-  filetype2 = streamptr2->filetype;
+  int filetype1 = streamptr1->filetype;
+  int filetype2 = streamptr2->filetype;
+  int filetype  = FILETYPE_UNDEF;
 
   if ( filetype1 == filetype2 ) filetype = filetype2;
   else
@@ -480,7 +370,7 @@ void streamCopyRecord(int streamID2, int streamID1)
         }
     }
 
-  if ( filetype == CDI_UNDEFID )
+  if ( filetype == FILETYPE_UNDEF )
     Error("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
 
   switch (filetype)
@@ -488,46 +378,31 @@ void streamCopyRecord(int streamID2, int streamID1)
 #if  defined  (HAVE_LIBGRIB)
     case FILETYPE_GRB:
     case FILETYPE_GRB2:
-      {
-        /* FIXME: return value not inspected */
-	status = grbCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      grbCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBSERVICE)
     case FILETYPE_SRV:
-      {
-        /* FIXME: return value not inspected */
-	status = srvCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      srvCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBEXTRA)
     case FILETYPE_EXT:
-      {
-        /* FIXME: return value not inspected */
-	status = extCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      extCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBIEG)
     case FILETYPE_IEG:
-      {
-        /* FIXME: return value not inspected */
-	status = iegCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      iegCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
 #if  defined  (HAVE_LIBNETCDF)
     case FILETYPE_NC:
     case FILETYPE_NC2:
     case FILETYPE_NC4:
     case FILETYPE_NC4C:
-      {
-        /* FIXME: return value not inspected */
-	status = cdfCopyRecord(streamptr2, streamptr1);
-	break;
-      }
+      cdfCopyRecord(streamptr2, streamptr1);
+      break;
 #endif
     default:
       {
@@ -540,24 +415,22 @@ void streamCopyRecord(int streamID2, int streamID1)
 
 void cdi_create_records(stream_t *streamptr, int tsID)
 {
-  int nrecords, maxrecords;
-  int nvars, varID, recID;
+  unsigned nrecords, maxrecords;
   record_t *records;
-  int vlistID;
 
   if ( streamptr->tsteps[tsID].records ) return;
 
-  vlistID  = streamptr->vlistID;
+  int vlistID  = streamptr->vlistID;
 
   if ( tsID == 0 )
     {
       maxrecords = 0;
-      nvars = streamptr->nvars;
-      for ( varID = 0; varID < nvars; varID++)
-	maxrecords += streamptr->vars[varID].nlevs;
+      int nvars = streamptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++)
+	maxrecords += (unsigned)streamptr->vars[varID].nlevs;
     }
   else
-    maxrecords = streamptr->tsteps[0].recordSize;
+    maxrecords = (unsigned)streamptr->tsteps[0].recordSize;
 
   if ( tsID == 0 )
     {
@@ -566,42 +439,41 @@ void cdi_create_records(stream_t *streamptr, int tsID)
   else if ( tsID == 1 )
     {
       nrecords = 0;
-      maxrecords = streamptr->tsteps[0].recordSize;
-      for ( recID = 0; recID < maxrecords; recID++ )
+      maxrecords = (unsigned)streamptr->tsteps[0].recordSize;
+      for (unsigned recID = 0; recID < maxrecords; recID++ )
 	{
-	  varID = streamptr->tsteps[0].records[recID].varID;
-	  if ( varID != -1 ) /* varID = -1 for write mode !!! */
-	    if ( vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT )
-	      continue;
-	  nrecords++;
+	  int varID = streamptr->tsteps[0].records[recID].varID;
+	  nrecords +=
+            (varID == -1 /* varID = -1 for write mode !!! */
+             || vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT);
 	}
     }
   else
-    nrecords = streamptr->tsteps[1].nallrecs;
+    nrecords = (unsigned)streamptr->tsteps[1].nallrecs;
 
   if ( maxrecords > 0 )
-    records = (record_t *) malloc(maxrecords*sizeof(record_t));
+    records = (record_t *) malloc(maxrecords * sizeof(record_t));
   else
     records = NULL;
 
   streamptr->tsteps[tsID].records    = records;
-  streamptr->tsteps[tsID].recordSize = maxrecords;
-  streamptr->tsteps[tsID].nallrecs   = nrecords;
+  streamptr->tsteps[tsID].recordSize = (int)maxrecords;
+  streamptr->tsteps[tsID].nallrecs   = (int)nrecords;
 
   if ( tsID == 0 )
     {
-      for ( recID = 0; recID < maxrecords; recID++ )
+      for ( unsigned recID = 0; recID < maxrecords; recID++ )
 	recordInitEntry(&streamptr->tsteps[tsID].records[recID]);
     }
   else
     {
       memcpy(streamptr->tsteps[tsID].records,
 	     streamptr->tsteps[0].records,
-	     maxrecords*sizeof(record_t));
+	     (size_t)maxrecords * sizeof(record_t));
 
-      for ( recID = 0; recID < maxrecords; recID++ )
+      for ( unsigned recID = 0; recID < maxrecords; recID++ )
 	{
-	  varID = streamptr->tsteps[0].records[recID].varID;
+	  int varID = streamptr->tsteps[0].records[recID].varID;
 	  if ( varID != -1 ) /* varID = -1 for write mode !!! */
 	    if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
 	      {
diff --git a/libcdi/src/stream_srv.c b/libcdi/src/stream_srv.c
index 801fca6..34ec0e8 100644
--- a/libcdi/src/stream_srv.c
+++ b/libcdi/src/stream_srv.c
@@ -2,7 +2,9 @@
 #  include "config.h"
 #endif
 
+#include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "dmemory.h"
@@ -14,6 +16,8 @@
 #include "varscan.h"
 #include "datetime.h"
 #include "service.h"
+#include "stream_fcommon.h"
+#include "stream_srv.h"
 #include "vlist.h"
 
 
@@ -96,7 +100,7 @@ int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
 }
 */
 
-int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 {
   int vlistID, fileID;
   int status;
@@ -119,7 +123,8 @@ int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
   fileSetPos(fileID, recpos, SEEK_SET);
 
   status = srvRead(fileID, srvp);
-  if ( status != 0 ) return (0);
+  if ( status != 0 )
+    Error("Failed to read record from SRV file");
 
   srvInqHeader(srvp, header);
   srvInqDataDP(srvp, data);
@@ -137,48 +142,19 @@ int srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
 	data[i] = missval;
 	(*nmiss)++;
       }
-
-  return (1);
 }
 
 
-int srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
 {
-  int fileID1, fileID2;
-  int tsID, recID, vrecID;
-  long recsize;
-  off_t recpos;
-  int status = 0;
-  char *buffer;
-
-  fileID1 = streamptr1->fileID;
-  fileID2 = streamptr2->fileID;
-
-  tsID    = streamptr1->curTsID;
-  vrecID  = streamptr1->tsteps[tsID].curRecID;
-  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
-  recpos  = streamptr1->tsteps[tsID].records[recID].position;
-  recsize = streamptr1->tsteps[tsID].records[recID].size;
-
-  fileSetPos(fileID1, recpos, SEEK_SET);
-
-  buffer = (char *) malloc(recsize);
-
-  fileRead(fileID1, buffer, recsize);
-
-  fileWrite(fileID2, buffer, recsize);
-
-  free(buffer);
-
-  return (status);
+  streamFCopyRecord(streamptr2, streamptr1, "SRV");
 }
 
 
-int srvDefRecord(stream_t *streamptr)
+void srvDefRecord(stream_t *streamptr)
 {
   int gridID;
   int header[8];
-  int status = 0;
   int xsize, ysize;
   int datatype;
   int pdis, pcat, pnum;
@@ -213,30 +189,25 @@ int srvDefRecord(stream_t *streamptr)
   srvp->dprec = srvDefDatatype(datatype);
 
   srvDefHeader(srvp, header);
-
-  return (status);
 }
 
 
-int srvWriteRecord(stream_t *streamptr, const double *data)
+void srvWriteRecord(stream_t *streamptr, const double *data)
 {
-  int status = 0;
   int fileID = streamptr->fileID;
   srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
 
   srvDefDataDP(srvp, data);
 
   srvWrite(fileID, srvp);
-
-  return (status);
 }
 
 static
 void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ysize,
-                    long recsize, off_t position, int prec)
+                    size_t recsize, off_t position, int prec)
 {
   int leveltype;
-  int gridID = UNDEFID;
+  int gridID = CDI_UNDEFID;
   int levelID = 0;
   int tsID, recID, varID;
   int datatype;
@@ -271,10 +242,11 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
   datatype = srvInqDatatype(prec);
 
   varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
-	       datatype, &varID, &levelID, UNDEFID, 0, 0, NULL, NULL, NULL, NULL);
+	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL);
 
-  (*record).varID   = varID;
-  (*record).levelID = levelID;
+  xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
+  (*record).varID   = (short)varID;
+  (*record).levelID = (short)levelID;
 
   streamptr->tsteps[tsID].nallrecs++;
   streamptr->nrecs++;
@@ -284,33 +256,6 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
 	    varID, gridID, levelID);
 }
 
-
-void srvCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
-		  int level, int xsize, int ysize)
-{
-  int varID = 0;
-  int levelID = 0;
-  record_t *record;
-
-  record  = &streamptr->tsteps[tsID].records[recID];
-
-  if ( param != (*record).param || level != (*record).ilevel )
-    Error("inconsistent timestep");
-
-  (*record).position = position;
-  /*
-  varID   = (*record).varID;
-  levelID = (*record).levelID;
-
-  streamptr->vars[varID].level[levelID] = recID;
-
-  streamptr->tsteps[tsID].nallrecs++;
-  streamptr->nrecs++;
-  */
-  if ( CDI_Debug )
-    Message("varID = %d levelID = %d", varID, levelID);
-}
-
 static
 void srvScanTimestep1(stream_t *streamptr)
 {
@@ -324,7 +269,6 @@ void srvScanTimestep1(stream_t *streamptr)
   DateTime datetime, datetime0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos;
   int nrecords, nrecs, recID;
   int taxisID = -1;
@@ -353,7 +297,7 @@ void srvScanTimestep1(stream_t *streamptr)
 	  streamptr->ntsteps = 1;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       srvInqHeader(srvp, header);
 
@@ -404,8 +348,8 @@ void srvScanTimestep1(stream_t *streamptr)
 
   taxisID = taxisCreate(TAXIS_ABSOLUTE);
   taxis->type  = TAXIS_ABSOLUTE;
-  taxis->vdate = datetime0.date;
-  taxis->vtime = datetime0.time;
+  taxis->vdate = (int)datetime0.date;
+  taxis->vtime = (int)datetime0.time;
 
   vlistID = streamptr->vlistID;
   vlistDefTaxis(vlistID, taxisID);
@@ -417,10 +361,11 @@ void srvScanTimestep1(stream_t *streamptr)
     {
       streamptr->tsteps[0].recordSize = nrecords;
       streamptr->tsteps[0].records =
-	(record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+	(record_t *)xrealloc(streamptr->tsteps[0].records,
+                             (size_t)nrecords * sizeof(record_t));
     }
 
-  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[0].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[0].nrecs = nrecords;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[0].recIDs[recID] = recID;
@@ -458,7 +403,6 @@ int srvScanTimestep2(stream_t *streamptr)
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
   int tsID;
   int varID;
-  long recsize;
   off_t recpos = 0;
   int nrecords, nrecs, recID, rindex;
   int nextstep;
@@ -483,7 +427,7 @@ int srvScanTimestep2(stream_t *streamptr)
   cdi_create_records(streamptr, tsID);
 
   nrecords = streamptr->tsteps[0].nallrecs;
-  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
+  streamptr->tsteps[1].recIDs = (int *)xmalloc((size_t)nrecords * sizeof (int));
   streamptr->tsteps[1].nrecs = 0;
   for ( recID = 0; recID < nrecords; recID++ )
     streamptr->tsteps[1].recIDs[recID] = -1;
@@ -506,7 +450,7 @@ int srvScanTimestep2(stream_t *streamptr)
 	  streamptr->ntsteps = 2;
 	  break;
 	}
-      recsize = fileGetPos(fileID) - recpos;
+      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
       srvInqHeader(srvp, header);
 
@@ -624,23 +568,20 @@ int srvInqContents(stream_t *streamptr)
 }
 
 static
-int srvScanTimestep(stream_t *streamptr)
+long srvScanTimestep(stream_t *streamptr)
 {
   int header[8];
   int status;
   int fileID;
-  int tsID;
   /* int rxsize = 0, rysize = 0; */
   int param = 0;
   int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
-  long recsize = 0;
   off_t recpos = 0;
   int recID;
-  taxis_t *taxis;
   int rindex, nrecs = 0;
   SRVCOMPVAR compVar, compVar0;
   srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
-
+  /*
   if ( CDI_Debug )
     {
       Message("streamID = %d", streamptr->self);
@@ -648,12 +589,10 @@ int srvScanTimestep(stream_t *streamptr)
       Message("rts = %d", streamptr->rtsteps);
       Message("nts = %d", streamptr->ntsteps);
     }
+  */
 
-  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;
 
   if ( streamptr->tsteps[tsID].recordSize == 0 )
     {
@@ -662,7 +601,7 @@ int srvScanTimestep(stream_t *streamptr)
       nrecs = streamptr->tsteps[1].nrecs;
 
       streamptr->tsteps[tsID].nrecs = nrecs;
-      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
+      streamptr->tsteps[tsID].recIDs = (int *)xmalloc((size_t)nrecs * sizeof (int));
       for ( recID = 0; recID < nrecs; recID++ )
 	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
 
@@ -679,7 +618,7 @@ int srvScanTimestep(stream_t *streamptr)
 	      streamptr->ntsteps = streamptr->rtsteps + 1;
 	      break;
 	    }
-	  recsize = fileGetPos(fileID) - recpos;
+	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
 
 	  srvInqHeader(srvp, header);
 
@@ -702,9 +641,7 @@ int srvScanTimestep(stream_t *streamptr)
 	      taxis->vdate = vdate;
 	      taxis->vtime = vtime;
 	    }
-	  /*
-	  srvCmpRecord(streamptr, tsID, nrecs, recpos, param, rlevel, rxsize, rysize);
-	  */
+
 	  compVar.param  = param;
           compVar.level  = rlevel;
 	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
@@ -716,7 +653,7 @@ int srvScanTimestep(stream_t *streamptr)
 		      tsID, recID,
 		      streamptr->tsteps[tsID].records[recID].param, param,
 		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
-	      Error("Invalid, unsupported or inconsistent record structure");
+	      Error("Invalid, unsupported or inconsistent record structure!");
 	    }
 
 	  streamptr->tsteps[tsID].records[recID].position = recpos;
@@ -754,7 +691,8 @@ int srvScanTimestep(stream_t *streamptr)
 
 int srvInqTimestep(stream_t *streamptr, int tsID)
 {
-  int ntsteps, nrecs;
+  long ntsteps;
+  int nrecs;
 
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
@@ -766,7 +704,7 @@ int srvInqTimestep(stream_t *streamptr, int tsID)
   while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
     ntsteps = srvScanTimestep(streamptr);
 
-  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
+  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID )
     {
       nrecs = 0;
     }
diff --git a/libcdi/src/stream_srv.h b/libcdi/src/stream_srv.h
index 5989808..3d776ba 100644
--- a/libcdi/src/stream_srv.h
+++ b/libcdi/src/stream_srv.h
@@ -9,10 +9,10 @@ int    srvInqContents(stream_t *streamptr);
 int    srvInqTimestep(stream_t *streamptr, int tsID);
 
 int    srvInqRecord(stream_t *streamptr, int *varID, int *levelID);
-int    srvDefRecord(stream_t *streamptr);
-int    srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-int    srvReadRecord(stream_t *streamptr, double *data, int *nmiss);
-int    srvWriteRecord(stream_t *streamptr, const double *data);
+void   srvDefRecord(stream_t *streamptr);
+void   srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void   srvReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void   srvWriteRecord(stream_t *streamptr, const double *data);
 
 void   srvReadVarDP (stream_t *streamptr, int varID,       double *data, int *nmiss);
 void   srvWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/libcdi/src/swap.c b/libcdi/src/swap.c
index df759b2..cb3259f 100644
--- a/libcdi/src/swap.c
+++ b/libcdi/src/swap.c
@@ -2,6 +2,7 @@
 #  include "config.h"
 #endif
 
+#include <inttypes.h>
 #include <stdio.h>
 
 #include "error.h"
@@ -9,52 +10,28 @@
 
 void swap4byte(void *ptr, size_t size)
 {
-  INT32 *ptrtmp;
-  int nval;
+  int32_t *ptrtmp = ptr;
 
-  nval = size;
-  if ( nval < 0 ) nval = 0;
-  ptrtmp = (INT32 *) ptr;
-
-  if ( sizeof(INT32) == 4 )
-    {
-      while ( nval-- )
-	{
-	  *ptrtmp = (((*ptrtmp >> 24) & 0x00ff) | ((*ptrtmp & 0x00ff) << 24) |
-		     ((*ptrtmp >>  8) & 0xff00) | ((*ptrtmp & 0xff00) <<  8));
-	  ptrtmp++;
-	}
-    }
+  if (sizeof (int32_t) == 4)
+    for (size_t i = 0; i < size; ++i)
+      ptrtmp[i] = (((ptrtmp[i] >> 24) & 0x00ff) | ((ptrtmp[i] & 0x00ff) << 24) |
+                   ((ptrtmp[i] >>  8) & 0xff00) | ((ptrtmp[i] & 0xff00) <<  8));
   else
-    {
-      Error("not implemented for %d byte data", sizeof(INT32));
-    }
+    Error("not implemented for %d byte data", sizeof(int32_t));
 }
 
 void swap8byte(void *ptr, size_t size)
 {
-  INT64 *ptrtmp;
-  int nval;
-
-  nval = size;
-  if ( nval < 0 ) nval = 0;
-  ptrtmp = (INT64 *) ptr;
-
-  if ( sizeof(INT64) == 8 )
-    {
-      while ( nval-- )
-	{
-	  *ptrtmp = (((*ptrtmp >> 56) & 0x000000ff) | ((*ptrtmp & 0x000000ff) << 56) |
-		     ((*ptrtmp >> 40) & 0x0000ff00) | ((*ptrtmp & 0x0000ff00) << 40) |
-		     ((*ptrtmp >> 24) & 0x00ff0000) | ((*ptrtmp & 0x00ff0000) << 24) |
-		     ((*ptrtmp >>  8) & 0xff000000) | ((*ptrtmp & 0xff000000) <<  8));
-	  ptrtmp++;
-	}
-    }
+  int64_t *ptrtmp = ptr;
+
+  if (sizeof (int64_t) == 8)
+    for (size_t i = 0; i < size; ++i)
+      ptrtmp[i] = (((ptrtmp[i] >> 56) & 0x000000ff) | ((ptrtmp[i] & 0x000000ff) << 56) |
+                   ((ptrtmp[i] >> 40) & 0x0000ff00) | ((ptrtmp[i] & 0x0000ff00) << 40) |
+                   ((ptrtmp[i] >> 24) & 0x00ff0000) | ((ptrtmp[i] & 0x00ff0000) << 24) |
+                   ((ptrtmp[i] >>  8) & 0xff000000) | ((ptrtmp[i] & 0xff000000) <<  8));
   else
-    {
-      Error("not implemented for %d byte data", sizeof(INT64));
-    }
+    Error("not implemented for %d byte data", sizeof(int64_t));
 }
 /*
  * Local Variables:
diff --git a/libcdi/src/table.c b/libcdi/src/table.c
index 33daaaf..5a2728b 100644
--- a/libcdi/src/table.c
+++ b/libcdi/src/table.c
@@ -3,6 +3,8 @@
 #endif
 
 #include <ctype.h>
+#include <stddef.h>
+#include <string.h>
 
 #include "dmemory.h"
 #include "cdi.h"
@@ -22,13 +24,13 @@
 
 typedef struct
 {
-  int    used;  
+  int    used;
   PAR   *pars;
   int    npars;
   int    modelID;
   int    number;
   char  *name;
-} 
+}
 PARTAB;
 
 static PARTAB parTable[MAX_TABLE];
@@ -38,8 +40,8 @@ static int  ParTableInit = 0;
 
 static char *tablePath = NULL;
 
-void tableDefModelID(int tableID, int modelID);
-void tableDefNum(int tableID, int tablenum);
+static void tableDefModelID(int tableID, int modelID);
+static void tableDefNum(int tableID, int tablenum);
 
 
 void tableDefEntry(int tableID, int id, const char *name,
@@ -47,30 +49,40 @@ void tableDefEntry(int tableID, int id, const char *name,
 {
   int item;
 
+  if ( tableID >= 0 && tableID < MAX_TABLE && parTable[tableID].used) { } else
+    Error("Invalid table ID %d", tableID);
   item = parTable[tableID].npars++;
   parTable[tableID].pars[item].id       = id;
+  parTable[tableID].pars[item].dupflags = 0;
   parTable[tableID].pars[item].name     = NULL;
   parTable[tableID].pars[item].longname = NULL;
   parTable[tableID].pars[item].units    = NULL;
 
-  if ( name )
-    if ( strlen(name) > 0 )
+  if ( name && strlen(name) > 0 )
+    {
       parTable[tableID].pars[item].name     = strdupx(name);
-  if ( longname )
-    if ( strlen(longname) > 0 )
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_NAME;
+    }
+  if ( longname && strlen(longname) > 0 )
+    {
       parTable[tableID].pars[item].longname = strdupx(longname);
-  if ( units )
-    if ( strlen(units) > 0 )
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_LONGNAME;
+    }
+  if ( units && strlen(units) > 0 )
+    {
       parTable[tableID].pars[item].units    = strdupx(units);
+      parTable[tableID].pars[item].dupflags |= TABLE_DUP_UNITS;
+    }
 }
 
-void tableLink(int tableID, PAR *pars, int npars)
+static void tableLink(int tableID, const PAR *pars, int npars)
 {
   int item;
 
   for ( item = 0; item < npars; item++ )
     {
       parTable[tableID].pars[item].id       = pars[item].id;
+      parTable[tableID].pars[item].dupflags = 0;
       parTable[tableID].pars[item].name     = pars[item].name;
       parTable[tableID].pars[item].longname = pars[item].longname;
       parTable[tableID].pars[item].units    = pars[item].units;
@@ -79,7 +91,7 @@ void tableLink(int tableID, PAR *pars, int npars)
   parTable[tableID].npars = npars;
 }
 
-void parTableInitEntry(int tableID)
+static void parTableInitEntry(int tableID)
 {
   parTable[tableID].used    = 0;
   parTable[tableID].pars    = NULL;
@@ -89,7 +101,7 @@ void parTableInitEntry(int tableID)
   parTable[tableID].name    = NULL;
 }
 
-void tableGetPath(void)
+static void tableGetPath(void)
 {
   char *path;
 
@@ -101,17 +113,38 @@ void tableGetPath(void)
   */
 }
 
-void parTableInit(void)
+static void parTableFinalize(void)
+{
+  for (int tableID = 0; tableID < MAX_TABLE; ++tableID)
+    if (parTable[tableID].used)
+      {
+        int npars = parTable[tableID].npars;
+        for (int item = 0; item < npars; ++item)
+          {
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_NAME)
+              free((void *)parTable[tableID].pars[item].name);
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_LONGNAME)
+              free((void *)parTable[tableID].pars[item].longname);
+            if (parTable[tableID].pars[item].dupflags & TABLE_DUP_UNITS)
+              free((void *)parTable[tableID].pars[item].units);
+          }
+        free(parTable[tableID].pars);
+        free(parTable[tableID].name);
+      }
+}
+
+static void parTableInit(void)
 {
   ParTableInit = 1;
 
+  atexit(parTableFinalize);
   if ( cdiPartabIntern )
     tableDefault();
 
   tableGetPath();
 }
 
-int tableNewEntry()
+static int tableNewEntry()
 {
   int tableID = 0;
   static int init = 0;
@@ -140,21 +173,18 @@ int tableNewEntry()
   return (tableID);
 }
 
-int decodeForm1(char *pline, char *name, char *longname, char *units)
+static int
+decodeForm1(char *pline, char *name, char *longname, char *units)
 {
-  /* Format 1 : code name add mult longname [units] */
-  double add, mult;
-  int level;
   char *pstart, *pend;
-  long len;
 
   /* FIXME: parse success isn't verified */
-  level = strtol(pline, &pline, 10);
+  /* long level =  */strtol(pline, &pline, 10);
   while ( isspace((int) *pline) ) pline++;
 
   pstart = pline;
   while ( ! (isspace((int) *pline) || *pline == 0) ) pline++;
-  len = pline - pstart;
+  size_t len = (size_t)(pline - pstart);
   if ( len > 0 )
     {
       memcpy(name, pstart, len);
@@ -166,10 +196,11 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
   len = strlen(pline);
   if ( len == 0 ) return (0);
 
+  /* Format 1 : code name add mult longname [units] */
   /* FIXME: successful parse isn't verified */
-  add  = strtod(pline, &pline);
+  /* double add  =  */strtod(pline, &pline);
   /* FIXME: successful parse isn't verified */
-  mult = strtod(pline, &pline);
+  /* double mult =  */strtod(pline, &pline);
 
   while ( isspace((int) *pline) ) pline++;
 
@@ -183,7 +214,7 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
       else
 	pend = pstart + len;
       while ( isspace((int) *pend) ) pend--;
-      len = pend - pstart + 1;
+      len = (size_t)(pend - pstart + 1);
       if ( len > 0 )
 	{
 	  memcpy(longname, pstart, len);
@@ -198,7 +229,7 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
 	  if ( ! pend ) return (0);
 	  pend--;
 	  while ( isspace((int) *pend) ) pend--;
-	  len = pend - pstart + 1;
+	  len = (size_t)(pend - pstart + 1);
 	  if ( len > 0 )
 	    {
 	      memcpy(units, pstart, len);
@@ -210,40 +241,46 @@ int decodeForm1(char *pline, char *name, char *longname, char *units)
   return (0);
 }
 
-int decodeForm2(char *pline, char *name, char *longname, char *units)
+static int
+decodeForm2(char *pline, char *name, char *longname, char *units)
 {
   /* Format 2 : code | name | longname | units */
   char *pend;
-  long len;
+  size_t len;
 
   pline = strchr(pline, '|');
   pline++;
 
   while ( isspace((int) *pline) ) pline++;
-  pend = strchr(pline, '|');
-  if ( ! pend )
+  if (*pline != '|')
     {
-      pend = pline;
-      while ( ! isspace((int) *pend) ) pend++;
-      len = pend - pline;
-      if ( len > 0 )
-	{
-	  memcpy(name, pline, len);
-	  name[len] = 0;
-	}
-      return (0);
+      pend = strchr(pline, '|');
+      if ( ! pend )
+        {
+          pend = pline;
+          while ( ! isspace((int) *pend) ) pend++;
+          len = (size_t)(pend - pline);
+          if ( len > 0 )
+            {
+              memcpy(name, pline, len);
+              name[len] = 0;
+            }
+          return (0);
+        }
+      else
+        {
+          pend--;
+          while ( isspace((int) *pend) ) pend--;
+          len = (size_t)(pend - pline + 1);
+          if ( len > 0 )
+            {
+              memcpy(name, pline, len);
+              name[len] = 0;
+            }
+        }
     }
   else
-    {
-      pend--;
-      while ( isspace((int) *pend) ) pend--;
-      len = pend - pline + 1;
-      if ( len > 0 )
-	{
-	  memcpy(name, pline, len);
-	  name[len] = 0;
-	}
-    }
+    name[0] = '\0';
 
   pline = strchr(pline, '|');
   pline++;
@@ -252,7 +289,7 @@ int decodeForm2(char *pline, char *name, char *longname, char *units)
   if ( !pend ) pend = strchr(pline, 0);
   pend--;
   while ( isspace((int) *pend) ) pend--;
-  len = pend - pline + 1;
+  len = (size_t)(pend - pline + 1);
   if ( len > 0 )
     {
       memcpy(longname, pline, len);
@@ -268,9 +305,9 @@ int decodeForm2(char *pline, char *name, char *longname, char *units)
       if ( !pend ) pend = strchr(pline, 0);
       pend--;
       while ( isspace((int) *pend) ) pend--;
-      len = pend - pline + 1;
+      ptrdiff_t len = pend - pline + 1;
       if ( len < 0 ) len = 0;
-      memcpy(units, pline, len);
+      memcpy(units, pline, (size_t)len);
       units[len] = 0;
     }
 
@@ -281,7 +318,6 @@ int tableRead(const char *tablefile)
 {
   char line[1024], *pline;
   int lnr = 0;
-  long len;
   int id;
   char name[256], longname[256], units[256];
   int tableID = UNDEFID;
@@ -300,7 +336,7 @@ int tableRead(const char *tablefile)
 
   while ( fgets(line, 1023, tablefp) )
     {
-      len = strlen(line);
+      size_t len = strlen(line);
       if ( line[len-1] == '\n' ) line[len-1] = '\0';
       lnr++;
       id       = CDI_UNDEFID;
@@ -336,7 +372,7 @@ int tableRead(const char *tablefile)
   return (tableID);
 }
 
-int tableFromEnv(int modelID, int tablenum)
+static int tableFromEnv(int modelID, int tablenum)
 {
   int tableID = UNDEFID;
   char tablename[256] = {'\0'};
@@ -347,7 +383,7 @@ int tableFromEnv(int modelID, int tablenum)
       strcpy(tablename, modelInqNamePtr(modelID));
       if ( tablenum )
 	{
-	  int len = strlen(tablename);
+	  size_t len = strlen(tablename);
 	  sprintf(tablename+len, "_%03d", tablenum);
 	}
       tablenamefound = 1;
@@ -362,7 +398,7 @@ int tableFromEnv(int modelID, int tablenum)
 	      strcpy(tablename, institutInqNamePtr(instID));
 	      if ( tablenum )
 		{
-		  int len = strlen(tablename);
+		  size_t len = strlen(tablename);
 		  sprintf(tablename+len, "_%03d", tablenum);
 		}
 	      tablenamefound = 1;
@@ -372,7 +408,7 @@ int tableFromEnv(int modelID, int tablenum)
 
   if ( tablenamefound )
     {
-      int lenp = 0, lenf;
+      size_t lenp = 0, lenf;
       char *tablefile = NULL;
       if ( tablePath )
 	lenp = strlen(tablePath);
@@ -407,7 +443,7 @@ int tableFromEnv(int modelID, int tablenum)
 int tableInq(int modelID, int tablenum, const char *tablename)
 {
   int tableID = UNDEFID;
-  int modelID2 = UNDEFID, i, len;
+  int modelID2 = UNDEFID;
   char tablefile[256] = {'\0'};
 
   if ( ! ParTableInit ) parTableInit();
@@ -438,12 +474,12 @@ int tableInq(int modelID, int tablenum, const char *tablename)
       for ( tableID = 0; tableID < MAX_TABLE; tableID++ )
 	{
 	  if ( parTable[tableID].used )
-	    {	  
+	    {
 	      if ( parTable[tableID].modelID == modelID &&
 		   parTable[tableID].number  == tablenum ) break;
 	    }
 	}
-  
+
       if ( tableID == MAX_TABLE ) tableID = UNDEFID;
 
       if ( tableID == UNDEFID )
@@ -453,8 +489,8 @@ int tableInq(int modelID, int tablenum, const char *tablename)
 	      if ( modelInqNamePtr(modelID) )
 		{
 		  strcpy(tablefile, modelInqNamePtr(modelID));
-		  len = strlen(tablefile);
-		  for ( i = 0; i < len; i++)
+		  size_t len = strlen(tablefile);
+		  for ( size_t i = 0; i < len; i++)
 		    if ( tablefile[i] == '.' ) tablefile[i] = '\0';
 		  modelID2 = modelInq(-1, 0, tablefile);
 		}
@@ -498,7 +534,7 @@ int tableDef(int modelID, int tablenum, const char *tablename)
 
       parTable[tableID].modelID = modelID;
       parTable[tableID].number  = tablenum;
-      if ( tablename ) 
+      if ( tablename )
 	parTable[tableID].name = strdupx(tablename);
 
       parTable[tableID].pars = (PAR *) malloc(MAX_PARS * sizeof(PAR));
@@ -507,12 +543,12 @@ int tableDef(int modelID, int tablenum, const char *tablename)
   return (tableID);
 }
 
-void tableDefModelID(int tableID, int modelID)
+static void tableDefModelID(int tableID, int modelID)
 {
   parTable[tableID].modelID = modelID;
 }
 
-void tableDefNum(int tableID, int tablenum)
+static void tableDefNum(int tableID, int tablenum)
 {
   parTable[tableID].number  = tablenum;
 }
@@ -537,7 +573,7 @@ int tableInqModel(int tableID)
   return (modelID);
 }
 
-void partabCheckID(int item)
+static void partabCheckID(int item)
 {
   if ( item < 0 || item >= parTableSize )
     Error("item %d undefined!", item);
@@ -565,12 +601,10 @@ char *tableInqNamePtr(int tableID)
 void tableWrite(const char *ptfile, int tableID)
 {
   int item, npars;
-  int lenname, lenlname, lenunits;
-  int maxname = 4, maxlname = 10, maxunits = 2;
+  size_t maxname = 4, maxlname = 10, maxunits = 2;
   FILE *ptfp;
   int tablenum, modelID, instID = CDI_UNDEFID;
   int center = 0, subcenter = 0;
-  char *name, *longname, *units;
   char *instnameptr = NULL, *modelnameptr = NULL;
 
   if ( CDI_Debug )
@@ -592,19 +626,19 @@ void tableWrite(const char *ptfile, int tableID)
     {
       if ( parTable[tableID].pars[item].name )
 	{
-	  lenname  = strlen(parTable[tableID].pars[item].name);
+	  size_t lenname = strlen(parTable[tableID].pars[item].name);
 	  if ( lenname  > maxname )  maxname  = lenname;
 	}
 
       if ( parTable[tableID].pars[item].longname )
 	{
-	  lenlname = strlen(parTable[tableID].pars[item].longname);
+	  size_t lenlname = strlen(parTable[tableID].pars[item].longname);
 	  if ( lenlname > maxlname ) maxlname = lenlname;
 	}
 
       if ( parTable[tableID].pars[item].units )
 	{
-	  lenunits = strlen(parTable[tableID].pars[item].units);
+	  size_t lenunits = strlen(parTable[tableID].pars[item].units);
 	  if ( lenunits > maxunits ) maxunits = lenunits;
 	}
     }
@@ -646,23 +680,23 @@ void tableWrite(const char *ptfile, int tableID)
   fprintf(ptfp, "# The format of each record is:\n");
   fprintf(ptfp, "#\n");
   fprintf(ptfp, "# id | %-*s | %-*s | %-*s\n",
-	  maxname,  "name",
-	  maxlname, "title",
-	  maxunits, "units");
+	  (int)maxname,  "name",
+	  (int)maxlname, "title",
+	  (int)maxunits, "units");
 	  
   for ( item = 0; item < npars; item++)
     {
-      name = parTable[tableID].pars[item].name;
-      longname = parTable[tableID].pars[item].longname;
-      units = parTable[tableID].pars[item].units;
+      const char *name = parTable[tableID].pars[item].name,
+        *longname = parTable[tableID].pars[item].longname,
+        *units = parTable[tableID].pars[item].units;
       if ( name == NULL ) name = " ";
       if ( longname == NULL ) longname = " ";
       if ( units == NULL ) units = " ";
       fprintf(ptfp, "%4d | %-*s | %-*s | %-*s\n",
 	      parTable[tableID].pars[item].id,
-	      maxname, name,
-	      maxlname, longname,
-	      maxunits, units);
+	      (int)maxname, name,
+	      (int)maxlname, longname,
+	      (int)maxunits, units);
     }
 
   fclose(ptfp);
@@ -671,16 +705,22 @@ void tableWrite(const char *ptfile, int tableID)
 
 void tableWriteC(const char *filename, int tableID)
 {
-  char chelp[] = "";
+  FILE *ptfp = fopen(filename, "w");
+  if (!ptfp)
+    Error("failed to open file \"%s\"!", filename);
+  if ( CDI_Debug )
+    Message("write parameter table %d to %s", tableID, filename);
+  tableFWriteC(ptfp, tableID);
+  fclose(ptfp);
+}
+
+void tableFWriteC(FILE *ptfp, int tableID)
+{
+  const char chelp[] = "";
   int item, npars;
-  int lenname, lenlname, lenunits;
-  int maxname = 0, maxlname = 0, maxunits = 0;
+  size_t maxname = 0, maxlname = 0, maxunits = 0;
   char tablename[256];
-  int len, i;
-  FILE *ptfp;
 
-  if ( CDI_Debug )
-    Message("write parameter table %d to %s", tableID, filename);
 
   if ( tableID == UNDEFID )
     {
@@ -690,73 +730,59 @@ void tableWriteC(const char *filename, int tableID)
 
   partabCheckID(tableID);
 
-  ptfp = fopen(filename, "w");
-
   npars = parTable[tableID].npars;
 
   for ( item = 0; item < npars; item++)
     {
       if ( parTable[tableID].pars[item].name )
 	{
-	  lenname  = strlen(parTable[tableID].pars[item].name);
+	  size_t lenname = strlen(parTable[tableID].pars[item].name);
 	  if ( lenname  > maxname )  maxname  = lenname;
 	}
 
       if ( parTable[tableID].pars[item].longname )
 	{
-	  lenlname = strlen(parTable[tableID].pars[item].longname);
+	  size_t lenlname = strlen(parTable[tableID].pars[item].longname);
 	  if ( lenlname > maxlname ) maxlname = lenlname;
 	}
 
       if ( parTable[tableID].pars[item].units )
 	{
-	  lenunits = strlen(parTable[tableID].pars[item].units);
+	  size_t lenunits = strlen(parTable[tableID].pars[item].units);
 	  if ( lenunits > maxunits ) maxunits = lenunits;
 	}
     }
 
-  strcpy(tablename, parTable[tableID].name);
-  len = strlen(tablename);
-
-  for ( i = 0; i < len; i++ )
-    if ( tablename[i] == '.' ) tablename[i] = '_';
+  strncpy(tablename, parTable[tableID].name, sizeof (tablename));
+  tablename[sizeof (tablename) - 1] = '\0';
+  {
+    size_t len = strlen(tablename);
+    for (size_t i = 0; i < len; i++ )
+      if ( tablename[i] == '.' ) tablename[i] = '_';
+  }
+  fprintf(ptfp, "static const PAR %s[] = {\n", tablename);
 
-  fprintf(ptfp, "static PAR %s[] = {\n", tablename);
-	  
   for ( item = 0; item < npars; item++ )
     {
-      len = strlen(parTable[tableID].pars[item].name);
-      fprintf(ptfp, "  {%4d, \"%s\", %-*s",
+      size_t len = strlen(parTable[tableID].pars[item].name),
+        llen = parTable[tableID].pars[item].longname
+        ? strlen(parTable[tableID].pars[item].longname) : 0,
+        ulen = parTable[tableID].pars[item].units
+        ? strlen(parTable[tableID].pars[item].units) : 0;
+      fprintf(ptfp, "  {%4d, 0, \"%s\", %-*s%c%s%s, %-*s%c%s%s %-*s},\n",
 	      parTable[tableID].pars[item].id,
-	      parTable[tableID].pars[item].name, maxname-len, chelp);
-
-      if ( parTable[tableID].pars[item].longname )
-	len = strlen(parTable[tableID].pars[item].longname);
-      else
-	len = 0;
-
-      if ( len == 0 )
-	fprintf(ptfp, " NULL, %-*s", maxlname-3, chelp);
-      else
-	fprintf(ptfp, "\"%s\", %-*s",
-		parTable[tableID].pars[item].longname, maxlname-len, chelp);
-
-      if ( parTable[tableID].pars[item].units )
-	len = strlen(parTable[tableID].pars[item].units);
-      else
-	len = 0;
-
-      if ( len == 0 )
-	fprintf(ptfp, " NULL %-*s},\n", maxunits-3, chelp);
-      else
-	fprintf(ptfp, "\"%s\" %-*s},\n",
-		parTable[tableID].pars[item].units,
-		maxunits-len, chelp);
+	      parTable[tableID].pars[item].name, (int)(maxname-len), chelp,
+              llen?'"':' ',
+              llen?parTable[tableID].pars[item].longname:"NULL",
+              llen?"\"":"",
+              (int)(maxlname-(llen?llen:3)), chelp,
+              ulen?'"':' ',
+              ulen?parTable[tableID].pars[item].units:"NULL",
+              ulen?"\"":"",
+              (int)(maxunits-(ulen?ulen:3)), chelp);
     }
 
   fprintf(ptfp, "};\n\n");
-
-  fclose(ptfp);
 }
 
 
@@ -818,9 +844,9 @@ int tableInqParName(int tableID, int code, char *varname)
 }
 
 
-char *tableInqParNamePtr(int tableID, int code)
+const char *tableInqParNamePtr(int tableID, int code)
 {
-  char *name = NULL;
+  const char *name = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -840,9 +866,9 @@ char *tableInqParNamePtr(int tableID, int code)
 }
 
 
-char *tableInqParLongnamePtr(int tableID, int code)
+const char *tableInqParLongnamePtr(int tableID, int code)
 {
-  char *longname = NULL;
+  const char *longname = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -862,9 +888,9 @@ char *tableInqParLongnamePtr(int tableID, int code)
 }
 
 
-char *tableInqParUnitsPtr(int tableID, int code)
+const char *tableInqParUnitsPtr(int tableID, int code)
 {
-  char *units = NULL;
+  const char *units = NULL;
   int item, npars;
 
   if ( tableID != UNDEFID )
@@ -891,6 +917,9 @@ int tableInqParLongname(int tableID, int code, char *longname)
 
   npars = parTable[tableID].npars;
 
+  if ( ((tableID >= 0) & (tableID < MAX_TABLE)) | (tableID == UNDEFID) ) { } else
+    Error("Invalid table ID %d", tableID);
+
   if ( tableID == UNDEFID )
     {
       err = 1;
@@ -920,6 +949,9 @@ int tableInqParUnits(int tableID, int code, char *units)
 
   npars = parTable[tableID].npars;
 
+  if ( ((tableID >= 0) & (tableID < MAX_TABLE)) | (tableID == UNDEFID) ) { } else
+    Error("Invalid table ID %d", tableID);
+
   if ( tableID == UNDEFID )
     {
       err = 1;
@@ -963,23 +995,6 @@ void tableInqPar(int tableID, int code, char *name, char *longname, char *units)
     }
 }
 
-
-int parInqID(int tableID, int code)
-{
-  int item, npars;
-
-  npars = parTable[tableID].npars;
-
-  for ( item = 0; item < npars; item++ )
-    {
-      if ( parTable[tableID].pars[item].id == code ) break;
-    }
-
-  if ( item == npars ) item = -1;
-
-  return (item);
-}
-
 int tableInqNumber(void)
 {
   if ( ! ParTableInit ) parTableInit();
diff --git a/libcdi/src/table.h b/libcdi/src/table.h
index 0d189d4..f7f5f14 100644
--- a/libcdi/src/table.h
+++ b/libcdi/src/table.h
@@ -1,1230 +1,1230 @@
 #ifndef _TABLE_H
 #define _TABLE_H
 
-static PAR echam4[] = {
-  {   4, "precip",      "total precipitation",                      "m/s"      },
-  {  34, "low_cld",     "low cloud",                                 NULL      },
-  {  35, "mid_cld",     "mid cloud",                                 NULL      },
-  {  36, "hih_cld",     "high cloud",                                NULL      },
-  { 129, "geosp",       "surface geopotential (orography)",         "m^2/s^2"  },
-  { 130, "t",           "temperature",                              "K"        },
-  { 131, "u",           "u-velocity",                               "m/s"      },
-  { 132, "v",           "v-velocity",                               "m/s"      },
-  { 133, "sq",          "specific humidity",                        "kg/kg"    },
-  { 134, "aps",         "Surface pressure",                         "Pa"       },
-  { 135, "omega",       "vertical velocity",                        "Pa/s"     },
-  { 138, "svo",         "vorticity",                                "1/s"      },
-  { 139, "ts",          "surface temperature",                      "K"        },
-  { 140, "ws",          "soil wetness",                             "m"        },
-  { 141, "sn",          "snow depth",                               "m"        },
-  { 142, "aprl",        "large scale precipitation",                "m/s"      },
-  { 143, "aprc",        "convective  precipitation",                "m/s"      },
-  { 144, "aprs",        "snow fall",                                "m/s"      },
-  { 145, "vdis",        "boundary layer dissipation",               "W/m^2"    },
-  { 146, "ahfs",        "surface sensible heat flux",               "W/m^2"    },
-  { 147, "ahfl",        "surface latent heat flux",                 "W/m^2"    },
-  { 148, "stream",      "streamfunction",                           "m^2/s"    },
-  { 149, "velopot",     "velocity potential",                       "m^2/s"    },
-  { 151, "slp",         "mean sea level pressure",                  "Pa"       },
-  { 152, "lsp",         "log surface pressure",                      NULL      },
-  { 153, "sx",          "liquid water content",                     "kg/kg"    },
-  { 155, "sd",          "divergence",                               "1/s"      },
-  { 156, "geopoth",     "geopotential height",                      "m"        },
-  { 157, "rhumidity",   "relative humidity",                        "fraction" },
-  { 158, "var158",      "tendency of surface pressure",             "Pa/s"     },
-  { 159, "ustar3",      "ustar3",                                   "m^3/s^3"  },
-  { 160, "runoff",      "surface runoff",                           "m/s"      },
-  { 161, "alwc",        "liquid water content",                     "kg/kg"    },
-  { 162, "aclc",        "cloud cover",                              "fraction" },
-  { 163, "aclcv",       "total cloud cover",                        "fraction" },
-  { 164, "aclcov",      "total cloud cover",                        "fraction" },
-  { 165, "u10",         "10m u-velocity",                           "m/s"      },
-  { 166, "v10",         "10m v-velocity",                           "m/s"      },
-  { 167, "temp2",       "2m temperature",                           "K"        },
-  { 168, "dew2",        "2m dew point temperature",                 "K"        },
-  { 169, "tsurf",       "surface temperature",                      "K"        },
-  { 170, "td",          "deep soil temperature",                    "K"        },
-  { 171, "wind10",      "10m windspeed",                            "m/s"      },
-  { 172, "slm",         "land sea mask",                            "fraction" },
-  { 173, "az0",         "surface roughness length",                 "m"        },
-  { 174, "alb",         "surface background albedo",                "fraction" },
-  { 175, "albedo",      "surface albedo",                           "fraction" },
-  { 176, "srads",       "net surface solar radiation",              "W/m^2"    },
-  { 177, "trads",       "net surface thermal radiation",            "W/m^2"    },
-  { 178, "srad0",       "net top solar radiation",                  "W/m^2"    },
-  { 179, "trad0",       "top thermal radiation (OLR)",              "W/m^2"    },
-  { 180, "ustr",        "surface u-stress",                         "Pa"       },
-  { 181, "vstr",        "surface v-stress",                         "Pa"       },
-  { 182, "evap",        "surface evaporation",                      "m/s"      },
-  { 183, "tdcl",        "soil temperature",                         "K"        },
-  { 185, "srafs",       "net surf. solar radiation   (clear sky)",  "W/m^2"    },
-  { 186, "trafs",       "net surf. thermal radiation (clear sky)",  "W/m^2"    },
-  { 187, "sraf0",       "net top solar radiation     (clear sky)",  "W/m^2"    },
-  { 188, "traf0",       "net top thermal radiation   (clear sky)",  "W/m^2"    },
-  { 189, "sclfs",       "surface solar cloud forcing",              "W/m^2"    },
-  { 190, "tclfs",       "surface thermal cloud forcing",            "W/m^2"    },
-  { 191, "sclf0",       "top solar cloud forcing",                  "W/m^2"    },
-  { 192, "tclf0",       "top thermal cloud forcing",                "W/m^2"    },
-  { 193, "wl",          "skin reservoir content",                   "m"        },
-  { 194, "wlm1",        "skin reservoir content of plants",         "m"        },
-  { 195, "ustrgw",      "u-gravity wave stress",                    "Pa"       },
-  { 196, "vstrgw",      "v-gravity wave stress",                    "Pa"       },
-  { 197, "vdisgw",      "gravity wave dissipation",                 "W/m^2"    },
-  { 198, "vgrat",       "vegetation ratio",                         "fraction" },
-  { 199, "varor",       "orographic variance",                      "m^2"      },
-  { 200, "vlt",         "leaf area index",                           NULL      },
-  { 201, "t2max",       "maximum 2m-temperature",                   "K"        },
-  { 202, "t2min",       "minimum 2m-temperature",                   "K"        },
-  { 203, "srad0u",      "top solar radiation upward",               "W/m^2"    },
-  { 204, "sradsu",      "surface solar radiation upward",           "W/m^2"    },
-  { 205, "tradsu",      "surface thermal radiation upward",         "W/m^2"    },
-  { 206, "tsn",         "snow temperature",                         "K"        },
-  { 207, "td3",         "soil temperature 3",                       "K"        },
-  { 208, "td4",         "soil temperature 4",                       "K"        },
-  { 209, "td5",         "soil temperature 5",                       "K"        },
-  { 210, "seaice",      "sea ice cover",                            "fraction" },
-  { 211, "siced",       "sea ice depth",                            "m"        },
-  { 212, "forest",      "vegetation type",                          "fraction" },
-  { 213, "teff",        "(effective) sea-ice skin temperature",     "K"        },
-  { 214, "tsmax",       "maximum surface temperature",              "K"        },
-  { 215, "tsmin",       "minimum surface temperature",              "K"        },
-  { 216, "wimax",       "maximum 10m-wind speed",                   "m/s"      },
-  { 217, "topmax",      "maximum height of convective cloud tops",  "Pa"       },
-  { 218, "snmel",       "snow melt",                                "m/s"      },
-  { 219, "runtoc",      "surface runoff into ocean",                 NULL      },
-  { 220, "tslin",       "land: residual surface heat budget",       "W/m^2"    },
-  { 221, "dsnac",       "snow depth change",                        "m/s"      },
-  { 222, "alwcac",      "liquid water content",                     "kg/kg"    },
-  { 223, "aclcac",      "cloud cover",                              "fraction" },
-  { 224, "tke",         "turbulent kinetic energy",                  NULL      },
-  { 225, "tkem1",       "turbulent kinetic energy (t-1)",            NULL      },
-  { 226, "fao",         "FAO data set (soil data flags)",            NULL      },
-  { 227, "rgcgn",       "heat capacity of soil",                     NULL      },
-  { 228, "sodif",       "soil diffusivity",                          NULL      },
-  { 229, "wsmx",        "field capacity of soil",                   "m"        },
-  { 230, "qvi",         "vertically integrated specific humidity",  "kg/m^2"   },
-  { 231, "alwcvi",      "vertically integrated liquid water cont.", "kg/m^2"   },
-  { 232, "glac",        "glacier mask",                             "fraction" },
-  { 233, "runlnd",      "surface runoff not running into ocean",     NULL      },
-  { 259, "windspeed",   "windspeed (sqrt(u^2+v^2))",                 NULL      },
-  { 260, "precip",      "total precipitation",                      "m/s"      },
-  { 261, "net_top",     "total top radiation",                       NULL      },
-  { 262, "net_bot",     "total surface radiation",                   NULL      },
-  { 263, "net_heat",    "net surface heat flux",                     NULL      },
-  { 264, "net_water",   "total surface water",                       NULL      },
-  { 268, "sw_atm",       NULL,                                       NULL      },
-  { 269, "lw_atm",       NULL,                                       NULL      },
-  { 270, "net_atm",      NULL,                                       NULL      },
-  { 271, "surf_runoff", "surface runoff",                            NULL      },
-  { 275, "fresh_water",  NULL,                                       NULL      },
+static const PAR echam4[] = {
+  {   4, 0, "precip",      "total precipitation",                      "m/s"      },
+  {  34, 0, "low_cld",     "low cloud",                                 NULL      },
+  {  35, 0, "mid_cld",     "mid cloud",                                 NULL      },
+  {  36, 0, "hih_cld",     "high cloud",                                NULL      },
+  { 129, 0, "geosp",       "surface geopotential (orography)",         "m^2/s^2"  },
+  { 130, 0, "t",           "temperature",                              "K"        },
+  { 131, 0, "u",           "u-velocity",                               "m/s"      },
+  { 132, 0, "v",           "v-velocity",                               "m/s"      },
+  { 133, 0, "sq",          "specific humidity",                        "kg/kg"    },
+  { 134, 0, "aps",         "Surface pressure",                         "Pa"       },
+  { 135, 0, "omega",       "vertical velocity",                        "Pa/s"     },
+  { 138, 0, "svo",         "vorticity",                                "1/s"      },
+  { 139, 0, "ts",          "surface temperature",                      "K"        },
+  { 140, 0, "ws",          "soil wetness",                             "m"        },
+  { 141, 0, "sn",          "snow depth",                               "m"        },
+  { 142, 0, "aprl",        "large scale precipitation",                "m/s"      },
+  { 143, 0, "aprc",        "convective  precipitation",                "m/s"      },
+  { 144, 0, "aprs",        "snow fall",                                "m/s"      },
+  { 145, 0, "vdis",        "boundary layer dissipation",               "W/m^2"    },
+  { 146, 0, "ahfs",        "surface sensible heat flux",               "W/m^2"    },
+  { 147, 0, "ahfl",        "surface latent heat flux",                 "W/m^2"    },
+  { 148, 0, "stream",      "streamfunction",                           "m^2/s"    },
+  { 149, 0, "velopot",     "velocity potential",                       "m^2/s"    },
+  { 151, 0, "slp",         "mean sea level pressure",                  "Pa"       },
+  { 152, 0, "lsp",         "log surface pressure",                      NULL      },
+  { 153, 0, "sx",          "liquid water content",                     "kg/kg"    },
+  { 155, 0, "sd",          "divergence",                               "1/s"      },
+  { 156, 0, "geopoth",     "geopotential height",                      "m"        },
+  { 157, 0, "rhumidity",   "relative humidity",                        "fraction" },
+  { 158, 0, "var158",      "tendency of surface pressure",             "Pa/s"     },
+  { 159, 0, "ustar3",      "ustar3",                                   "m^3/s^3"  },
+  { 160, 0, "runoff",      "surface runoff",                           "m/s"      },
+  { 161, 0, "alwc",        "liquid water content",                     "kg/kg"    },
+  { 162, 0, "aclc",        "cloud cover",                              "fraction" },
+  { 163, 0, "aclcv",       "total cloud cover",                        "fraction" },
+  { 164, 0, "aclcov",      "total cloud cover",                        "fraction" },
+  { 165, 0, "u10",         "10m u-velocity",                           "m/s"      },
+  { 166, 0, "v10",         "10m v-velocity",                           "m/s"      },
+  { 167, 0, "temp2",       "2m temperature",                           "K"        },
+  { 168, 0, "dew2",        "2m dew point temperature",                 "K"        },
+  { 169, 0, "tsurf",       "surface temperature",                      "K"        },
+  { 170, 0, "td",          "deep soil temperature",                    "K"        },
+  { 171, 0, "wind10",      "10m windspeed",                            "m/s"      },
+  { 172, 0, "slm",         "land sea mask",                            "fraction" },
+  { 173, 0, "az0",         "surface roughness length",                 "m"        },
+  { 174, 0, "alb",         "surface background albedo",                "fraction" },
+  { 175, 0, "albedo",      "surface albedo",                           "fraction" },
+  { 176, 0, "srads",       "net surface solar radiation",              "W/m^2"    },
+  { 177, 0, "trads",       "net surface thermal radiation",            "W/m^2"    },
+  { 178, 0, "srad0",       "net top solar radiation",                  "W/m^2"    },
+  { 179, 0, "trad0",       "top thermal radiation (OLR)",              "W/m^2"    },
+  { 180, 0, "ustr",        "surface u-stress",                         "Pa"       },
+  { 181, 0, "vstr",        "surface v-stress",                         "Pa"       },
+  { 182, 0, "evap",        "surface evaporation",                      "m/s"      },
+  { 183, 0, "tdcl",        "soil temperature",                         "K"        },
+  { 185, 0, "srafs",       "net surf. solar radiation   (clear sky)",  "W/m^2"    },
+  { 186, 0, "trafs",       "net surf. thermal radiation (clear sky)",  "W/m^2"    },
+  { 187, 0, "sraf0",       "net top solar radiation     (clear sky)",  "W/m^2"    },
+  { 188, 0, "traf0",       "net top thermal radiation   (clear sky)",  "W/m^2"    },
+  { 189, 0, "sclfs",       "surface solar cloud forcing",              "W/m^2"    },
+  { 190, 0, "tclfs",       "surface thermal cloud forcing",            "W/m^2"    },
+  { 191, 0, "sclf0",       "top solar cloud forcing",                  "W/m^2"    },
+  { 192, 0, "tclf0",       "top thermal cloud forcing",                "W/m^2"    },
+  { 193, 0, "wl",          "skin reservoir content",                   "m"        },
+  { 194, 0, "wlm1",        "skin reservoir content of plants",         "m"        },
+  { 195, 0, "ustrgw",      "u-gravity wave stress",                    "Pa"       },
+  { 196, 0, "vstrgw",      "v-gravity wave stress",                    "Pa"       },
+  { 197, 0, "vdisgw",      "gravity wave dissipation",                 "W/m^2"    },
+  { 198, 0, "vgrat",       "vegetation ratio",                         "fraction" },
+  { 199, 0, "varor",       "orographic variance",                      "m^2"      },
+  { 200, 0, "vlt",         "leaf area index",                           NULL      },
+  { 201, 0, "t2max",       "maximum 2m-temperature",                   "K"        },
+  { 202, 0, "t2min",       "minimum 2m-temperature",                   "K"        },
+  { 203, 0, "srad0u",      "top solar radiation upward",               "W/m^2"    },
+  { 204, 0, "sradsu",      "surface solar radiation upward",           "W/m^2"    },
+  { 205, 0, "tradsu",      "surface thermal radiation upward",         "W/m^2"    },
+  { 206, 0, "tsn",         "snow temperature",                         "K"        },
+  { 207, 0, "td3",         "soil temperature 3",                       "K"        },
+  { 208, 0, "td4",         "soil temperature 4",                       "K"        },
+  { 209, 0, "td5",         "soil temperature 5",                       "K"        },
+  { 210, 0, "seaice",      "sea ice cover",                            "fraction" },
+  { 211, 0, "siced",       "sea ice depth",                            "m"        },
+  { 212, 0, "forest",      "vegetation type",                          "fraction" },
+  { 213, 0, "teff",        "(effective) sea-ice skin temperature",     "K"        },
+  { 214, 0, "tsmax",       "maximum surface temperature",              "K"        },
+  { 215, 0, "tsmin",       "minimum surface temperature",              "K"        },
+  { 216, 0, "wimax",       "maximum 10m-wind speed",                   "m/s"      },
+  { 217, 0, "topmax",      "maximum height of convective cloud tops",  "Pa"       },
+  { 218, 0, "snmel",       "snow melt",                                "m/s"      },
+  { 219, 0, "runtoc",      "surface runoff into ocean",                 NULL      },
+  { 220, 0, "tslin",       "land: residual surface heat budget",       "W/m^2"    },
+  { 221, 0, "dsnac",       "snow depth change",                        "m/s"      },
+  { 222, 0, "alwcac",      "liquid water content",                     "kg/kg"    },
+  { 223, 0, "aclcac",      "cloud cover",                              "fraction" },
+  { 224, 0, "tke",         "turbulent kinetic energy",                  NULL      },
+  { 225, 0, "tkem1",       "turbulent kinetic energy (t-1)",            NULL      },
+  { 226, 0, "fao",         "FAO data set (soil data flags)",            NULL      },
+  { 227, 0, "rgcgn",       "heat capacity of soil",                     NULL      },
+  { 228, 0, "sodif",       "soil diffusivity",                          NULL      },
+  { 229, 0, "wsmx",        "field capacity of soil",                   "m"        },
+  { 230, 0, "qvi",         "vertically integrated specific humidity",  "kg/m^2"   },
+  { 231, 0, "alwcvi",      "vertically integrated liquid water cont.", "kg/m^2"   },
+  { 232, 0, "glac",        "glacier mask",                             "fraction" },
+  { 233, 0, "runlnd",      "surface runoff not running into ocean",     NULL      },
+  { 259, 0, "windspeed",   "windspeed (sqrt(u^2+v^2))",                 NULL      },
+  { 260, 0, "precip",      "total precipitation",                      "m/s"      },
+  { 261, 0, "net_top",     "total top radiation",                       NULL      },
+  { 262, 0, "net_bot",     "total surface radiation",                   NULL      },
+  { 263, 0, "net_heat",    "net surface heat flux",                     NULL      },
+  { 264, 0, "net_water",   "total surface water",                       NULL      },
+  { 268, 0, "sw_atm",       NULL,                                       NULL      },
+  { 269, 0, "lw_atm",       NULL,                                       NULL      },
+  { 270, 0, "net_atm",      NULL,                                       NULL      },
+  { 271, 0, "surf_runoff", "surface runoff",                            NULL      },
+  { 275, 0, "fresh_water",  NULL,                                       NULL      },
 };
 
-static PAR echam5[] = {
-  {   4, "precip",     "total precipitation",                       "kg/m^2s" },
-  {  79, "swnirac",    "net surface NIR flux acc.",                 "W/m^2"   },
-  {  80, "swdifnirac", "fraction of diffuse NIR acc.",              "W/m^2"   },
-  {  81, "swvisac",    "net surface visible flux acc.",             "W/m^2"   },
-  {  82, "swdifvisac", "fraction of diffuse visible acc.",          "W/m^2"   },
-  {  83, "ocu",        "ocean eastw. velocity (coupled mode)",      "m/s"     },
-  {  84, "ocv",        "ocean northw. velocity (coupled mode)",     "m/s"     },
-  {  85, "tradl",      "net LW radiation 200mb",                    "W/m^2"   },
-  {  86, "sradl",      "net SW radiation 200mb",                    "W/m^2"   },
-  {  87, "trafl",      "net LW radiation 200mb (clear sky)",        "W/m^2"   },
-  {  88, "srafl",      "net SW radiation 200mb (clear sky)",        "W/m^2"   },
-  {  89, "amlcorac",   "mixed layer flux correction",               "W/m^2"   },
-  {  90, "amlheatac",  "mixed layer heat content",                  "J/m^2"   },
-  {  91, "trfliac",    "net LW radiation over ice",                 "W/m^2"   },
-  {  92, "trflwac",    "net LW radiation over water",               "W/m^2"   },
-  {  93, "trfllac",    "net LW radiation over land",                "W/m^2"   },
-  {  94, "sofliac",    "net SW radiation over ice",                 "W/m^2"   },
-  {  95, "soflwac",    "net SW radiation over water",               "W/m^2"   },
-  {  96, "sofllac",    "net SW radiation over land",                "W/m^2"   },
-  {  97, "friac",      "ice cover (fraction of grid box)",           NULL     },
-  { 102, "tsi",        "surface temperature of ice",                "K"       },
-  { 103, "tsw",        "surface temperature of water",              "K"       },
-  { 104, "ustri",      "zonal      wind stress over ice",           "Pa"      },
-  { 105, "vstri",      "meridional wind stress over ice",           "Pa"      },
-  { 106, "ustrw",      "zonal      wind stress over water",         "Pa"      },
-  { 107, "vstrw",      "meridional wind stress over water",         "Pa"      },
-  { 108, "ustrl",      "zonal      wind stress over land",          "Pa"      },
-  { 109, "vstrl",      "meridional wind stress over land",          "Pa"      },
-  { 110, "ahfliac",    "latent heat flux over ice",                 "W/m^2"   },
-  { 111, "ahflwac",    "latent heat flux over water",               "W/m^2"   },
-  { 112, "ahfllac",    "latent heat flux over land",                "W/m^2"   },
-  { 113, "evapiac",    "evaporation over ice",                      "kg/m^2s" },
-  { 114, "evapwac",    "evaporation over water",                    "kg/m^2s" },
-  { 115, "evaplac",    "evaporation over land",                     "kg/m^2s" },
-  { 116, "az0i",       "roughness length over ice",                 "m"       },
-  { 117, "az0w",       "roughness length over water",               "m"       },
-  { 118, "az0l",       "roughness length over land",                "m"       },
-  { 119, "ahfsiac",    "sensible heat flux over ice",               "W/m^2"   },
-  { 120, "ahfswac",    "sensible heat flux over water",             "W/m^2"   },
-  { 121, "ahfslac",    "sensible heat flux over land",              "W/m^2"   },
-  { 122, "alsoi",      "albedo of ice",                              NULL     },
-  { 123, "alsow",      "albedo of water",                            NULL     },
-  { 124, "alsol",      "albedo of land",                             NULL     },
-  { 125, "ahfice",     "conductive heat flux through ice",          "W/m^2"   },
-  { 126, "qres",       "residual heat flux for melting sea ice",    "W/m^2"   },
-  { 127, "alake",      "lake fraction",                              NULL     },
-  { 128, "rintop",     "low level inversion",                        NULL     },
-  { 129, "geosp",      "surface geopotential (orography)",          "m^2/s^2" },
-  { 130, "t",          "temperature",                               "K"       },
-  { 131, "u",          "u-velocity",                                "m/s"     },
-  { 132, "v",          "v-velocity",                                "m/s"     },
-  { 133, "q",          "specific humidity",                         "kg/kg"   },
-  { 134, "aps",        "surface pressure",                          "Pa"      },
-  { 135, "omega",      "vertical velocity",                         "Pa/s"    },
-  { 136, "acdnc",      "cloud droplet number concentration",        "1/m^3"   },
-  { 137, "apmeb",      "(P-E) error",                               "kg/m^2s" },
-  { 138, "svo",        "vorticity",                                 "1/s"     },
-  { 139, "tslm1",      "surface temperature of land",               "K"       },
-  { 140, "ws",         "soil wetness",                              "m"       },
-  { 141, "sn",         "water equivalent snow depth",               "m"       },
-  { 142, "aprl",       "large scale precipitation",                 "kg/m^2s" },
-  { 143, "aprc",       "convective  precipitation",                 "kg/m^2s" },
-  { 144, "aprs",       "snow fall",                                 "kg/m^2s" },
-  { 145, "vdis",       "boundary layer dissipation",                "W/m^2"   },
-  { 146, "ahfs",       "sensible heat flux",                        "W/m^2"   },
-  { 147, "ahfl",       "latent heat flux",                          "W/m^2"   },
-  { 148, "stream",     "streamfunction",                            "m^2/s"   },
-  { 149, "velopot",    "velocity potential",                        "m^2/s"   },
-  { 150, "xivi",       "vertically integrated cloud ice",           "kg/m^2"  },
-  { 151, "slp",        "mean sea level pressure",                   "Pa"      },
-  { 152, "lsp",        "log surface pressure",                       NULL     },
-  { 153, "xl",         "cloud water",                               "kg/kg"   },
-  { 154, "xi",         "cloud ice",                                 "kg/kg"   },
-  { 155, "sd",         "divergence",                                "1/s"     },
-  { 156, "geopoth",    "geopotential height",                       "m"       },
-  { 157, "rhumidity",  "relative humidity",                          NULL     },
-  { 159, "wind10w",    "10m windspeed over water",                  "m/s"     },
-  { 160, "runoff",     "surface runoff and drainage",               "kg/m^2s" },
-  { 161, "drain",      "drainage",                                  "kg/m^2s" },
-  { 162, "aclc",       "cloud cover",                                NULL     },
-  { 164, "aclcov",     "total cloud cover",                          NULL     },
-  { 165, "u10",        "10m u-velocity",                            "m/s"     },
-  { 166, "v10",        "10m v-velocity",                            "m/s"     },
-  { 167, "temp2",      "2m temperature",                            "K"       },
-  { 168, "dew2",       "2m dew point temperature",                  "K"       },
-  { 169, "tsurf",      "surface temperature",                       "K"       },
-  { 170, "xvar",       "variance of total water amount",            "kg/kg"   },
-  { 171, "wind10",     "10m windspeed",                             "m/s"     },
-  { 172, "slm",        "land sea mask (1. = land, 0. = sea/lakes)",  NULL     },
-  { 173, "az0",        "roughness length",                          "m"       },
-  { 174, "alb",        "surface background albedo",                  NULL     },
-  { 175, "albedo",     "surface albedo",                             NULL     },
-  { 176, "srads",      "net surface SW radiation",                  "W/m^2"   },
-  { 177, "trads",      "net surface LW radiation",                  "W/m^2"   },
-  { 178, "srad0",      "net top SW radiation",                      "W/m^2"   },
-  { 179, "trad0",      "net top LW radiation (-OLR)",               "W/m^2"   },
-  { 180, "ustr",       "u-stress",                                  "Pa"      },
-  { 181, "vstr",       "v-stress",                                  "Pa"      },
-  { 182, "evap",       "evaporation",                               "kg/m^2s" },
-  { 183, "xskew",      "skewness of total water amount qv+qi+ql",    NULL     },
-  { 184, "srad0d",     "top incoming SW radiation",                 "W/m^2"   },
-  { 185, "srafs",      "net surface SW radiation (clear sky)",      "W/m^2"   },
-  { 186, "trafs",      "net surface LW radiation (clear sky)",      "W/m^2"   },
-  { 187, "sraf0",      "net top SW radiation   (clear sky)",        "W/m^2"   },
-  { 188, "traf0",      "net top LW radiation   (clear sky)",        "W/m^2"   },
-  { 189, "sclfs",      "net surface SW cloud forcing (176-185)",    "W/m^2"   },
-  { 190, "tclfs",      "net surface LW cloud forcing (177-186)",    "W/m^2"   },
-  { 191, "sclf0",      "net SW top cloud forcing (178-187)",        "W/m^2"   },
-  { 192, "tclf0",      "net LW top cloud forcing (179-188)",        "W/m^2"   },
-  { 193, "wl",         "skin reservoir content",                    "m"       },
-  { 194, "slf",        "fractional land cover",                      NULL     },
-  { 195, "ustrgw",     "u-gravity wave stress",                     "Pa"      },
-  { 196, "vstrgw",     "v-gravity wave stress",                     "Pa"      },
-  { 197, "vdisgw",     "gravity wave dissipation",                  "W/m^2"   },
-  { 198, "vgrat",      "vegetation ratio",                           NULL     },
-  { 199, "orostd",     "orographic standard deviation",             "m"       },
-  { 200, "vlt",        "leaf area index",                            NULL     },
-  { 201, "t2max",      "maximum 2m-temperature",                    "K"       },
-  { 202, "t2min",      "minimum 2m-temperature",                    "K"       },
-  { 203, "srad0u",     "top SW radiation upward",                   "W/m^2"   },
-  { 204, "sradsu",     "surface SW radiation upward",               "W/m^2"   },
-  { 205, "tradsu",     "surface LW radiation upward",               "W/m^2"   },
-  { 206, "grndflux",   "surface ground heat flux",                   NULL     },
-  { 207, "tsoil",      "deep soil temperatures (5 layers)",         "K"       },
-  { 208, "ahfcon",     "conductive heat flux through ice",          "W/m^2"   },
-  { 209, "ahfres",     "res. heat flux for melting ice",            "W/m^2"   },
-  { 210, "seaice",     "ice cover (fraction of ice+water)",          NULL     },
-  { 211, "siced",      "ice thickness",                             "m"       },
-  { 212, "forest",     "forest fraction",                            NULL     },
-  { 213, "gld",        "glacier thickness",                         "m"       },
-  { 214, "sni",        "water equivalent of snow on ice",           "m"       },
-  { 215, "rogl",       "glacier runoff",                            "kg/m^2s" },
-  { 216, "wimax",      "maximum 10m-wind speed",                    "m/s"     },
-  { 217, "topmax",     "maximum height of convective cloud tops",   "Pa"      },
-  { 218, "snmel",      "snow melt",                                 "kg/m^2s" },
-  { 219, "runtoc",     "surface runoff into ocean",                 "kg/m^2s" },
-  { 220, "runlnd",     "surface runoff not running into ocean",     "kg/m^2s" },
-  { 221, "apmegl",     "P-E over land ice",                         "kg/m^2s" },
-  { 222, "snacl",      "snow accumulation over land",               "kg/m^2s" },
-  { 223, "aclcac",     "cloud cover",                                NULL     },
-  { 224, "tke",        "turbulent kinetic energy",                  "m^2/s^2" },
-  { 225, "tkem1",      "turbulent kinetic energy (t-1)",            "m^2/s^2" },
-  { 226, "fao",        "FAO data set (soil data flags) 0...5",       NULL     },
-  { 227, "rgcgn",      "heat capacity of soil",                      NULL     },
-  { 228, "sodif",      "soil diffusivity",                          "m^2/s"   },
-  { 229, "wsmx",       "field capacity of soil",                    "m"       },
-  { 230, "qvi",        "vertically integrated water vapor",         "kg/m^2"  },
-  { 231, "xlvi",       "vertically integrated cloud water",         "kg/m^2"  },
-  { 232, "glac",       "fraction of land covered by glaciers",       NULL     },
-  { 233, "snc",        "snow depth at the canopy",                  "m"       },
-  { 234, "rtype",      "type of convection",                        "0...3"   },
-  { 235, "abso4",      "anthropogenic sulfur burden",               "kg/m^2"  },
-  { 236, "ao3",        "ipcc ozone",                                "kg/m^2"  },
-  { 237, "tropo",      "WMO defined tropopause height",             "Pa"      },
-  { 259, "windspeed",  "windspeed (sqrt(u^2+v^2))",                 "m/s"     },
-  { 260, "precip",     "total precipitation  (142+143)",            "kg/m^2s" },
-  { 261, "net_top",    "total top radiation  (178+179)",            "W/m^2"   },
-  { 262, "net_bot",    "total surface radiation (176+177)",         "W/m^2"   },
-  { 272, "mastrfu",    "mass stream function",                      "kg/s"    },
+static const PAR echam5[] = {
+  {   4, 0, "precip",     "total precipitation",                       "kg/m^2s" },
+  {  79, 0, "swnirac",    "net surface NIR flux acc.",                 "W/m^2"   },
+  {  80, 0, "swdifnirac", "fraction of diffuse NIR acc.",              "W/m^2"   },
+  {  81, 0, "swvisac",    "net surface visible flux acc.",             "W/m^2"   },
+  {  82, 0, "swdifvisac", "fraction of diffuse visible acc.",          "W/m^2"   },
+  {  83, 0, "ocu",        "ocean eastw. velocity (coupled mode)",      "m/s"     },
+  {  84, 0, "ocv",        "ocean northw. velocity (coupled mode)",     "m/s"     },
+  {  85, 0, "tradl",      "net LW radiation 200mb",                    "W/m^2"   },
+  {  86, 0, "sradl",      "net SW radiation 200mb",                    "W/m^2"   },
+  {  87, 0, "trafl",      "net LW radiation 200mb (clear sky)",        "W/m^2"   },
+  {  88, 0, "srafl",      "net SW radiation 200mb (clear sky)",        "W/m^2"   },
+  {  89, 0, "amlcorac",   "mixed layer flux correction",               "W/m^2"   },
+  {  90, 0, "amlheatac",  "mixed layer heat content",                  "J/m^2"   },
+  {  91, 0, "trfliac",    "net LW radiation over ice",                 "W/m^2"   },
+  {  92, 0, "trflwac",    "net LW radiation over water",               "W/m^2"   },
+  {  93, 0, "trfllac",    "net LW radiation over land",                "W/m^2"   },
+  {  94, 0, "sofliac",    "net SW radiation over ice",                 "W/m^2"   },
+  {  95, 0, "soflwac",    "net SW radiation over water",               "W/m^2"   },
+  {  96, 0, "sofllac",    "net SW radiation over land",                "W/m^2"   },
+  {  97, 0, "friac",      "ice cover (fraction of grid box)",           NULL     },
+  { 102, 0, "tsi",        "surface temperature of ice",                "K"       },
+  { 103, 0, "tsw",        "surface temperature of water",              "K"       },
+  { 104, 0, "ustri",      "zonal      wind stress over ice",           "Pa"      },
+  { 105, 0, "vstri",      "meridional wind stress over ice",           "Pa"      },
+  { 106, 0, "ustrw",      "zonal      wind stress over water",         "Pa"      },
+  { 107, 0, "vstrw",      "meridional wind stress over water",         "Pa"      },
+  { 108, 0, "ustrl",      "zonal      wind stress over land",          "Pa"      },
+  { 109, 0, "vstrl",      "meridional wind stress over land",          "Pa"      },
+  { 110, 0, "ahfliac",    "latent heat flux over ice",                 "W/m^2"   },
+  { 111, 0, "ahflwac",    "latent heat flux over water",               "W/m^2"   },
+  { 112, 0, "ahfllac",    "latent heat flux over land",                "W/m^2"   },
+  { 113, 0, "evapiac",    "evaporation over ice",                      "kg/m^2s" },
+  { 114, 0, "evapwac",    "evaporation over water",                    "kg/m^2s" },
+  { 115, 0, "evaplac",    "evaporation over land",                     "kg/m^2s" },
+  { 116, 0, "az0i",       "roughness length over ice",                 "m"       },
+  { 117, 0, "az0w",       "roughness length over water",               "m"       },
+  { 118, 0, "az0l",       "roughness length over land",                "m"       },
+  { 119, 0, "ahfsiac",    "sensible heat flux over ice",               "W/m^2"   },
+  { 120, 0, "ahfswac",    "sensible heat flux over water",             "W/m^2"   },
+  { 121, 0, "ahfslac",    "sensible heat flux over land",              "W/m^2"   },
+  { 122, 0, "alsoi",      "albedo of ice",                              NULL     },
+  { 123, 0, "alsow",      "albedo of water",                            NULL     },
+  { 124, 0, "alsol",      "albedo of land",                             NULL     },
+  { 125, 0, "ahfice",     "conductive heat flux through ice",          "W/m^2"   },
+  { 126, 0, "qres",       "residual heat flux for melting sea ice",    "W/m^2"   },
+  { 127, 0, "alake",      "lake fraction",                              NULL     },
+  { 128, 0, "rintop",     "low level inversion",                        NULL     },
+  { 129, 0, "geosp",      "surface geopotential (orography)",          "m^2/s^2" },
+  { 130, 0, "t",          "temperature",                               "K"       },
+  { 131, 0, "u",          "u-velocity",                                "m/s"     },
+  { 132, 0, "v",          "v-velocity",                                "m/s"     },
+  { 133, 0, "q",          "specific humidity",                         "kg/kg"   },
+  { 134, 0, "aps",        "surface pressure",                          "Pa"      },
+  { 135, 0, "omega",      "vertical velocity",                         "Pa/s"    },
+  { 136, 0, "acdnc",      "cloud droplet number concentration",        "1/m^3"   },
+  { 137, 0, "apmeb",      "(P-E) error",                               "kg/m^2s" },
+  { 138, 0, "svo",        "vorticity",                                 "1/s"     },
+  { 139, 0, "tslm1",      "surface temperature of land",               "K"       },
+  { 140, 0, "ws",         "soil wetness",                              "m"       },
+  { 141, 0, "sn",         "water equivalent snow depth",               "m"       },
+  { 142, 0, "aprl",       "large scale precipitation",                 "kg/m^2s" },
+  { 143, 0, "aprc",       "convective  precipitation",                 "kg/m^2s" },
+  { 144, 0, "aprs",       "snow fall",                                 "kg/m^2s" },
+  { 145, 0, "vdis",       "boundary layer dissipation",                "W/m^2"   },
+  { 146, 0, "ahfs",       "sensible heat flux",                        "W/m^2"   },
+  { 147, 0, "ahfl",       "latent heat flux",                          "W/m^2"   },
+  { 148, 0, "stream",     "streamfunction",                            "m^2/s"   },
+  { 149, 0, "velopot",    "velocity potential",                        "m^2/s"   },
+  { 150, 0, "xivi",       "vertically integrated cloud ice",           "kg/m^2"  },
+  { 151, 0, "slp",        "mean sea level pressure",                   "Pa"      },
+  { 152, 0, "lsp",        "log surface pressure",                       NULL     },
+  { 153, 0, "xl",         "cloud water",                               "kg/kg"   },
+  { 154, 0, "xi",         "cloud ice",                                 "kg/kg"   },
+  { 155, 0, "sd",         "divergence",                                "1/s"     },
+  { 156, 0, "geopoth",    "geopotential height",                       "m"       },
+  { 157, 0, "rhumidity",  "relative humidity",                          NULL     },
+  { 159, 0, "wind10w",    "10m windspeed over water",                  "m/s"     },
+  { 160, 0, "runoff",     "surface runoff and drainage",               "kg/m^2s" },
+  { 161, 0, "drain",      "drainage",                                  "kg/m^2s" },
+  { 162, 0, "aclc",       "cloud cover",                                NULL     },
+  { 164, 0, "aclcov",     "total cloud cover",                          NULL     },
+  { 165, 0, "u10",        "10m u-velocity",                            "m/s"     },
+  { 166, 0, "v10",        "10m v-velocity",                            "m/s"     },
+  { 167, 0, "temp2",      "2m temperature",                            "K"       },
+  { 168, 0, "dew2",       "2m dew point temperature",                  "K"       },
+  { 169, 0, "tsurf",      "surface temperature",                       "K"       },
+  { 170, 0, "xvar",       "variance of total water amount",            "kg/kg"   },
+  { 171, 0, "wind10",     "10m windspeed",                             "m/s"     },
+  { 172, 0, "slm",        "land sea mask (1. = land, 0. = sea/lakes)",  NULL     },
+  { 173, 0, "az0",        "roughness length",                          "m"       },
+  { 174, 0, "alb",        "surface background albedo",                  NULL     },
+  { 175, 0, "albedo",     "surface albedo",                             NULL     },
+  { 176, 0, "srads",      "net surface SW radiation",                  "W/m^2"   },
+  { 177, 0, "trads",      "net surface LW radiation",                  "W/m^2"   },
+  { 178, 0, "srad0",      "net top SW radiation",                      "W/m^2"   },
+  { 179, 0, "trad0",      "net top LW radiation (-OLR)",               "W/m^2"   },
+  { 180, 0, "ustr",       "u-stress",                                  "Pa"      },
+  { 181, 0, "vstr",       "v-stress",                                  "Pa"      },
+  { 182, 0, "evap",       "evaporation",                               "kg/m^2s" },
+  { 183, 0, "xskew",      "skewness of total water amount qv+qi+ql",    NULL     },
+  { 184, 0, "srad0d",     "top incoming SW radiation",                 "W/m^2"   },
+  { 185, 0, "srafs",      "net surface SW radiation (clear sky)",      "W/m^2"   },
+  { 186, 0, "trafs",      "net surface LW radiation (clear sky)",      "W/m^2"   },
+  { 187, 0, "sraf0",      "net top SW radiation   (clear sky)",        "W/m^2"   },
+  { 188, 0, "traf0",      "net top LW radiation   (clear sky)",        "W/m^2"   },
+  { 189, 0, "sclfs",      "net surface SW cloud forcing (176-185)",    "W/m^2"   },
+  { 190, 0, "tclfs",      "net surface LW cloud forcing (177-186)",    "W/m^2"   },
+  { 191, 0, "sclf0",      "net SW top cloud forcing (178-187)",        "W/m^2"   },
+  { 192, 0, "tclf0",      "net LW top cloud forcing (179-188)",        "W/m^2"   },
+  { 193, 0, "wl",         "skin reservoir content",                    "m"       },
+  { 194, 0, "slf",        "fractional land cover",                      NULL     },
+  { 195, 0, "ustrgw",     "u-gravity wave stress",                     "Pa"      },
+  { 196, 0, "vstrgw",     "v-gravity wave stress",                     "Pa"      },
+  { 197, 0, "vdisgw",     "gravity wave dissipation",                  "W/m^2"   },
+  { 198, 0, "vgrat",      "vegetation ratio",                           NULL     },
+  { 199, 0, "orostd",     "orographic standard deviation",             "m"       },
+  { 200, 0, "vlt",        "leaf area index",                            NULL     },
+  { 201, 0, "t2max",      "maximum 2m-temperature",                    "K"       },
+  { 202, 0, "t2min",      "minimum 2m-temperature",                    "K"       },
+  { 203, 0, "srad0u",     "top SW radiation upward",                   "W/m^2"   },
+  { 204, 0, "sradsu",     "surface SW radiation upward",               "W/m^2"   },
+  { 205, 0, "tradsu",     "surface LW radiation upward",               "W/m^2"   },
+  { 206, 0, "grndflux",   "surface ground heat flux",                   NULL     },
+  { 207, 0, "tsoil",      "deep soil temperatures (5 layers)",         "K"       },
+  { 208, 0, "ahfcon",     "conductive heat flux through ice",          "W/m^2"   },
+  { 209, 0, "ahfres",     "res. heat flux for melting ice",            "W/m^2"   },
+  { 210, 0, "seaice",     "ice cover (fraction of ice+water)",          NULL     },
+  { 211, 0, "siced",      "ice thickness",                             "m"       },
+  { 212, 0, "forest",     "forest fraction",                            NULL     },
+  { 213, 0, "gld",        "glacier thickness",                         "m"       },
+  { 214, 0, "sni",        "water equivalent of snow on ice",           "m"       },
+  { 215, 0, "rogl",       "glacier runoff",                            "kg/m^2s" },
+  { 216, 0, "wimax",      "maximum 10m-wind speed",                    "m/s"     },
+  { 217, 0, "topmax",     "maximum height of convective cloud tops",   "Pa"      },
+  { 218, 0, "snmel",      "snow melt",                                 "kg/m^2s" },
+  { 219, 0, "runtoc",     "surface runoff into ocean",                 "kg/m^2s" },
+  { 220, 0, "runlnd",     "surface runoff not running into ocean",     "kg/m^2s" },
+  { 221, 0, "apmegl",     "P-E over land ice",                         "kg/m^2s" },
+  { 222, 0, "snacl",      "snow accumulation over land",               "kg/m^2s" },
+  { 223, 0, "aclcac",     "cloud cover",                                NULL     },
+  { 224, 0, "tke",        "turbulent kinetic energy",                  "m^2/s^2" },
+  { 225, 0, "tkem1",      "turbulent kinetic energy (t-1)",            "m^2/s^2" },
+  { 226, 0, "fao",        "FAO data set (soil data flags) 0...5",       NULL     },
+  { 227, 0, "rgcgn",      "heat capacity of soil",                      NULL     },
+  { 228, 0, "sodif",      "soil diffusivity",                          "m^2/s"   },
+  { 229, 0, "wsmx",       "field capacity of soil",                    "m"       },
+  { 230, 0, "qvi",        "vertically integrated water vapor",         "kg/m^2"  },
+  { 231, 0, "xlvi",       "vertically integrated cloud water",         "kg/m^2"  },
+  { 232, 0, "glac",       "fraction of land covered by glaciers",       NULL     },
+  { 233, 0, "snc",        "snow depth at the canopy",                  "m"       },
+  { 234, 0, "rtype",      "type of convection",                        "0...3"   },
+  { 235, 0, "abso4",      "anthropogenic sulfur burden",               "kg/m^2"  },
+  { 236, 0, "ao3",        "ipcc ozone",                                "kg/m^2"  },
+  { 237, 0, "tropo",      "WMO defined tropopause height",             "Pa"      },
+  { 259, 0, "windspeed",  "windspeed (sqrt(u^2+v^2))",                 "m/s"     },
+  { 260, 0, "precip",     "total precipitation  (142+143)",            "kg/m^2s" },
+  { 261, 0, "net_top",    "total top radiation  (178+179)",            "W/m^2"   },
+  { 262, 0, "net_bot",    "total surface radiation (176+177)",         "W/m^2"   },
+  { 272, 0, "mastrfu",    "mass stream function",                      "kg/s"    },
 };
 
-static PAR echam6[] = {
-  {   4, "precip",         "total precipitation",                       "kg m-2 s-1" },
-  {  34, "low_cld",        "low cloud",                                  NULL        },
-  {  35, "mid_cld",        "mid cloud",                                  NULL        },
-  {  36, "hih_cld",        "high cloud",                                 NULL        },
-  {  68, "fage",           "aging factor of snow on ice",                NULL        },
-  {  69, "snifrac",        "fraction of ice covered with snow",          NULL        },
-  {  70, "barefrac",       "bare ice fraction",                          NULL        },
-  {  71, "alsom",          "albedo of melt ponds",                       NULL        },
-  {  72, "alsobs",         "albedo of bare ice and snow",                NULL        },
-  {  73, "sicepdw",        "melt pond depth on sea-ice",                "m"          },
-  {  74, "sicepdi",        "ice thickness on melt pond",                "m"          },
-  {  75, "tsicepdi",       "ice temperature on frozen melt pond",       "K"          },
-  {  76, "sicepres",       "residual heat flux",                        "W m-2"      },
-  {  77, "ameltdepth",     "total melt pond depth",                     "m"          },
-  {  78, "ameltfrac",      "fractional area of melt ponds on sea-ice",   NULL        },
-  {  79, "albedo_vis_dir", "surface albedo visible range direct",        NULL        },
-  {  80, "albedo_nir_dir", "surface albedo NIR range direct",            NULL        },
-  {  81, "albedo_vis_dif", "surface albedo visible range diffuse",       NULL        },
-  {  82, "albedo_nir_dif", "surface albedo NIR range diffuse",           NULL        },
-  {  83, "ocu",            "ocean eastw. velocity (coupled mode)",      "m/s"        },
-  {  84, "ocv",            "ocean northw. velocity (coupled mode)",     "m/s"        },
-  {  85, "tradl",          "thermal radiation 200mb",                   "W m-2"      },
-  {  86, "sradl",          "solar radiation 200mb",                     "W m-2"      },
-  {  87, "trafl",          "thermal radiation 200mb (clear sky)",       "W m-2"      },
-  {  88, "srafl",          "solar radiation 200mb (clear sky)",         "W m-2"      },
-  {  89, "amlcorac",       "mixed layer flux correction",               "W m-2"      },
-  {  90, "amlheatac",      "mixed layer heat content",                  "J m-2"      },
-  {  91, "trfliac",        "LW flux over ice",                          "W m-2"      },
-  {  92, "trflwac",        "LW flux over water",                        "W m-2"      },
-  {  93, "trfllac",        "LW flux over land",                         "W m-2"      },
-  {  94, "sofliac",        "SW flux over ice",                          "W m-2"      },
-  {  95, "soflwac",        "SW flux over water",                        "W m-2"      },
-  {  96, "sofllac",        "SW flux over land",                         "W m-2"      },
-  {  97, "friac",          "ice cover (fraction of grid box)",           NULL        },
-  { 102, "tsi",            "surface temperature of ice",                "K"          },
-  { 103, "tsw",            "surface temperature of water",              "K"          },
-  { 104, "ustri",          "zonal      wind stress over ice",           "Pa"         },
-  { 105, "vstri",          "meridional wind stress over ice",           "Pa"         },
-  { 106, "ustrw",          "zonal      wind stress over water",         "Pa"         },
-  { 107, "vstrw",          "meridional wind stress over water",         "Pa"         },
-  { 108, "ustrl",          "zonal      wind stress over land",          "Pa"         },
-  { 109, "vstrl",          "meridional wind stress over land",          "Pa"         },
-  { 110, "ahfliac",        "latent heat flux over ice",                 "W m-2"      },
-  { 111, "ahflwac",        "latent heat flux over water",               "W m-2"      },
-  { 112, "ahfllac",        "latent heat flux over land",                "W m-2"      },
-  { 113, "evapiac",        "evaporation over ice",                      "kg m-2 s-1" },
-  { 114, "evapwac",        "evaporation over water",                    "kg m-2 s-1" },
-  { 115, "evaplac",        "evaporation over land",                     "kg m-2 s-1" },
-  { 116, "az0i",           "roughness length over ice",                 "m"          },
-  { 117, "az0w",           "roughness length over water",               "m"          },
-  { 118, "az0l",           "roughness length over land",                "m"          },
-  { 119, "ahfsiac",        "sensible heat flux over ice",               "W m-2"      },
-  { 120, "ahfswac",        "sensible heat flux over water",             "W m-2"      },
-  { 121, "ahfslac",        "sensible heat flux over land",              "W m-2"      },
-  { 122, "alsoi",          "albedo of ice",                              NULL        },
-  { 123, "alsow",          "albedo of water",                            NULL        },
-  { 124, "alsol",          "albedo of land",                             NULL        },
-  { 125, "ahfice",         "conductive heat flux",                      "W m-2"      },
-  { 126, "qres",           "residual heat flux for melting sea ice",    "W m-2"      },
-  { 127, "alake",          "lake fraction of grid box",                 "fraction"   },
-  { 128, "rintop",         "low level inversion",                        NULL        },
-  { 129, "geosp",          "surface geopotential (orography)",          "m^2/s^2"    },
-  { 130, "t",              "temperature",                               "K"          },
-  { 131, "u",              "u-velocity",                                "m/s"        },
-  { 132, "v",              "v-velocity",                                "m/s"        },
-  { 133, "q",              "specific humidity",                         "kg/kg"      },
-  { 134, "aps",            "surface pressure",                          "Pa"         },
-  { 135, "omega",          "vertical velocity",                         "Pa/s"       },
-  { 136, "acdnc",          "cloud droplet number concentration",        "1 m-3"      },
-  { 137, "apmeb",          "vert. integr. tendencies of water",         "kg m-2 s-1" },
-  { 138, "svo",            "vorticity",                                 "1/s"        },
-  { 139, "tslm1",          "surface temperature of land",               "K"          },
-  { 140, "ws",             "soil wetness",                              "m"          },
-  { 141, "sn",             "snow depth",                                "m"          },
-  { 142, "aprl",           "large scale precipitation",                 "kg m-2 s-1" },
-  { 143, "aprc",           "convective  precipitation",                 "kg m-2 s-1" },
-  { 144, "aprs",           "snow fall",                                 "kg m-2 s-1" },
-  { 145, "vdis",           "boundary layer dissipation",                "W m-2"      },
-  { 146, "ahfs",           "sensible heat flux",                        "W m-2"      },
-  { 147, "ahfl",           "latent heat flux",                          "W m-2"      },
-  { 148, "stream",         "streamfunction",                            "m^2/s"      },
-  { 149, "velopot",        "velocity potential",                        "m^2/s"      },
-  { 150, "xivi",           "vertically integrated cloud ice",           "kg m-2"     },
-  { 151, "slp",            "mean sea level pressure",                   "Pa"         },
-  { 152, "lsp",            "log surface pressure",                       NULL        },
-  { 153, "xl",             "cloud water",                               "kg/kg"      },
-  { 154, "xi",             "cloud ice",                                 "kg/kg"      },
-  { 155, "sd",             "divergence",                                "1/s"        },
-  { 156, "geopoth",        "geopotential height",                       "m"          },
-  { 157, "rhumidity",      "relative humidity",                         "fraction"   },
-  { 158, "var158",         "tendency of surface pressure",              "Pa/s"       },
-  { 159, "wind10w",        "10m windspeed over water",                  "m/s"        },
-  { 160, "runoff",         "surface runoff and drainage",               "kg m-2 s-1" },
-  { 161, "drain",          "drainage",                                  "kg m-2 s-1" },
-  { 162, "aclc",           "cloud cover",                                NULL        },
-  { 163, "aclcv",          "total cloud cover",                          NULL        },
-  { 164, "aclcov",         "total cloud cover (mean)",                   NULL        },
-  { 165, "u10",            "10m u-velocity",                            "m/s"        },
-  { 166, "v10",            "10m v-velocity",                            "m/s"        },
-  { 167, "temp2",          "2m temperature",                            "K"          },
-  { 168, "dew2",           "2m dew point temperature",                  "K"          },
-  { 169, "tsurf",          "surface temperature",                       "K"          },
-  { 170, "xvar",           "variance of total water amount qv+qi+ql",   "kg/kg"      },
-  { 171, "wind10",         "10m windspeed",                             "m/s"        },
-  { 172, "slm",            "land sea mask (1. = land, 0. = sea/lakes)",  NULL        },
-  { 173, "az0",            "roughness length",                          "m"          },
-  { 174, "alb",            "surface background albedo",                  NULL        },
-  { 175, "albedo",         "surface albedo",                             NULL        },
-  { 176, "srads",          "net surface solar radiation",               "W m-2"      },
-  { 177, "trads",          "net surface thermal radiation",             "W m-2"      },
-  { 178, "srad0",          "net top solar radiation",                   "W m-2"      },
-  { 179, "trad0",          "top thermal radiation (OLR)",               "W m-2"      },
-  { 180, "ustr",           "u-stress",                                  "Pa"         },
-  { 181, "vstr",           "v-stress",                                  "Pa"         },
-  { 182, "evap",           "evaporation",                               "kg m-2 s-1" },
-  { 183, "xskew",          "skewness of total water amount qv+qi+ql",    NULL        },
-  { 184, "srad0d",         "top incoming solar radiation",              "W m-2"      },
-  { 185, "srafs",          "net surf. solar radiation   (clear sky)",   "W m-2"      },
-  { 186, "trafs",          "net surf. thermal radiation (clear sky)",   "W m-2"      },
-  { 187, "sraf0",          "net top solar radiation     (clear sky)",   "W m-2"      },
-  { 188, "traf0",          "net top thermal radiation   (clear sky)",   "W m-2"      },
-  { 189, "sclfs",          "surface solar cloud forcing",               "W m-2"      },
-  { 190, "tclfs",          "surface thermal cloud forcing",             "W m-2"      },
-  { 191, "sclf0",          "SW top cloud forcing (178-187)",            "W m-2"      },
-  { 192, "tclf0",          "LW top cloud forcing (179-188)",            "W m-2"      },
-  { 193, "wl",             "skin reservoir content",                    "m"          },
-  { 194, "slf",            "sea land fraction",                          NULL        },
-  { 195, "ustrgw",         "u-gravity wave stress",                     "Pa"         },
-  { 196, "vstrgw",         "v-gravity wave stress",                     "Pa"         },
-  { 197, "vdisgw",         "gravity wave dissipation",                  "W m-2"      },
-  { 198, "vgrat",          "vegetation ratio",                           NULL        },
-  { 199, "orostd",         "orographic standard deviation",             "m"          },
-  { 200, "vlt",            "leaf area index",                            NULL        },
-  { 201, "t2max",          "maximum 2m-temperature",                    "K"          },
-  { 202, "t2min",          "minimum 2m-temperature",                    "K"          },
-  { 203, "srad0u",         "top solar radiation upward",                "W m-2"      },
-  { 204, "sradsu",         "surface solar radiation upward",            "W m-2"      },
-  { 205, "tradsu",         "surface thermal radiation upward",          "W m-2"      },
-  { 206, "grndflux",       "surface ground heat flux",                   NULL        },
-  { 207, "tsoil",          "deep soil temperatures (5 layers)",         "K"          },
-  { 208, "ahfcon",         "conductive heat flux through ice",          "W m-2"      },
-  { 209, "ahfres",         "melting of ice",                            "W m-2"      },
-  { 210, "seaice",         "ice cover (fraction of 1-SLM)",              NULL        },
-  { 211, "siced",          "ice depth",                                 "m"          },
-  { 212, "forest",         "forest fraction",                            NULL        },
-  { 213, "gld",            "glacier depth",                             "m"          },
-  { 214, "sni",            "water equivalent of snow on ice",           "m"          },
-  { 215, "rogl",           "glacier runoff",                            "kg m-2 s-1" },
-  { 216, "wimax",          "maximum 10m-wind speed",                    "m/s"        },
-  { 217, "topmax",         "maximum height of convective cloud tops",   "Pa"         },
-  { 218, "snmel",          "snow melt",                                 "kg m-2 s-1" },
-  { 219, "runtoc",         "surface runoff into ocean",                 "kg m-2 s-1" },
-  { 220, "runlnd",         "surface runoff not running into ocean",     "kg m-2 s-1" },
-  { 221, "apmegl",         "P-E over land ice",                         "kg m-2 s-1" },
-  { 222, "snacl",          "snow accumulation over land",               "kg m-2 s-1" },
-  { 223, "aclcac",         "cloud cover",                                NULL        },
-  { 224, "tke",            "turbulent kinetic energy",                  "m^2/s^2"    },
-  { 225, "tkem1",          "turbulent kinetic energy (t-1)",            "m^2/s^2"    },
-  { 226, "fao",            "FAO data set (soil data flags)",            "0...5"      },
-  { 227, "rgcgn",          "heat capacity of soil",                      NULL        },
-  { 228, "sodif",          "diffusivity of soil and land ice",          "m^2/s"      },
-  { 229, "wsmx",           "field capacity of soil",                    "m"          },
-  { 230, "qvi",            "vertically integrated water vapor",         "kg m-2"     },
-  { 231, "xlvi",           "vertically integrated cloud water",         "kg m-2"     },
-  { 232, "glac",           "fraction of land covered by glaciers",       NULL        },
-  { 233, "snc",            "snow depth at the canopy",                  "m"          },
-  { 234, "rtype",          "type of convection",                        "0...3"      },
-  { 235, "abso4",          "antropogenic sulfur burden",                "kg m-2"     },
-  { 236, "ao3",            "ipcc ozone",                                "kg m-2"     },
-  { 237, "tropo",          "WMO defined tropopause height",             "Pa"         },
-  { 259, "windspeed",      "windspeed (sqrt(u^2+v^2))",                 "m/s"        },
-  { 260, "precip",         "total precipitation  (142+143)",            "kg m-2 s-1" },
-  { 261, "net_top",        "total top radiation  (178+179)",            "W m-2"      },
-  { 262, "net_bot",        "total surface radiation (176+177)",         "W m-2"      },
-  { 272, "mastfru",        "mass stream function",                      "kg/s"       },
+static const PAR echam6[] = {
+  {   4, 0, "precip",         "total precipitation",                       "kg m-2 s-1" },
+  {  34, 0, "low_cld",        "low cloud",                                  NULL        },
+  {  35, 0, "mid_cld",        "mid cloud",                                  NULL        },
+  {  36, 0, "hih_cld",        "high cloud",                                 NULL        },
+  {  68, 0, "fage",           "aging factor of snow on ice",                NULL        },
+  {  69, 0, "snifrac",        "fraction of ice covered with snow",          NULL        },
+  {  70, 0, "barefrac",       "bare ice fraction",                          NULL        },
+  {  71, 0, "alsom",          "albedo of melt ponds",                       NULL        },
+  {  72, 0, "alsobs",         "albedo of bare ice and snow",                NULL        },
+  {  73, 0, "sicepdw",        "melt pond depth on sea-ice",                "m"          },
+  {  74, 0, "sicepdi",        "ice thickness on melt pond",                "m"          },
+  {  75, 0, "tsicepdi",       "ice temperature on frozen melt pond",       "K"          },
+  {  76, 0, "sicepres",       "residual heat flux",                        "W m-2"      },
+  {  77, 0, "ameltdepth",     "total melt pond depth",                     "m"          },
+  {  78, 0, "ameltfrac",      "fractional area of melt ponds on sea-ice",   NULL        },
+  {  79, 0, "albedo_vis_dir", "surface albedo visible range direct",        NULL        },
+  {  80, 0, "albedo_nir_dir", "surface albedo NIR range direct",            NULL        },
+  {  81, 0, "albedo_vis_dif", "surface albedo visible range diffuse",       NULL        },
+  {  82, 0, "albedo_nir_dif", "surface albedo NIR range diffuse",           NULL        },
+  {  83, 0, "ocu",            "ocean eastw. velocity (coupled mode)",      "m/s"        },
+  {  84, 0, "ocv",            "ocean northw. velocity (coupled mode)",     "m/s"        },
+  {  85, 0, "tradl",          "thermal radiation 200mb",                   "W m-2"      },
+  {  86, 0, "sradl",          "solar radiation 200mb",                     "W m-2"      },
+  {  87, 0, "trafl",          "thermal radiation 200mb (clear sky)",       "W m-2"      },
+  {  88, 0, "srafl",          "solar radiation 200mb (clear sky)",         "W m-2"      },
+  {  89, 0, "amlcorac",       "mixed layer flux correction",               "W m-2"      },
+  {  90, 0, "amlheatac",      "mixed layer heat content",                  "J m-2"      },
+  {  91, 0, "trfliac",        "LW flux over ice",                          "W m-2"      },
+  {  92, 0, "trflwac",        "LW flux over water",                        "W m-2"      },
+  {  93, 0, "trfllac",        "LW flux over land",                         "W m-2"      },
+  {  94, 0, "sofliac",        "SW flux over ice",                          "W m-2"      },
+  {  95, 0, "soflwac",        "SW flux over water",                        "W m-2"      },
+  {  96, 0, "sofllac",        "SW flux over land",                         "W m-2"      },
+  {  97, 0, "friac",          "ice cover (fraction of grid box)",           NULL        },
+  { 102, 0, "tsi",            "surface temperature of ice",                "K"          },
+  { 103, 0, "tsw",            "surface temperature of water",              "K"          },
+  { 104, 0, "ustri",          "zonal      wind stress over ice",           "Pa"         },
+  { 105, 0, "vstri",          "meridional wind stress over ice",           "Pa"         },
+  { 106, 0, "ustrw",          "zonal      wind stress over water",         "Pa"         },
+  { 107, 0, "vstrw",          "meridional wind stress over water",         "Pa"         },
+  { 108, 0, "ustrl",          "zonal      wind stress over land",          "Pa"         },
+  { 109, 0, "vstrl",          "meridional wind stress over land",          "Pa"         },
+  { 110, 0, "ahfliac",        "latent heat flux over ice",                 "W m-2"      },
+  { 111, 0, "ahflwac",        "latent heat flux over water",               "W m-2"      },
+  { 112, 0, "ahfllac",        "latent heat flux over land",                "W m-2"      },
+  { 113, 0, "evapiac",        "evaporation over ice",                      "kg m-2 s-1" },
+  { 114, 0, "evapwac",        "evaporation over water",                    "kg m-2 s-1" },
+  { 115, 0, "evaplac",        "evaporation over land",                     "kg m-2 s-1" },
+  { 116, 0, "az0i",           "roughness length over ice",                 "m"          },
+  { 117, 0, "az0w",           "roughness length over water",               "m"          },
+  { 118, 0, "az0l",           "roughness length over land",                "m"          },
+  { 119, 0, "ahfsiac",        "sensible heat flux over ice",               "W m-2"      },
+  { 120, 0, "ahfswac",        "sensible heat flux over water",             "W m-2"      },
+  { 121, 0, "ahfslac",        "sensible heat flux over land",              "W m-2"      },
+  { 122, 0, "alsoi",          "albedo of ice",                              NULL        },
+  { 123, 0, "alsow",          "albedo of water",                            NULL        },
+  { 124, 0, "alsol",          "albedo of land",                             NULL        },
+  { 125, 0, "ahfice",         "conductive heat flux",                      "W m-2"      },
+  { 126, 0, "qres",           "residual heat flux for melting sea ice",    "W m-2"      },
+  { 127, 0, "alake",          "lake fraction of grid box",                 "fraction"   },
+  { 128, 0, "rintop",         "low level inversion",                        NULL        },
+  { 129, 0, "geosp",          "surface geopotential (orography)",          "m^2/s^2"    },
+  { 130, 0, "t",              "temperature",                               "K"          },
+  { 131, 0, "u",              "u-velocity",                                "m/s"        },
+  { 132, 0, "v",              "v-velocity",                                "m/s"        },
+  { 133, 0, "q",              "specific humidity",                         "kg/kg"      },
+  { 134, 0, "aps",            "surface pressure",                          "Pa"         },
+  { 135, 0, "omega",          "vertical velocity",                         "Pa/s"       },
+  { 136, 0, "acdnc",          "cloud droplet number concentration",        "1 m-3"      },
+  { 137, 0, "apmeb",          "vert. integr. tendencies of water",         "kg m-2 s-1" },
+  { 138, 0, "svo",            "vorticity",                                 "1/s"        },
+  { 139, 0, "tslm1",          "surface temperature of land",               "K"          },
+  { 140, 0, "ws",             "soil wetness",                              "m"          },
+  { 141, 0, "sn",             "snow depth",                                "m"          },
+  { 142, 0, "aprl",           "large scale precipitation",                 "kg m-2 s-1" },
+  { 143, 0, "aprc",           "convective  precipitation",                 "kg m-2 s-1" },
+  { 144, 0, "aprs",           "snow fall",                                 "kg m-2 s-1" },
+  { 145, 0, "vdis",           "boundary layer dissipation",                "W m-2"      },
+  { 146, 0, "ahfs",           "sensible heat flux",                        "W m-2"      },
+  { 147, 0, "ahfl",           "latent heat flux",                          "W m-2"      },
+  { 148, 0, "stream",         "streamfunction",                            "m^2/s"      },
+  { 149, 0, "velopot",        "velocity potential",                        "m^2/s"      },
+  { 150, 0, "xivi",           "vertically integrated cloud ice",           "kg m-2"     },
+  { 151, 0, "slp",            "mean sea level pressure",                   "Pa"         },
+  { 152, 0, "lsp",            "log surface pressure",                       NULL        },
+  { 153, 0, "xl",             "cloud water",                               "kg/kg"      },
+  { 154, 0, "xi",             "cloud ice",                                 "kg/kg"      },
+  { 155, 0, "sd",             "divergence",                                "1/s"        },
+  { 156, 0, "geopoth",        "geopotential height",                       "m"          },
+  { 157, 0, "rhumidity",      "relative humidity",                         "fraction"   },
+  { 158, 0, "var158",         "tendency of surface pressure",              "Pa/s"       },
+  { 159, 0, "wind10w",        "10m windspeed over water",                  "m/s"        },
+  { 160, 0, "runoff",         "surface runoff and drainage",               "kg m-2 s-1" },
+  { 161, 0, "drain",          "drainage",                                  "kg m-2 s-1" },
+  { 162, 0, "aclc",           "cloud cover",                                NULL        },
+  { 163, 0, "aclcv",          "total cloud cover",                          NULL        },
+  { 164, 0, "aclcov",         "total cloud cover (mean)",                   NULL        },
+  { 165, 0, "u10",            "10m u-velocity",                            "m/s"        },
+  { 166, 0, "v10",            "10m v-velocity",                            "m/s"        },
+  { 167, 0, "temp2",          "2m temperature",                            "K"          },
+  { 168, 0, "dew2",           "2m dew point temperature",                  "K"          },
+  { 169, 0, "tsurf",          "surface temperature",                       "K"          },
+  { 170, 0, "xvar",           "variance of total water amount qv+qi+ql",   "kg/kg"      },
+  { 171, 0, "wind10",         "10m windspeed",                             "m/s"        },
+  { 172, 0, "slm",            "land sea mask (1. = land, 0. = sea/lakes)",  NULL        },
+  { 173, 0, "az0",            "roughness length",                          "m"          },
+  { 174, 0, "alb",            "surface background albedo",                  NULL        },
+  { 175, 0, "albedo",         "surface albedo",                             NULL        },
+  { 176, 0, "srads",          "net surface solar radiation",               "W m-2"      },
+  { 177, 0, "trads",          "net surface thermal radiation",             "W m-2"      },
+  { 178, 0, "srad0",          "net top solar radiation",                   "W m-2"      },
+  { 179, 0, "trad0",          "top thermal radiation (OLR)",               "W m-2"      },
+  { 180, 0, "ustr",           "u-stress",                                  "Pa"         },
+  { 181, 0, "vstr",           "v-stress",                                  "Pa"         },
+  { 182, 0, "evap",           "evaporation",                               "kg m-2 s-1" },
+  { 183, 0, "xskew",          "skewness of total water amount qv+qi+ql",    NULL        },
+  { 184, 0, "srad0d",         "top incoming solar radiation",              "W m-2"      },
+  { 185, 0, "srafs",          "net surf. solar radiation   (clear sky)",   "W m-2"      },
+  { 186, 0, "trafs",          "net surf. thermal radiation (clear sky)",   "W m-2"      },
+  { 187, 0, "sraf0",          "net top solar radiation     (clear sky)",   "W m-2"      },
+  { 188, 0, "traf0",          "net top thermal radiation   (clear sky)",   "W m-2"      },
+  { 189, 0, "sclfs",          "surface solar cloud forcing",               "W m-2"      },
+  { 190, 0, "tclfs",          "surface thermal cloud forcing",             "W m-2"      },
+  { 191, 0, "sclf0",          "SW top cloud forcing (178-187)",            "W m-2"      },
+  { 192, 0, "tclf0",          "LW top cloud forcing (179-188)",            "W m-2"      },
+  { 193, 0, "wl",             "skin reservoir content",                    "m"          },
+  { 194, 0, "slf",            "sea land fraction",                          NULL        },
+  { 195, 0, "ustrgw",         "u-gravity wave stress",                     "Pa"         },
+  { 196, 0, "vstrgw",         "v-gravity wave stress",                     "Pa"         },
+  { 197, 0, "vdisgw",         "gravity wave dissipation",                  "W m-2"      },
+  { 198, 0, "vgrat",          "vegetation ratio",                           NULL        },
+  { 199, 0, "orostd",         "orographic standard deviation",             "m"          },
+  { 200, 0, "vlt",            "leaf area index",                            NULL        },
+  { 201, 0, "t2max",          "maximum 2m-temperature",                    "K"          },
+  { 202, 0, "t2min",          "minimum 2m-temperature",                    "K"          },
+  { 203, 0, "srad0u",         "top solar radiation upward",                "W m-2"      },
+  { 204, 0, "sradsu",         "surface solar radiation upward",            "W m-2"      },
+  { 205, 0, "tradsu",         "surface thermal radiation upward",          "W m-2"      },
+  { 206, 0, "grndflux",       "surface ground heat flux",                   NULL        },
+  { 207, 0, "tsoil",          "deep soil temperatures (5 layers)",         "K"          },
+  { 208, 0, "ahfcon",         "conductive heat flux through ice",          "W m-2"      },
+  { 209, 0, "ahfres",         "melting of ice",                            "W m-2"      },
+  { 210, 0, "seaice",         "ice cover (fraction of 1-SLM)",              NULL        },
+  { 211, 0, "siced",          "ice depth",                                 "m"          },
+  { 212, 0, "forest",         "forest fraction",                            NULL        },
+  { 213, 0, "gld",            "glacier depth",                             "m"          },
+  { 214, 0, "sni",            "water equivalent of snow on ice",           "m"          },
+  { 215, 0, "rogl",           "glacier runoff",                            "kg m-2 s-1" },
+  { 216, 0, "wimax",          "maximum 10m-wind speed",                    "m/s"        },
+  { 217, 0, "topmax",         "maximum height of convective cloud tops",   "Pa"         },
+  { 218, 0, "snmel",          "snow melt",                                 "kg m-2 s-1" },
+  { 219, 0, "runtoc",         "surface runoff into ocean",                 "kg m-2 s-1" },
+  { 220, 0, "runlnd",         "surface runoff not running into ocean",     "kg m-2 s-1" },
+  { 221, 0, "apmegl",         "P-E over land ice",                         "kg m-2 s-1" },
+  { 222, 0, "snacl",          "snow accumulation over land",               "kg m-2 s-1" },
+  { 223, 0, "aclcac",         "cloud cover",                                NULL        },
+  { 224, 0, "tke",            "turbulent kinetic energy",                  "m^2/s^2"    },
+  { 225, 0, "tkem1",          "turbulent kinetic energy (t-1)",            "m^2/s^2"    },
+  { 226, 0, "fao",            "FAO data set (soil data flags)",            "0...5"      },
+  { 227, 0, "rgcgn",          "heat capacity of soil",                      NULL        },
+  { 228, 0, "sodif",          "diffusivity of soil and land ice",          "m^2/s"      },
+  { 229, 0, "wsmx",           "field capacity of soil",                    "m"          },
+  { 230, 0, "qvi",            "vertically integrated water vapor",         "kg m-2"     },
+  { 231, 0, "xlvi",           "vertically integrated cloud water",         "kg m-2"     },
+  { 232, 0, "glac",           "fraction of land covered by glaciers",       NULL        },
+  { 233, 0, "snc",            "snow depth at the canopy",                  "m"          },
+  { 234, 0, "rtype",          "type of convection",                        "0...3"      },
+  { 235, 0, "abso4",          "antropogenic sulfur burden",                "kg m-2"     },
+  { 236, 0, "ao3",            "ipcc ozone",                                "kg m-2"     },
+  { 237, 0, "tropo",          "WMO defined tropopause height",             "Pa"         },
+  { 259, 0, "windspeed",      "windspeed (sqrt(u^2+v^2))",                 "m/s"        },
+  { 260, 0, "precip",         "total precipitation  (142+143)",            "kg m-2 s-1" },
+  { 261, 0, "net_top",        "total top radiation  (178+179)",            "W m-2"      },
+  { 262, 0, "net_bot",        "total surface radiation (176+177)",         "W m-2"      },
+  { 272, 0, "mastfru",        "mass stream function",                      "kg/s"       },
 };
 
-static PAR mpiom1[] = {
-  {   2, "THO",      "temperature",                     "C"        },
-  {   5, "SAO",      "salinity",                        "psu"      },
-  {   3, "UKO",      "zon. velocity",                   "m/s"      },
-  {   4, "VKE",      "mer. velocity",                   "m/s"      },
-  { 303, "UKOMFL",   "zon. velocity (divergence free)", "m/s"      },
-  { 304, "VKEMFL",   "mer. velocity (divergence free)", "m/s"      },
-  {   7, "WO",       "ver. velocity",                   "m/s"      },
-  {   8, "RHO",      "insitu density",                  "kg/m**3"  },
-  {   6, "PO",       "pressure",                        "Pa"       },
-  {  67, "EMINPO",   "freshwaterflux by restoring",     "m/s"      },
-  {  70, "FLUM",     "total heatflux",                  "W/m**2"   },
-  {  79, "PEM",      "total freshwaterflux",            "m/s"      },
-  {  13, "SICTHO",   "ice thickness",                   "m"        },
-  {  15, "SICOMO",   "ice compactness",                 "frac."    },
-  {  35, "SICUO",    "zon. ice velocity",               "m/s"      },
-  {  36, "SICVE",    "mer. ice velocity",               "m/s"      },
-  {  92, "TAFO",     "surface air temperature",         "C"        },
-  { 164, "FCLOU",    "cloud cover",                      NULL      },
-  {  52, "TXO",      "surface u-stress",                "Pa/1025." },
-  {  53, "TYE",      "surface v-stress",                "Pa/1025." },
-  { 260, "FPREC",    "prescr. precipitation",           "m/s"      },
-  {  80, "FSWR",     "downward shortwave rad.",         "W/m**2"   },
-  {  81, "FTDEW",    "dewpoint temperature",            "K"        },
-  { 171, "FU10",     "10m windspeed",                   "m/s"      },
-  { 141, "SICSNO",   "snow thickness",                  "m"        },
-  { 176, "QSWO",     "heat flux shortwave",             "W/m**2"   },
-  { 177, "QLWO",     "heat flux longwave",              "W/m**2"   },
-  { 147, "QLAO",     "heat flux latent",                "W/m**2"   },
-  { 146, "QSEO",     "heat flux sensible",              "W/m**2"   },
-  {  65, "PRECO",    "net freshwater flux + runoff",    "m/s"      },
-  {   1, "ZO",       "sealevel",                        "m"        },
-  {  82, "Z1O",      "sealevel change",                 "m"        },
-  {  69, "KCONDEP",  "depth of convection",             "level"    },
-  {  27, "PSIUWE",   "hor. bar. streamfunction",        "Sv"       },
-  {  83, "AMLD",     "mixed layer depth",               "m"        },
-  { 172, "WETO",     "landseamask (pressure points)",    NULL      },
-  { 507, "AMSUE",    "landseamask (vector points v)",    NULL      },
-  { 508, "AMSUO",    "landseamask (vector points u)",    NULL      },
-  {  84, "DEPTO",    "depth at pressure points",        "m"        },
-  { 484, "DEUTO",    "depth at vector points (u)",      "m"        },
-  { 584, "DEUTE",    "depth at vector points (v)",      "m"        },
-  { 184, "DDUO",     "level thickness (vector u )",     "m"        },
-  { 284, "DDUE",     "level thickness (vector v )",     "m"        },
-  { 384, "DDPO",     "level thickness (pressure )",     "m"        },
-  {  85, "DLXP",     "grid distance x",                 "m"        },
-  {  86, "DLYP",     "grid distance y",                 "m"        },
-  { 185, "DLXU",     "grid distance x  (vector u)",     "m"        },
-  { 186, "DLYU",     "grid distance y  (vector u)",     "m"        },
-  { 285, "DLXV",     "grid distance x  (vector v)",     "m"        },
-  { 286, "DLYV",     "grid distance y  (vector v)",     "m"        },
-  {  54, "GILA",     "latitude in radiants",            "rad"      },
-  {  55, "GIPH",     "longitude in radiants",           "rad"      },
-  { 354, "ALAT",     "latitude in degrees (pressure)",  "deg"      },
-  { 355, "ALON",     "longitude in degrees (pressure)", "deg"      },
-  { 154, "ALATU",    "latitude in degrees (vector u)",  "deg"      },
-  { 155, "ALONU",    "longitude in degrees (vector u)", "deg"      },
-  { 254, "ALATV",    "latitude in degrees (vector v)",  "deg"      },
-  { 255, "ALONV",    "longitude in degrees (vector v)", "deg"      },
-  { 110, "AVO",      "vertical impuls diffusion",       "m**2/s"   },
-  { 111, "DVO",      "vertical T,S diffusion",          "m**2/s"   },
-  { 142, "SICTRU",   "seaice transport x",              "m**2/s"   },
-  { 143, "SICTRV",   "seaice transport y",              "m**2/s"   },
-  { 612, "WTMIX",    "wind mixing",                     "m**2/s"   },
-  { 183, "zmld",     "mixed layer depth (SJ)",          "m"        },
-  { 207, "WGO",      "GM vertical velocity",            "m/s"      },
-  { 305, "rivrun",   "RiverRunoff",                     "m/s"      },
-  { 158, "TMCDO",    "mon. mean depth of convection",   "level"    },
-  { 247, "DQSWO",    "heatflux sw over water",          "W/m**2"   },
-  { 248, "DQLWO",    "heatflux lw over water",          "W/m**2"   },
-  { 249, "DQSEO",    "heatflux se over water",          "W/m**2"   },
-  { 250, "DQLAO",    "heatflux la over water",          "W/m**2"   },
-  { 251, "DQTHO",    "heatflux net over water",         "W/m**2"   },
-  { 252, "DQSWI",    "heatflux sw over seaice",         "W/m**2"   },
-  { 253, "DQLWI",    "heatflux lw over seaice",         "W/m**2"   },
-  { 254, "DQSEI",    "heatflux se over seaice",         "W/m**2"   },
-  { 255, "DQLAI",    "heatflux la over seaice",         "W/m**2"   },
-  { 256, "DQTHI",    "heatflux net over seaice",        "W/m**2"   },
-  { 257, "DTICEO",   "Equi. temp over seaice",          "K"        },
-  { 270, "AOFLNHWO", "oasis net heat flux water",       "W/m**2"   },
-  { 271, "AOFLSHWO", "oasis downward short wave",       "W/m**2"   },
-  { 272, "AOFLRHIO", "oasis residual heat flux ice",    "W/m**2"   },
-  { 273, "AOFLCHIO", "oasis conduct. heat flux ice",    "W/m**2"   },
-  { 274, "AOFLFRWO", "oasis fluid fresh water flux",    "m/s"      },
-  { 275, "AOFLFRIO", "oasis solid fresh water flux",    "m/s"      },
-  { 276, "AOFLTXWO", "oasis wind stress water x",       "Pa/102"   },
-  { 277, "AOFLTYWO", "oasis wind stress water y",       "Pa/102"   },
-  { 278, "AOFLTXIO", "oasis wind stress ice x",         "Pa/102"   },
-  { 279, "AOFLTYIO", "oasis wind stress ice x",         "Pa/102"   },
-  { 280, "AOFLWSVO", "oasis wind speed",                "m/s"      },
+static const PAR mpiom1[] = {
+  {   2, 0, "THO",      "temperature",                     "C"        },
+  {   5, 0, "SAO",      "salinity",                        "psu"      },
+  {   3, 0, "UKO",      "zon. velocity",                   "m/s"      },
+  {   4, 0, "VKE",      "mer. velocity",                   "m/s"      },
+  { 303, 0, "UKOMFL",   "zon. velocity (divergence free)", "m/s"      },
+  { 304, 0, "VKEMFL",   "mer. velocity (divergence free)", "m/s"      },
+  {   7, 0, "WO",       "ver. velocity",                   "m/s"      },
+  {   8, 0, "RHO",      "insitu density",                  "kg/m**3"  },
+  {   6, 0, "PO",       "pressure",                        "Pa"       },
+  {  67, 0, "EMINPO",   "freshwaterflux by restoring",     "m/s"      },
+  {  70, 0, "FLUM",     "total heatflux",                  "W/m**2"   },
+  {  79, 0, "PEM",      "total freshwaterflux",            "m/s"      },
+  {  13, 0, "SICTHO",   "ice thickness",                   "m"        },
+  {  15, 0, "SICOMO",   "ice compactness",                 "frac."    },
+  {  35, 0, "SICUO",    "zon. ice velocity",               "m/s"      },
+  {  36, 0, "SICVE",    "mer. ice velocity",               "m/s"      },
+  {  92, 0, "TAFO",     "surface air temperature",         "C"        },
+  { 164, 0, "FCLOU",    "cloud cover",                      NULL      },
+  {  52, 0, "TXO",      "surface u-stress",                "Pa/1025." },
+  {  53, 0, "TYE",      "surface v-stress",                "Pa/1025." },
+  { 260, 0, "FPREC",    "prescr. precipitation",           "m/s"      },
+  {  80, 0, "FSWR",     "downward shortwave rad.",         "W/m**2"   },
+  {  81, 0, "FTDEW",    "dewpoint temperature",            "K"        },
+  { 171, 0, "FU10",     "10m windspeed",                   "m/s"      },
+  { 141, 0, "SICSNO",   "snow thickness",                  "m"        },
+  { 176, 0, "QSWO",     "heat flux shortwave",             "W/m**2"   },
+  { 177, 0, "QLWO",     "heat flux longwave",              "W/m**2"   },
+  { 147, 0, "QLAO",     "heat flux latent",                "W/m**2"   },
+  { 146, 0, "QSEO",     "heat flux sensible",              "W/m**2"   },
+  {  65, 0, "PRECO",    "net freshwater flux + runoff",    "m/s"      },
+  {   1, 0, "ZO",       "sealevel",                        "m"        },
+  {  82, 0, "Z1O",      "sealevel change",                 "m"        },
+  {  69, 0, "KCONDEP",  "depth of convection",             "level"    },
+  {  27, 0, "PSIUWE",   "hor. bar. streamfunction",        "Sv"       },
+  {  83, 0, "AMLD",     "mixed layer depth",               "m"        },
+  { 172, 0, "WETO",     "landseamask (pressure points)",    NULL      },
+  { 507, 0, "AMSUE",    "landseamask (vector points v)",    NULL      },
+  { 508, 0, "AMSUO",    "landseamask (vector points u)",    NULL      },
+  {  84, 0, "DEPTO",    "depth at pressure points",        "m"        },
+  { 484, 0, "DEUTO",    "depth at vector points (u)",      "m"        },
+  { 584, 0, "DEUTE",    "depth at vector points (v)",      "m"        },
+  { 184, 0, "DDUO",     "level thickness (vector u )",     "m"        },
+  { 284, 0, "DDUE",     "level thickness (vector v )",     "m"        },
+  { 384, 0, "DDPO",     "level thickness (pressure )",     "m"        },
+  {  85, 0, "DLXP",     "grid distance x",                 "m"        },
+  {  86, 0, "DLYP",     "grid distance y",                 "m"        },
+  { 185, 0, "DLXU",     "grid distance x  (vector u)",     "m"        },
+  { 186, 0, "DLYU",     "grid distance y  (vector u)",     "m"        },
+  { 285, 0, "DLXV",     "grid distance x  (vector v)",     "m"        },
+  { 286, 0, "DLYV",     "grid distance y  (vector v)",     "m"        },
+  {  54, 0, "GILA",     "latitude in radiants",            "rad"      },
+  {  55, 0, "GIPH",     "longitude in radiants",           "rad"      },
+  { 354, 0, "ALAT",     "latitude in degrees (pressure)",  "deg"      },
+  { 355, 0, "ALON",     "longitude in degrees (pressure)", "deg"      },
+  { 154, 0, "ALATU",    "latitude in degrees (vector u)",  "deg"      },
+  { 155, 0, "ALONU",    "longitude in degrees (vector u)", "deg"      },
+  { 254, 0, "ALATV",    "latitude in degrees (vector v)",  "deg"      },
+  { 255, 0, "ALONV",    "longitude in degrees (vector v)", "deg"      },
+  { 110, 0, "AVO",      "vertical impuls diffusion",       "m**2/s"   },
+  { 111, 0, "DVO",      "vertical T,S diffusion",          "m**2/s"   },
+  { 142, 0, "SICTRU",   "seaice transport x",              "m**2/s"   },
+  { 143, 0, "SICTRV",   "seaice transport y",              "m**2/s"   },
+  { 612, 0, "WTMIX",    "wind mixing",                     "m**2/s"   },
+  { 183, 0, "zmld",     "mixed layer depth (SJ)",          "m"        },
+  { 207, 0, "WGO",      "GM vertical velocity",            "m/s"      },
+  { 305, 0, "rivrun",   "RiverRunoff",                     "m/s"      },
+  { 158, 0, "TMCDO",    "mon. mean depth of convection",   "level"    },
+  { 247, 0, "DQSWO",    "heatflux sw over water",          "W/m**2"   },
+  { 248, 0, "DQLWO",    "heatflux lw over water",          "W/m**2"   },
+  { 249, 0, "DQSEO",    "heatflux se over water",          "W/m**2"   },
+  { 250, 0, "DQLAO",    "heatflux la over water",          "W/m**2"   },
+  { 251, 0, "DQTHO",    "heatflux net over water",         "W/m**2"   },
+  { 252, 0, "DQSWI",    "heatflux sw over seaice",         "W/m**2"   },
+  { 253, 0, "DQLWI",    "heatflux lw over seaice",         "W/m**2"   },
+  { 254, 0, "DQSEI",    "heatflux se over seaice",         "W/m**2"   },
+  { 255, 0, "DQLAI",    "heatflux la over seaice",         "W/m**2"   },
+  { 256, 0, "DQTHI",    "heatflux net over seaice",        "W/m**2"   },
+  { 257, 0, "DTICEO",   "Equi. temp over seaice",          "K"        },
+  { 270, 0, "AOFLNHWO", "oasis net heat flux water",       "W/m**2"   },
+  { 271, 0, "AOFLSHWO", "oasis downward short wave",       "W/m**2"   },
+  { 272, 0, "AOFLRHIO", "oasis residual heat flux ice",    "W/m**2"   },
+  { 273, 0, "AOFLCHIO", "oasis conduct. heat flux ice",    "W/m**2"   },
+  { 274, 0, "AOFLFRWO", "oasis fluid fresh water flux",    "m/s"      },
+  { 275, 0, "AOFLFRIO", "oasis solid fresh water flux",    "m/s"      },
+  { 276, 0, "AOFLTXWO", "oasis wind stress water x",       "Pa/102"   },
+  { 277, 0, "AOFLTYWO", "oasis wind stress water y",       "Pa/102"   },
+  { 278, 0, "AOFLTXIO", "oasis wind stress ice x",         "Pa/102"   },
+  { 279, 0, "AOFLTYIO", "oasis wind stress ice x",         "Pa/102"   },
+  { 280, 0, "AOFLWSVO", "oasis wind speed",                "m/s"      },
 };
 
-static PAR ecmwf[] = {
-  {   1, "STRF",   "Stream function",                                            "m**2 s**-1"            },
-  {   2, "VPOT",   "Velocity potential",                                         "m**2 s**-1"            },
-  {   3, "PT",     "Potential temperature",                                      "K"                     },
-  {   4, "EQPT",   "Equivalent potential temperature",                           "K"                     },
-  {   5, "SEPT",   "Saturated equivalent potential temperature",                 "K"                     },
-  {  11, "UDVW",   "U component of divergent wind",                              "m s**-1"               },
-  {  12, "VDVW",   "V component of divergent wind",                              "m s**-1"               },
-  {  13, "URTW",   "U component of rotational wind",                             "m s**-1"               },
-  {  14, "VRTW",   "V component of rotational wind",                             "m s**-1"               },
-  {  21, "UCTP",   "Unbalanced component of temperature",                        "K"                     },
-  {  22, "UCLN",   "Unbalanced component of logarithm of surface pressure",       NULL                   },
-  {  23, "UCDV",   "Unbalanced component of divergence",                         "s**-1"                 },
-  {  26, "CL",     "Lake cover",                                                  NULL                   },
-  {  27, "CVL",    "Low vegetation cover",                                        NULL                   },
-  {  28, "CVH",    "High vegetation cover",                                       NULL                   },
-  {  29, "TVL",    "Type of low vegetation",                                      NULL                   },
-  {  30, "TVH",    "Type of high vegetation",                                     NULL                   },
-  {  31, "CI",     "Sea-ice cover",                                               NULL                   },
-  {  32, "ASN",    "Snow albedo",                                                 NULL                   },
-  {  33, "RSN",    "Snow density kg",                                            "m**-3"                 },
-  {  34, "SSTK",   "Sea surface temperature",                                    "K"                     },
-  {  35, "ISTL1",  "Ice surface temperature layer 1",                            "K"                     },
-  {  36, "ISTL2",  "Ice surface temperature layer 2",                            "K"                     },
-  {  37, "ISTL3",  "Ice surface temperature layer 3",                            "K"                     },
-  {  38, "ISTL4",  "Ice surface temperature layer 4",                            "K"                     },
-  {  39, "SWVL1",  "Volumetric soil water layer 1",                              "m**3 m**-3"            },
-  {  40, "SWVL2",  "Volumetric soil water layer 2",                              "m**3 m**-3"            },
-  {  41, "SWVL3",  "Volumetric soil water layer 3",                              "m**3 m**-3"            },
-  {  42, "SWVL4",  "Volumetric soil water layer 4",                              "m**3 m**-3"            },
-  {  43, "SLT",    "Soil type",                                                   NULL                   },
-  {  44, "ES",     "Snow evaporation m of water",                                 NULL                   },
-  {  45, "SMLT",   "Snowmelt m of water",                                         NULL                   },
-  {  46, "SDUR",   "Solar duration",                                             "s"                     },
-  {  47, "DSRP",   "Direct solar radiation",                                     "w m**-2"               },
-  {  48, "MAGSS",  "Magnitude of surface stress",                                "N m**-2 s"             },
-  {  49, "WG10",   "Wind gust at 10 metres",                                     "m s**-1"               },
-  {  50, "LSPF",   "Large-scale precipitation fraction",                         "s"                     },
-  {  51, "MX2T24", "Maximum 2 metre temperature",                                "K"                     },
-  {  52, "MN2T24", "Minimum 2 metre temperature",                                "K"                     },
-  {  53, "MONT",   "Montgomery potential",                                       "m**2 s**-2"            },
-  {  54, "PRES",   "Pressure",                                                   "Pa"                    },
-  {  55, "MN2T24", "Mean 2 metre temperature past 24 hours",                     "K"                     },
-  {  56, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours",            "K"                     },
-  {  60, "PV",     "Potential vorticity",                                        "K m**2 kg**-1 s**-1"   },
-  { 127, "AT",     "Atmospheric tide",                                            NULL                   },
-  { 128, "BV",     "Budget values",                                               NULL                   },
-  { 129, "Z",      "Geopotential",                                               "m**2 s**-2"            },
-  { 130, "T",      "Temperature",                                                "K"                     },
-  { 131, "U",      "U velocity",                                                 "m s**-1"               },
-  { 132, "V",      "V velocity",                                                 "m s**-1"               },
-  { 133, "Q",      "Specific humidity",                                          "kg kg**-1"             },
-  { 134, "SP",     "Surface pressure",                                           "Pa"                    },
-  { 135, "W",      "Vertical velocity",                                          "Pa s**-1"              },
-  { 136, "TCW",    "Total column water",                                         "kg m**-2"              },
-  { 137, "TCWV",   "Total column water vapour",                                  "kg m**-2"              },
-  { 138, "VO",     "Vorticity (relative)",                                       "s**-1"                 },
-  { 139, "STL1",   "Soil temperature level 1",                                   "K"                     },
-  { 140, "SWL1",   "Soil wetness level 1 m of water",                             NULL                   },
-  { 141, "SD",     "Snow depth         1 m of water equivalent",                  NULL                   },
-  { 142, "LSP",    "Stratiform precipitation (Large scale precipitation)",       "m"                     },
-  { 143, "CP",     "Convective precipitation",                                   "m"                     },
-  { 144, "SF",     "Snowfall (convective + stratiform)",                         "m"                     },
-  { 145, "BLD",    "Boundary layer dissipation",                                 "W m**-2 s"             },
-  { 146, "SSHF",   "Surface sensible heat flux",                                 "W m**-2 s"             },
-  { 147, "SLHF",   "Surface latent heat flux",                                   "W m**-2 s"             },
-  { 148, "CHNK",   "Charnock",                                                    NULL                   },
-  { 149, "SNR",    "Surface net radiation",                                      "W m**-2 s"             },
-  { 150, "TNR",    "Top net radiation",                                           NULL                   },
-  { 151, "MSL",    "Mean sea-level pressure",                                    "Pa"                    },
-  { 152, "LNSP",   "Logarithm of surface pressure",                               NULL                   },
-  { 153, "SWHR",   "Short-wave heating rate",                                    "K"                     },
-  { 154, "LWHR",   "Long-wave heating rate",                                     "K"                     },
-  { 155, "D",      "Divergence",                                                 "s**-1"                 },
-  { 156, "GH",     "Height m Geopotential height",                                NULL                   },
-  { 157, "R",      "Relative humidity",                                          "%"                     },
-  { 158, "TSP",    "Tendency of surface pressure",                               "Pa s**-1"              },
-  { 159, "BLH",    "Boundary layer height",                                      "m"                     },
-  { 160, "SDOR",   "Standard deviation of orography",                             NULL                   },
-  { 161, "ISOR",   "Anisotropy of sub-gridscale orography",                       NULL                   },
-  { 162, "ANOR",   "Angle of sub-gridscale orography",                           "rad"                   },
-  { 163, "SLOR",   "Slope of sub-gridscale orography",                            NULL                   },
-  { 164, "TCC",    "Total cloud cover",                                           NULL                   },
-  { 165, "U10M",   "10 metre U wind component",                                  "m s**-1"               },
-  { 166, "V10M",   "10 metre V wind component",                                  "m s**-1"               },
-  { 167, "T2M",    "2 metre temperature",                                        "K"                     },
-  { 168, "D2M",    "2 metre dewpoint temperature",                               "K"                     },
-  { 169, "SSRD",   "Surface solar radiation downwards",                          "W m**-2 s"             },
-  { 170, "STL2",   "Soil temperature level 2",                                   "K"                     },
-  { 171, "SWL2",   "Soil wetness level 2",                                       "m of water"            },
-  { 172, "LSM",    "Land/sea mask",                                               NULL                   },
-  { 173, "SR",     "Surface roughness",                                          "m"                     },
-  { 174, "AL",     "Albedo",                                                      NULL                   },
-  { 175, "STRD",   "Surface thermal radiation downwards",                        "W m**-2 s"             },
-  { 176, "SSR",    "Surface solar radiation",                                    "W m**-2 s"             },
-  { 177, "STR",    "Surface thermal radiation",                                  "W m**-2 s"             },
-  { 178, "TSR",    "Top solar radiation",                                        "W m**-2 s"             },
-  { 179, "TTR",    "Top thermal radiation",                                      "W m**-2 s"             },
-  { 180, "EWSS",   "East/West surface stress",                                   "N m**-2 s"             },
-  { 181, "NSSS",   "North/South surface stress",                                 "N m**-2 s"             },
-  { 182, "E",      "Evaporation",                                                "m of water"            },
-  { 183, "STL3",   "Soil temperature level 3",                                   "K"                     },
-  { 184, "SWL3",   "Soil wetness level 3",                                       "m of water"            },
-  { 185, "CCC",    "Convective cloud cover",                                      NULL                   },
-  { 186, "LCC",    "Low cloud cover",                                             NULL                   },
-  { 187, "MCC",    "Medium cloud cover",                                          NULL                   },
-  { 188, "HCC",    "High cloud cover",                                            NULL                   },
-  { 189, "SUND",   "Sunshine duration",                                          "s"                     },
-  { 190, "EWOV",   "EW component of subgrid orographic variance",                "m**2"                  },
-  { 191, "NSOV",   "NS component of subgrid orographic variance",                "m**2"                  },
-  { 192, "NWOV",   "NWSE component of subgrid orographic variance",              "m**2"                  },
-  { 193, "NEOV",   "NESW component of subgrid orographic variance",              "m**2"                  },
-  { 194, "BTMP",   "Brightness temperature",                                     "K"                     },
-  { 195, "LGWS",   "Lat. component of gravity wave stress",                      "N m**-2 s"             },
-  { 196, "MGWS",   "Meridional component of gravity wave stress",                "N m**-2 s"             },
-  { 197, "GWD",    "Gravity wave dissipation",                                   "W m**-2 s"             },
-  { 198, "SRC",    "Skin reservoir content",                                     "m of water"            },
-  { 199, "VEG",    "Vegetation fraction",                                         NULL                   },
-  { 200, "VSO",    "Variance of sub-gridscale orography",                        "m**2"                  },
-  { 201, "MX2T",   "Maximum 2 metre temperature since previous post-processing", "K"                     },
-  { 202, "MN2T",   "Minimum 2 metre temperature since previous post-processing", "K"                     },
-  { 203, "O3",     "Ozone mass mixing ratio",                                    "kg kg**-1"             },
-  { 204, "PAW",    "Precipiation analysis weights",                               NULL                   },
-  { 205, "RO",     "Runoff",                                                     "m"                     },
-  { 206, "TCO3",   "Total column ozone",                                         "kg m**-2"              },
-  { 207, "WS10",   "10 meter windspeed",                                         "m s**-1"               },
-  { 208, "TSRC",   "Top net solar radiation, clear sky",                         "W m**-2"               },
-  { 209, "TTRC",   "Top net thermal radiation, clear sky",                       "W m**-2"               },
-  { 210, "SSRC",   "Surface net solar radiation, clear sky",                     "W m**-2"               },
-  { 211, "STRC",   "Surface net thermal radiation, clear sky",                   "W m**-2"               },
-  { 212, "SI",     "Solar insolation",                                           "W m**-2"               },
-  { 214, "DHR",    "Diabatic heating by radiation",                              "K"                     },
-  { 215, "DHVD",   "Diabatic heating by vertical diffusion",                     "K"                     },
-  { 216, "DHCC",   "Diabatic heating by cumulus convection",                     "K"                     },
-  { 217, "DHLC",   "Diabatic heating large-scale condensation",                  "K"                     },
-  { 218, "VDZW",   "Vertical diffusion of zonal wind",                           "m s**-1"               },
-  { 219, "VDMW",   "Vertical diffusion of meridional wind",                      "m s**-1"               },
-  { 220, "EWGD",   "EW gravity wave drag tendency",                              "m s**-1"               },
-  { 221, "NSGD",   "NS gravity wave drag tendency",                              "m s**-1"               },
-  { 222, "CTZW",   "Convective tendency of zonal wind",                          "m s**-1"               },
-  { 223, "CTMW",   "Convective tendency of meridional wind",                     "m s**-1"               },
-  { 224, "VDH",    "Vertical diffusion of humidity",                             "kg kg**-1"             },
-  { 225, "HTCC",   "Humidity tendency by cumulus convection",                    "kg kg**-1"             },
-  { 226, "HTLC",   "Humidity tendency large-scale condensation",                 "kg kg**-1"             },
-  { 227, "CRNH",   "Change from removing negative humidity",                     "kg kg**-1"             },
-  { 228, "TP",     "Total precipitation",                                        "m"                     },
-  { 229, "IEWS",   "Instantaneous X surface stress",                             "N m**-2"               },
-  { 230, "INSS",   "Instantaneous Y surface stress",                             "N m**-2"               },
-  { 231, "ISHF",   "Instantaneous surface heat flux",                            "W m**-2"               },
-  { 232, "IE",     "Instantaneous moisture flux",                                "kg m**-2 s"            },
-  { 233, "ASQ",    "Apparent surface humidity",                                  "kg kg**-1"             },
-  { 234, "LSRH",   "Logarithm of surface roughness length for heat",              NULL                   },
-  { 235, "SKT",    "Skin temperature",                                           "K"                     },
-  { 236, "STL4",   "Soil temperature level 4",                                   "K"                     },
-  { 237, "SWL4",   "Soil wetness level 4",                                       "m"                     },
-  { 238, "TSN",    "Temperature of snow layer",                                  "K"                     },
-  { 239, "CSF",    "Convective snowfall",                                        "m of water equivalent" },
-  { 240, "LSF",    "Large-scale snowfall",                                       "m of water equivalent" },
-  { 241, "ACF",    "Accumulated cloud fraction tendency",                         NULL                   },
-  { 242, "ALW",    "Accumulated liquid water tendency",                           NULL                   },
-  { 243, "FAL",    "Forecast albedo",                                             NULL                   },
-  { 244, "FSR",    "Forecast surface roughness",                                 "m"                     },
-  { 245, "FLSR",   "Forecast log of surface roughness for heat",                  NULL                   },
-  { 246, "CLWC",   "Cloud liquid water content",                                 "kg kg**-1"             },
-  { 247, "CIWC",   "Cloud ice water content",                                    "kg kg**-1"             },
-  { 248, "CC",     "Cloud cover",                                                 NULL                   },
-  { 249, "AIW",    "Accumulated ice water tendency",                              NULL                   },
-  { 250, "ICE",    "Ice age",                                                     NULL                   },
-  { 251, "ATTE",   "Adiabatic tendency of temperature",                          "K"                     },
-  { 252, "ATHE",   "Adiabatic tendency of humidity",                             "kg kg**-1"             },
-  { 253, "ATZE",   "Adiabatic tendency of zonal wind",                           "m s**-1"               },
-  { 254, "ATMW",   "Adiabatic tendency of meridional wind",                      "m s**-1"               },
+static const PAR ecmwf[] = {
+  {   1, 0, "STRF",   "Stream function",                                            "m**2 s**-1"            },
+  {   2, 0, "VPOT",   "Velocity potential",                                         "m**2 s**-1"            },
+  {   3, 0, "PT",     "Potential temperature",                                      "K"                     },
+  {   4, 0, "EQPT",   "Equivalent potential temperature",                           "K"                     },
+  {   5, 0, "SEPT",   "Saturated equivalent potential temperature",                 "K"                     },
+  {  11, 0, "UDVW",   "U component of divergent wind",                              "m s**-1"               },
+  {  12, 0, "VDVW",   "V component of divergent wind",                              "m s**-1"               },
+  {  13, 0, "URTW",   "U component of rotational wind",                             "m s**-1"               },
+  {  14, 0, "VRTW",   "V component of rotational wind",                             "m s**-1"               },
+  {  21, 0, "UCTP",   "Unbalanced component of temperature",                        "K"                     },
+  {  22, 0, "UCLN",   "Unbalanced component of logarithm of surface pressure",       NULL                   },
+  {  23, 0, "UCDV",   "Unbalanced component of divergence",                         "s**-1"                 },
+  {  26, 0, "CL",     "Lake cover",                                                  NULL                   },
+  {  27, 0, "CVL",    "Low vegetation cover",                                        NULL                   },
+  {  28, 0, "CVH",    "High vegetation cover",                                       NULL                   },
+  {  29, 0, "TVL",    "Type of low vegetation",                                      NULL                   },
+  {  30, 0, "TVH",    "Type of high vegetation",                                     NULL                   },
+  {  31, 0, "CI",     "Sea-ice cover",                                               NULL                   },
+  {  32, 0, "ASN",    "Snow albedo",                                                 NULL                   },
+  {  33, 0, "RSN",    "Snow density kg",                                            "m**-3"                 },
+  {  34, 0, "SSTK",   "Sea surface temperature",                                    "K"                     },
+  {  35, 0, "ISTL1",  "Ice surface temperature layer 1",                            "K"                     },
+  {  36, 0, "ISTL2",  "Ice surface temperature layer 2",                            "K"                     },
+  {  37, 0, "ISTL3",  "Ice surface temperature layer 3",                            "K"                     },
+  {  38, 0, "ISTL4",  "Ice surface temperature layer 4",                            "K"                     },
+  {  39, 0, "SWVL1",  "Volumetric soil water layer 1",                              "m**3 m**-3"            },
+  {  40, 0, "SWVL2",  "Volumetric soil water layer 2",                              "m**3 m**-3"            },
+  {  41, 0, "SWVL3",  "Volumetric soil water layer 3",                              "m**3 m**-3"            },
+  {  42, 0, "SWVL4",  "Volumetric soil water layer 4",                              "m**3 m**-3"            },
+  {  43, 0, "SLT",    "Soil type",                                                   NULL                   },
+  {  44, 0, "ES",     "Snow evaporation m of water",                                 NULL                   },
+  {  45, 0, "SMLT",   "Snowmelt m of water",                                         NULL                   },
+  {  46, 0, "SDUR",   "Solar duration",                                             "s"                     },
+  {  47, 0, "DSRP",   "Direct solar radiation",                                     "w m**-2"               },
+  {  48, 0, "MAGSS",  "Magnitude of surface stress",                                "N m**-2 s"             },
+  {  49, 0, "WG10",   "Wind gust at 10 metres",                                     "m s**-1"               },
+  {  50, 0, "LSPF",   "Large-scale precipitation fraction",                         "s"                     },
+  {  51, 0, "MX2T24", "Maximum 2 metre temperature",                                "K"                     },
+  {  52, 0, "MN2T24", "Minimum 2 metre temperature",                                "K"                     },
+  {  53, 0, "MONT",   "Montgomery potential",                                       "m**2 s**-2"            },
+  {  54, 0, "PRES",   "Pressure",                                                   "Pa"                    },
+  {  55, 0, "MN2T24", "Mean 2 metre temperature past 24 hours",                     "K"                     },
+  {  56, 0, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours",            "K"                     },
+  {  60, 0, "PV",     "Potential vorticity",                                        "K m**2 kg**-1 s**-1"   },
+  { 127, 0, "AT",     "Atmospheric tide",                                            NULL                   },
+  { 128, 0, "BV",     "Budget values",                                               NULL                   },
+  { 129, 0, "Z",      "Geopotential",                                               "m**2 s**-2"            },
+  { 130, 0, "T",      "Temperature",                                                "K"                     },
+  { 131, 0, "U",      "U velocity",                                                 "m s**-1"               },
+  { 132, 0, "V",      "V velocity",                                                 "m s**-1"               },
+  { 133, 0, "Q",      "Specific humidity",                                          "kg kg**-1"             },
+  { 134, 0, "SP",     "Surface pressure",                                           "Pa"                    },
+  { 135, 0, "W",      "Vertical velocity",                                          "Pa s**-1"              },
+  { 136, 0, "TCW",    "Total column water",                                         "kg m**-2"              },
+  { 137, 0, "TCWV",   "Total column water vapour",                                  "kg m**-2"              },
+  { 138, 0, "VO",     "Vorticity (relative)",                                       "s**-1"                 },
+  { 139, 0, "STL1",   "Soil temperature level 1",                                   "K"                     },
+  { 140, 0, "SWL1",   "Soil wetness level 1 m of water",                             NULL                   },
+  { 141, 0, "SD",     "Snow depth         1 m of water equivalent",                  NULL                   },
+  { 142, 0, "LSP",    "Stratiform precipitation (Large scale precipitation)",       "m"                     },
+  { 143, 0, "CP",     "Convective precipitation",                                   "m"                     },
+  { 144, 0, "SF",     "Snowfall (convective + stratiform)",                         "m"                     },
+  { 145, 0, "BLD",    "Boundary layer dissipation",                                 "W m**-2 s"             },
+  { 146, 0, "SSHF",   "Surface sensible heat flux",                                 "W m**-2 s"             },
+  { 147, 0, "SLHF",   "Surface latent heat flux",                                   "W m**-2 s"             },
+  { 148, 0, "CHNK",   "Charnock",                                                    NULL                   },
+  { 149, 0, "SNR",    "Surface net radiation",                                      "W m**-2 s"             },
+  { 150, 0, "TNR",    "Top net radiation",                                           NULL                   },
+  { 151, 0, "MSL",    "Mean sea-level pressure",                                    "Pa"                    },
+  { 152, 0, "LNSP",   "Logarithm of surface pressure",                               NULL                   },
+  { 153, 0, "SWHR",   "Short-wave heating rate",                                    "K"                     },
+  { 154, 0, "LWHR",   "Long-wave heating rate",                                     "K"                     },
+  { 155, 0, "D",      "Divergence",                                                 "s**-1"                 },
+  { 156, 0, "GH",     "Height m Geopotential height",                                NULL                   },
+  { 157, 0, "R",      "Relative humidity",                                          "%"                     },
+  { 158, 0, "TSP",    "Tendency of surface pressure",                               "Pa s**-1"              },
+  { 159, 0, "BLH",    "Boundary layer height",                                      "m"                     },
+  { 160, 0, "SDOR",   "Standard deviation of orography",                             NULL                   },
+  { 161, 0, "ISOR",   "Anisotropy of sub-gridscale orography",                       NULL                   },
+  { 162, 0, "ANOR",   "Angle of sub-gridscale orography",                           "rad"                   },
+  { 163, 0, "SLOR",   "Slope of sub-gridscale orography",                            NULL                   },
+  { 164, 0, "TCC",    "Total cloud cover",                                           NULL                   },
+  { 165, 0, "U10M",   "10 metre U wind component",                                  "m s**-1"               },
+  { 166, 0, "V10M",   "10 metre V wind component",                                  "m s**-1"               },
+  { 167, 0, "T2M",    "2 metre temperature",                                        "K"                     },
+  { 168, 0, "D2M",    "2 metre dewpoint temperature",                               "K"                     },
+  { 169, 0, "SSRD",   "Surface solar radiation downwards",                          "W m**-2 s"             },
+  { 170, 0, "STL2",   "Soil temperature level 2",                                   "K"                     },
+  { 171, 0, "SWL2",   "Soil wetness level 2",                                       "m of water"            },
+  { 172, 0, "LSM",    "Land/sea mask",                                               NULL                   },
+  { 173, 0, "SR",     "Surface roughness",                                          "m"                     },
+  { 174, 0, "AL",     "Albedo",                                                      NULL                   },
+  { 175, 0, "STRD",   "Surface thermal radiation downwards",                        "W m**-2 s"             },
+  { 176, 0, "SSR",    "Surface solar radiation",                                    "W m**-2 s"             },
+  { 177, 0, "STR",    "Surface thermal radiation",                                  "W m**-2 s"             },
+  { 178, 0, "TSR",    "Top solar radiation",                                        "W m**-2 s"             },
+  { 179, 0, "TTR",    "Top thermal radiation",                                      "W m**-2 s"             },
+  { 180, 0, "EWSS",   "East/West surface stress",                                   "N m**-2 s"             },
+  { 181, 0, "NSSS",   "North/South surface stress",                                 "N m**-2 s"             },
+  { 182, 0, "E",      "Evaporation",                                                "m of water"            },
+  { 183, 0, "STL3",   "Soil temperature level 3",                                   "K"                     },
+  { 184, 0, "SWL3",   "Soil wetness level 3",                                       "m of water"            },
+  { 185, 0, "CCC",    "Convective cloud cover",                                      NULL                   },
+  { 186, 0, "LCC",    "Low cloud cover",                                             NULL                   },
+  { 187, 0, "MCC",    "Medium cloud cover",                                          NULL                   },
+  { 188, 0, "HCC",    "High cloud cover",                                            NULL                   },
+  { 189, 0, "SUND",   "Sunshine duration",                                          "s"                     },
+  { 190, 0, "EWOV",   "EW component of subgrid orographic variance",                "m**2"                  },
+  { 191, 0, "NSOV",   "NS component of subgrid orographic variance",                "m**2"                  },
+  { 192, 0, "NWOV",   "NWSE component of subgrid orographic variance",              "m**2"                  },
+  { 193, 0, "NEOV",   "NESW component of subgrid orographic variance",              "m**2"                  },
+  { 194, 0, "BTMP",   "Brightness temperature",                                     "K"                     },
+  { 195, 0, "LGWS",   "Lat. component of gravity wave stress",                      "N m**-2 s"             },
+  { 196, 0, "MGWS",   "Meridional component of gravity wave stress",                "N m**-2 s"             },
+  { 197, 0, "GWD",    "Gravity wave dissipation",                                   "W m**-2 s"             },
+  { 198, 0, "SRC",    "Skin reservoir content",                                     "m of water"            },
+  { 199, 0, "VEG",    "Vegetation fraction",                                         NULL                   },
+  { 200, 0, "VSO",    "Variance of sub-gridscale orography",                        "m**2"                  },
+  { 201, 0, "MX2T",   "Maximum 2 metre temperature since previous post-processing", "K"                     },
+  { 202, 0, "MN2T",   "Minimum 2 metre temperature since previous post-processing", "K"                     },
+  { 203, 0, "O3",     "Ozone mass mixing ratio",                                    "kg kg**-1"             },
+  { 204, 0, "PAW",    "Precipiation analysis weights",                               NULL                   },
+  { 205, 0, "RO",     "Runoff",                                                     "m"                     },
+  { 206, 0, "TCO3",   "Total column ozone",                                         "kg m**-2"              },
+  { 207, 0, "WS10",   "10 meter windspeed",                                         "m s**-1"               },
+  { 208, 0, "TSRC",   "Top net solar radiation, clear sky",                         "W m**-2"               },
+  { 209, 0, "TTRC",   "Top net thermal radiation, clear sky",                       "W m**-2"               },
+  { 210, 0, "SSRC",   "Surface net solar radiation, clear sky",                     "W m**-2"               },
+  { 211, 0, "STRC",   "Surface net thermal radiation, clear sky",                   "W m**-2"               },
+  { 212, 0, "SI",     "Solar insolation",                                           "W m**-2"               },
+  { 214, 0, "DHR",    "Diabatic heating by radiation",                              "K"                     },
+  { 215, 0, "DHVD",   "Diabatic heating by vertical diffusion",                     "K"                     },
+  { 216, 0, "DHCC",   "Diabatic heating by cumulus convection",                     "K"                     },
+  { 217, 0, "DHLC",   "Diabatic heating large-scale condensation",                  "K"                     },
+  { 218, 0, "VDZW",   "Vertical diffusion of zonal wind",                           "m s**-1"               },
+  { 219, 0, "VDMW",   "Vertical diffusion of meridional wind",                      "m s**-1"               },
+  { 220, 0, "EWGD",   "EW gravity wave drag tendency",                              "m s**-1"               },
+  { 221, 0, "NSGD",   "NS gravity wave drag tendency",                              "m s**-1"               },
+  { 222, 0, "CTZW",   "Convective tendency of zonal wind",                          "m s**-1"               },
+  { 223, 0, "CTMW",   "Convective tendency of meridional wind",                     "m s**-1"               },
+  { 224, 0, "VDH",    "Vertical diffusion of humidity",                             "kg kg**-1"             },
+  { 225, 0, "HTCC",   "Humidity tendency by cumulus convection",                    "kg kg**-1"             },
+  { 226, 0, "HTLC",   "Humidity tendency large-scale condensation",                 "kg kg**-1"             },
+  { 227, 0, "CRNH",   "Change from removing negative humidity",                     "kg kg**-1"             },
+  { 228, 0, "TP",     "Total precipitation",                                        "m"                     },
+  { 229, 0, "IEWS",   "Instantaneous X surface stress",                             "N m**-2"               },
+  { 230, 0, "INSS",   "Instantaneous Y surface stress",                             "N m**-2"               },
+  { 231, 0, "ISHF",   "Instantaneous surface heat flux",                            "W m**-2"               },
+  { 232, 0, "IE",     "Instantaneous moisture flux",                                "kg m**-2 s"            },
+  { 233, 0, "ASQ",    "Apparent surface humidity",                                  "kg kg**-1"             },
+  { 234, 0, "LSRH",   "Logarithm of surface roughness length for heat",              NULL                   },
+  { 235, 0, "SKT",    "Skin temperature",                                           "K"                     },
+  { 236, 0, "STL4",   "Soil temperature level 4",                                   "K"                     },
+  { 237, 0, "SWL4",   "Soil wetness level 4",                                       "m"                     },
+  { 238, 0, "TSN",    "Temperature of snow layer",                                  "K"                     },
+  { 239, 0, "CSF",    "Convective snowfall",                                        "m of water equivalent" },
+  { 240, 0, "LSF",    "Large-scale snowfall",                                       "m of water equivalent" },
+  { 241, 0, "ACF",    "Accumulated cloud fraction tendency",                         NULL                   },
+  { 242, 0, "ALW",    "Accumulated liquid water tendency",                           NULL                   },
+  { 243, 0, "FAL",    "Forecast albedo",                                             NULL                   },
+  { 244, 0, "FSR",    "Forecast surface roughness",                                 "m"                     },
+  { 245, 0, "FLSR",   "Forecast log of surface roughness for heat",                  NULL                   },
+  { 246, 0, "CLWC",   "Cloud liquid water content",                                 "kg kg**-1"             },
+  { 247, 0, "CIWC",   "Cloud ice water content",                                    "kg kg**-1"             },
+  { 248, 0, "CC",     "Cloud cover",                                                 NULL                   },
+  { 249, 0, "AIW",    "Accumulated ice water tendency",                              NULL                   },
+  { 250, 0, "ICE",    "Ice age",                                                     NULL                   },
+  { 251, 0, "ATTE",   "Adiabatic tendency of temperature",                          "K"                     },
+  { 252, 0, "ATHE",   "Adiabatic tendency of humidity",                             "kg kg**-1"             },
+  { 253, 0, "ATZE",   "Adiabatic tendency of zonal wind",                           "m s**-1"               },
+  { 254, 0, "ATMW",   "Adiabatic tendency of meridional wind",                      "m s**-1"               },
 };
 
-static PAR remo[] = {
-  {  14, "FTKVM",     "turbulent transfer coefficient of momentum in the atmosphere",   NULL           },
-  {  15, "FTKVH",     "turbulent transfer coefficient of heat in the atmosphere",       NULL           },
-  {  38, "U10ER",     "10m u-velocity",                                                "m/s"           },
-  {  39, "V10ER",     "10m v-velocity",                                                "m/s"           },
-  {  40, "CAPE",      "convetive available potential energy",                           NULL           },
-  {  41, "GHPBL",     "height of the planetary boudary layer",                         "gpm"           },
-  {  42, "BETA",      "BETA",                                                           NULL           },
-  {  43, "WMINLOK",   "WMINLOK",                                                        NULL           },
-  {  44, "WMAXLOK",   "WMAXLOK",                                                        NULL           },
-  {  45, "VBM10M",    "maximum of the expected gust velocity near the surface",        "m/s"           },
-  {  46, "BFLHS",     "surface sensible heat flux",                                    "W/m**2"        },
-  {  47, "BFLQDS",    "surface latent heat flux",                                      "W/m**2"        },
-  {  48, "TMCM",      "turbulent transfer coefficient of momentum at the surface",      NULL           },
-  {  49, "TRSOL",     "TRSOL",                                                          NULL           },
-  {  50, "TMCH",      "turbulent transfer coefficient of heat at the surface",          NULL           },
-  {  51, "EMTEF",     "EMTEF",                                                          NULL           },
-  {  52, "TRSOF",     "TRSOF",                                                          NULL           },
-  {  53, "DRAIN",     "drainage",                                                      "mm"            },
-  {  54, "TSL",       "surface temperature (land)",                                    "K"             },
-  {  55, "TSW",       "surface temperature (water)",                                   "K"             },
-  {  56, "TSI",       "surface temperature (ice)",                                     "K"             },
-  {  57, "USTRL",     "surface u-stress (land)",                                       "Pa"            },
-  {  58, "USTRW",     "surface u-stress (water)",                                      "Pa"            },
-  {  59, "USTRI",     "surface u-stress (ice)",                                        "Pa"            },
-  {  60, "VSTRL",     "surface v-stress (land)",                                       "Pa"            },
-  {  61, "VSTRW",     "surface v-stress (water)",                                      "Pa"            },
-  {  62, "VSTRI",     "surface v-stress (ice)",                                        "Pa"            },
-  {  63, "EVAPL",     "surface evaporation (land)",                                    "mm"            },
-  {  64, "EVAPW",     "surface evaporation (water)",                                   "mm"            },
-  {  65, "EVAPI",     "surface evaporation (ice)",                                     "mm"            },
-  {  66, "AHFLL",     "surface latent heat flux (land)",                               "W/m**2"        },
-  {  67, "AHFLW",     "surface latent heat flux (water)",                              "W/m**2"        },
-  {  68, "AHFLI",     "surface latent heat flux (ice)",                                "W/m**2"        },
-  {  69, "AHFSL",     "surface sensible heat flux (land)",                             "W/m**2"        },
-  {  70, "AHFSW",     "surface sensible heat flux (water)",                            "W/m**2"        },
-  {  71, "AHFSI",     "surface sensible heat flux (ice)",                              "W/m**2"        },
-  {  72, "AZ0L",      "surface roughness length (land)",                               "m"             },
-  {  73, "AZ0W",      "surface roughness length (water)",                              "m"             },
-  {  74, "AZ0I",      "surface roughness length (ice)",                                "m"             },
-  {  75, "ALSOL",     "surface albedo (land)",                                         "fract."        },
-  {  76, "ALSOW",     "surface albedo (water)",                                        "fract."        },
-  {  77, "ALSOI",     "surface albedo (ice)",                                          "fract."        },
-  {  81, "TMCHL",     "turbulent transfer coefficient of heat at the surface (land)",   NULL           },
-  {  82, "TMCHW",     "turbulent transfer coefficient of heat at the surface (water)",  NULL           },
-  {  83, "TMCHI",     "turbulent transfer coefficient of heat at the surface (ice)",    NULL           },
-  {  84, "QDBL",      "specific humidity surface (land)",                              "kg/kg"         },
-  {  85, "QDBW",      "specific humidity surface (water)",                             "kg/kg"         },
-  {  86, "QDBI",      "specific humidity surface (ice)",                               "kg/kg"         },
-  {  87, "BFLHSL",    "surface sensible heat flux (land)",                             "W/m**2"        },
-  {  88, "BFLHSW",    "surface sensible heat flux (water)",                            "W/m**2"        },
-  {  89, "BFLHSI",    "surface sensible heat flux (ice)",                              "W/m**2"        },
-  {  90, "BFLQDSL",   "surface latent heat flux (land)",                               "W/m**2"        },
-  {  91, "BFLQDSW",   "surface latent heat flux (water)",                              "W/m**2"        },
-  {  92, "BFLQDSI",   "surface latent heat flux (ice)",                                "W/m**2"        },
-  {  93, "AHFICE",    "sea-ice: conductive heat",                                      "W/m"           },
-  {  94, "QRES",      "residual heat flux for melting sea ice",                        "W/m**2"        },
-  {  95, "SRFL",      "SRFL",                                                           NULL           },
-  {  96, "QDBOXS",    "horizontal transport of water vapour",                          "kg/m**2"       },
-  {  97, "QWBOXS",    "horizontal transport of cloud water",                           "kg/m**2"       },
-  {  98, "EKBOXS",    "horizontal transport of kinetic energy",                        "(3600*J)/m**2" },
-  {  99, "FHBOXS",    "horizontal transport of sensible heat",                         "(3600*J)/m**2" },
-  { 100, "FIBOXS",    "horizontal transport of potential energy",                      "(3600*J)/m**2" },
-  { 101, "TLAMBDA",   "heat conductivity of dry soil",                                 "W/(K*m)"       },
-  { 103, "DLAMBDA",   "parameter for increasing the heat conductivity of the soil",     NULL           },
-  { 104, "PORVOL",    "pore volume",                                                    NULL           },
-  { 105, "FCAP",      "field capacity of soil",                                         NULL           },
-  { 106, "WI3",       "fraction of frozen soil",                                        NULL           },
-  { 107, "WI4",       "fraction of frozen soil",                                        NULL           },
-  { 108, "WI5",       "fraction of frozen soil",                                        NULL           },
-  { 109, "WI",        "fraction of frozen soil",                                        NULL           },
-  { 110, "WICL",      "fraction of frozen soil",                                        NULL           },
-  { 112, "QDB",       "specific humidity surface",                                     "kg/kg"         },
-  { 129, "FIB",       "surface geopotential (orography)",                              "m"             },
-  { 130, "T",         "temperature",                                                   "K"             },
-  { 131, "U",         "u-velocity",                                                    "m/s"           },
-  { 132, "V",         "v-velocity",                                                    "m/s"           },
-  { 133, "QD",        "specific humidity",                                             "kg/kg"         },
-  { 134, "PS",        "Surface pressure",                                              "Pa"            },
-  { 135, "VERVEL",    "Vertical velocity",                                             "Pa/s"          },
-  { 138, "SVO",       "vorticity",                                                     "1/s"           },
-  { 139, "TS",        "surface temperature",                                           "K"             },
-  { 140, "WS",        "soil wetness",                                                  "m"             },
-  { 141, "SN",        "snow depth",                                                    "m"             },
-  { 142, "APRL",      "large scale precipitation",                                     "mm"            },
-  { 143, "APRC",      "convective  precipitation",                                     "mm"            },
-  { 144, "APRS",      "snow fall",                                                     "mm"            },
-  { 145, "VDIS",      "boundary layer dissipation",                                    "W/m**2"        },
-  { 146, "AHFS",      "surface sensible heat flux",                                    "W/m**2"        },
-  { 147, "AHFL",      "surface latent heat flux",                                      "W/m**2"        },
-  { 148, "STREAM",    "streamfunction",                                                "m**2/s"        },
-  { 149, "VELOPOT",   "velocity potential",                                            "m**2/s"        },
-  { 151, "PSRED",     "mean sea level pressure",                                       "Pa"            },
-  { 152, "LSP",       "log surface pressure",                                           NULL           },
-  { 153, "QW",        "liquid water content",                                          "kg/kg"         },
-  { 155, "SD",        "divergence",                                                    "1/s"           },
-  { 156, "FI",        "geopotential height",                                           "gpm"           },
-  { 159, "USTAR3",    "ustar**3",                                                      "m**3/s**3"     },
-  { 160, "RUNOFF",    "surface runoff",                                                "mm"            },
-  { 162, "ACLC",      "cloud cover",                                                   "fract."        },
-  { 163, "ACLCV",     "total cloud cover",                                             "fract."        },
-  { 164, "ACLCOV",    "total cloud cover",                                             "fract."        },
-  { 165, "U10",       "10m u-velocity",                                                "m/s"           },
-  { 166, "V10",       "10m v-velocity",                                                "m/s"           },
-  { 167, "TEMP2",     "2m temperature",                                                "K"             },
-  { 168, "DEW2",      "2m dew point temperature",                                      "K"             },
-  { 169, "TSURF",     "surface temperature (land)",                                    "K"             },
-  { 170, "TD",        "deep soil temperature",                                         "K"             },
-  { 171, "WIND10",    "10m windspeed",                                                 "m/s"           },
-  { 172, "BLA",       "land sea mask",                                                 "fract."        },
-  { 173, "AZ0",       "surface roughness length",                                      "m"             },
-  { 174, "ALB",       "surface background albedo",                                     "fract."        },
-  { 175, "ALBEDO",    "surface albedo",                                                "fract."        },
-  { 176, "SRADS",     "net surface solar radiation",                                   "W/m**2"        },
-  { 177, "TRADS",     "net surface thermal radiation",                                 "W/m**2"        },
-  { 178, "SRAD0",     "net top solar radiation",                                       "W/m**2"        },
-  { 179, "TRAD0",     "top thermal radiation (OLR)",                                   "W/m**2"        },
-  { 180, "USTR",      "surface u-stress",                                              "Pa"            },
-  { 181, "VSTR",      "surface v-stress",                                              "Pa"            },
-  { 182, "EVAP",      "surface evaporation",                                           "mm"            },
-  { 183, "TDCL",      "soil temperature",                                              "K"             },
-  { 185, "SRAFS",     "net surf. solar radiation   (clear sky)",                       "W/m**2"        },
-  { 186, "TRAFS",     "net surf. thermal radiation (clear sky)",                       "W/m**2"        },
-  { 187, "SRAF0",     "net top solar radiation     (clear sky)",                       "W/m**2"        },
-  { 188, "TRAF0",     "net top thermal radiation   (clear sky)",                       "W/m**2"        },
-  { 189, "SCLFS",     "surface solar cloud forcing",                                   "W/m**2"        },
-  { 190, "TCLFS",     "surface thermal cloud forcing",                                 "W/m**2"        },
-  { 191, "SCLF0",     "top solar cloud forcing",                                       "W/m**2"        },
-  { 192, "TCLF0",     "top thermal cloud forcing",                                     "W/m**2"        },
-  { 194, "WL",        "skin reservoir content",                                        "m"             },
-  { 195, "USTRGW",    "u-gravity wave stress",                                         "Pa"            },
-  { 196, "VSTRGW",    "v-gravity wave stress",                                         "Pa"            },
-  { 197, "VDISGW",    "gravity wave dissipation",                                      "W/m**2"        },
-  { 198, "VGRAT",     "vegetation ratio",                                               NULL           },
-  { 199, "VAROR",     "orographic variance (for surface runoff)",                       NULL           },
-  { 200, "VLT",       "leaf area index",                                                NULL           },
-  { 201, "T2MAX",     "maximum 2m-temperature",                                        "K"             },
-  { 202, "T2MIN",     "minimum 2m-temperature",                                        "K"             },
-  { 203, "SRAD0U",    "top solar radiation upward",                                    "W/m**2"        },
-  { 204, "SRADSU",    "surface solar radiation upward",                                "W/m**2"        },
-  { 205, "TRADSU",    "surface thermal radiation upward",                              "W/m**2"        },
-  { 206, "TSN",       "snow temperature",                                              "K"             },
-  { 207, "TD3",       "soil temperature",                                              "K"             },
-  { 208, "TD4",       "soil temperature",                                              "K"             },
-  { 209, "TD5",       "soil temperature",                                              "K"             },
-  { 210, "SEAICE",    "sea ice cover",                                                 "fract."        },
-  { 211, "SICED",     "sea ice depth",                                                 "m"             },
-  { 212, "FOREST",    "vegetation type",                                                NULL           },
-  { 213, "TEFF",      "(effective) sea-ice skin temperature",                          "K"             },
-  { 214, "TSMAX",     "maximum surface temperature",                                   "K"             },
-  { 215, "TSMIN",     "minimum surface temperature",                                   "K"             },
-  { 216, "WIMAX",     "maximum 10m-wind speed",                                        "m/s"           },
-  { 217, "TOPMAX",    "maximum height of convective cloud tops",                       "Pa"            },
-  { 218, "SNMEL",     "snow melt",                                                     "mm"            },
-  { 220, "TSLIN",     "land: residual surface heat budget",                            "W/m**2"        },
-  { 221, "DSNAC",     "snow depth change",                                             "mm"            },
-  { 222, "EMTER",     "EMTER",                                                          NULL           },
-  { 223, "ACLCAC",    "cloud cover",                                                   "fract."        },
-  { 224, "TKE",       "turbulent kinetic energy",                                       NULL           },
-  { 226, "FAO",       "FAO data set (soil data flags)",                                 NULL           },
-  { 227, "RGCGN",     "heat capacity of soil",                                          NULL           },
-  { 229, "WSMX",      "field capacity of soil",                                         NULL           },
-  { 230, "QVI",       "vertically integrated specific humidity",                       "kg/m**2"       },
-  { 231, "ALWCVI",    "vertically integrated liquid water cont.",                      "kg/m**2"       },
-  { 232, "GLAC",      "glacier mask",                                                   NULL           },
-  { 253, "PHI",       "latitude in real coordinates",                                  "degrees_north" },
-  { 254, "RLA",       "longitude in real coordinates",                                 "degrees_east"  },
-  { 259, "WINDSPEED", "windspeed (sqrt(u**2+v**2))",                                    NULL           },
-  { 260, "PRECIP",    "total precipitation",                                            NULL           },
+static const PAR remo[] = {
+  {  14, 0, "FTKVM",     "turbulent transfer coefficient of momentum in the atmosphere",   NULL           },
+  {  15, 0, "FTKVH",     "turbulent transfer coefficient of heat in the atmosphere",       NULL           },
+  {  38, 0, "U10ER",     "10m u-velocity",                                                "m/s"           },
+  {  39, 0, "V10ER",     "10m v-velocity",                                                "m/s"           },
+  {  40, 0, "CAPE",      "convetive available potential energy",                           NULL           },
+  {  41, 0, "GHPBL",     "height of the planetary boudary layer",                         "gpm"           },
+  {  42, 0, "BETA",      "BETA",                                                           NULL           },
+  {  43, 0, "WMINLOK",   "WMINLOK",                                                        NULL           },
+  {  44, 0, "WMAXLOK",   "WMAXLOK",                                                        NULL           },
+  {  45, 0, "VBM10M",    "maximum of the expected gust velocity near the surface",        "m/s"           },
+  {  46, 0, "BFLHS",     "surface sensible heat flux",                                    "W/m**2"        },
+  {  47, 0, "BFLQDS",    "surface latent heat flux",                                      "W/m**2"        },
+  {  48, 0, "TMCM",      "turbulent transfer coefficient of momentum at the surface",      NULL           },
+  {  49, 0, "TRSOL",     "TRSOL",                                                          NULL           },
+  {  50, 0, "TMCH",      "turbulent transfer coefficient of heat at the surface",          NULL           },
+  {  51, 0, "EMTEF",     "EMTEF",                                                          NULL           },
+  {  52, 0, "TRSOF",     "TRSOF",                                                          NULL           },
+  {  53, 0, "DRAIN",     "drainage",                                                      "mm"            },
+  {  54, 0, "TSL",       "surface temperature (land)",                                    "K"             },
+  {  55, 0, "TSW",       "surface temperature (water)",                                   "K"             },
+  {  56, 0, "TSI",       "surface temperature (ice)",                                     "K"             },
+  {  57, 0, "USTRL",     "surface u-stress (land)",                                       "Pa"            },
+  {  58, 0, "USTRW",     "surface u-stress (water)",                                      "Pa"            },
+  {  59, 0, "USTRI",     "surface u-stress (ice)",                                        "Pa"            },
+  {  60, 0, "VSTRL",     "surface v-stress (land)",                                       "Pa"            },
+  {  61, 0, "VSTRW",     "surface v-stress (water)",                                      "Pa"            },
+  {  62, 0, "VSTRI",     "surface v-stress (ice)",                                        "Pa"            },
+  {  63, 0, "EVAPL",     "surface evaporation (land)",                                    "mm"            },
+  {  64, 0, "EVAPW",     "surface evaporation (water)",                                   "mm"            },
+  {  65, 0, "EVAPI",     "surface evaporation (ice)",                                     "mm"            },
+  {  66, 0, "AHFLL",     "surface latent heat flux (land)",                               "W/m**2"        },
+  {  67, 0, "AHFLW",     "surface latent heat flux (water)",                              "W/m**2"        },
+  {  68, 0, "AHFLI",     "surface latent heat flux (ice)",                                "W/m**2"        },
+  {  69, 0, "AHFSL",     "surface sensible heat flux (land)",                             "W/m**2"        },
+  {  70, 0, "AHFSW",     "surface sensible heat flux (water)",                            "W/m**2"        },
+  {  71, 0, "AHFSI",     "surface sensible heat flux (ice)",                              "W/m**2"        },
+  {  72, 0, "AZ0L",      "surface roughness length (land)",                               "m"             },
+  {  73, 0, "AZ0W",      "surface roughness length (water)",                              "m"             },
+  {  74, 0, "AZ0I",      "surface roughness length (ice)",                                "m"             },
+  {  75, 0, "ALSOL",     "surface albedo (land)",                                         "fract."        },
+  {  76, 0, "ALSOW",     "surface albedo (water)",                                        "fract."        },
+  {  77, 0, "ALSOI",     "surface albedo (ice)",                                          "fract."        },
+  {  81, 0, "TMCHL",     "turbulent transfer coefficient of heat at the surface (land)",   NULL           },
+  {  82, 0, "TMCHW",     "turbulent transfer coefficient of heat at the surface (water)",  NULL           },
+  {  83, 0, "TMCHI",     "turbulent transfer coefficient of heat at the surface (ice)",    NULL           },
+  {  84, 0, "QDBL",      "specific humidity surface (land)",                              "kg/kg"         },
+  {  85, 0, "QDBW",      "specific humidity surface (water)",                             "kg/kg"         },
+  {  86, 0, "QDBI",      "specific humidity surface (ice)",                               "kg/kg"         },
+  {  87, 0, "BFLHSL",    "surface sensible heat flux (land)",                             "W/m**2"        },
+  {  88, 0, "BFLHSW",    "surface sensible heat flux (water)",                            "W/m**2"        },
+  {  89, 0, "BFLHSI",    "surface sensible heat flux (ice)",                              "W/m**2"        },
+  {  90, 0, "BFLQDSL",   "surface latent heat flux (land)",                               "W/m**2"        },
+  {  91, 0, "BFLQDSW",   "surface latent heat flux (water)",                              "W/m**2"        },
+  {  92, 0, "BFLQDSI",   "surface latent heat flux (ice)",                                "W/m**2"        },
+  {  93, 0, "AHFICE",    "sea-ice: conductive heat",                                      "W/m"           },
+  {  94, 0, "QRES",      "residual heat flux for melting sea ice",                        "W/m**2"        },
+  {  95, 0, "SRFL",      "SRFL",                                                           NULL           },
+  {  96, 0, "QDBOXS",    "horizontal transport of water vapour",                          "kg/m**2"       },
+  {  97, 0, "QWBOXS",    "horizontal transport of cloud water",                           "kg/m**2"       },
+  {  98, 0, "EKBOXS",    "horizontal transport of kinetic energy",                        "(3600*J)/m**2" },
+  {  99, 0, "FHBOXS",    "horizontal transport of sensible heat",                         "(3600*J)/m**2" },
+  { 100, 0, "FIBOXS",    "horizontal transport of potential energy",                      "(3600*J)/m**2" },
+  { 101, 0, "TLAMBDA",   "heat conductivity of dry soil",                                 "W/(K*m)"       },
+  { 103, 0, "DLAMBDA",   "parameter for increasing the heat conductivity of the soil",     NULL           },
+  { 104, 0, "PORVOL",    "pore volume",                                                    NULL           },
+  { 105, 0, "FCAP",      "field capacity of soil",                                         NULL           },
+  { 106, 0, "WI3",       "fraction of frozen soil",                                        NULL           },
+  { 107, 0, "WI4",       "fraction of frozen soil",                                        NULL           },
+  { 108, 0, "WI5",       "fraction of frozen soil",                                        NULL           },
+  { 109, 0, "WI",        "fraction of frozen soil",                                        NULL           },
+  { 110, 0, "WICL",      "fraction of frozen soil",                                        NULL           },
+  { 112, 0, "QDB",       "specific humidity surface",                                     "kg/kg"         },
+  { 129, 0, "FIB",       "surface geopotential (orography)",                              "m"             },
+  { 130, 0, "T",         "temperature",                                                   "K"             },
+  { 131, 0, "U",         "u-velocity",                                                    "m/s"           },
+  { 132, 0, "V",         "v-velocity",                                                    "m/s"           },
+  { 133, 0, "QD",        "specific humidity",                                             "kg/kg"         },
+  { 134, 0, "PS",        "Surface pressure",                                              "Pa"            },
+  { 135, 0, "VERVEL",    "Vertical velocity",                                             "Pa/s"          },
+  { 138, 0, "SVO",       "vorticity",                                                     "1/s"           },
+  { 139, 0, "TS",        "surface temperature",                                           "K"             },
+  { 140, 0, "WS",        "soil wetness",                                                  "m"             },
+  { 141, 0, "SN",        "snow depth",                                                    "m"             },
+  { 142, 0, "APRL",      "large scale precipitation",                                     "mm"            },
+  { 143, 0, "APRC",      "convective  precipitation",                                     "mm"            },
+  { 144, 0, "APRS",      "snow fall",                                                     "mm"            },
+  { 145, 0, "VDIS",      "boundary layer dissipation",                                    "W/m**2"        },
+  { 146, 0, "AHFS",      "surface sensible heat flux",                                    "W/m**2"        },
+  { 147, 0, "AHFL",      "surface latent heat flux",                                      "W/m**2"        },
+  { 148, 0, "STREAM",    "streamfunction",                                                "m**2/s"        },
+  { 149, 0, "VELOPOT",   "velocity potential",                                            "m**2/s"        },
+  { 151, 0, "PSRED",     "mean sea level pressure",                                       "Pa"            },
+  { 152, 0, "LSP",       "log surface pressure",                                           NULL           },
+  { 153, 0, "QW",        "liquid water content",                                          "kg/kg"         },
+  { 155, 0, "SD",        "divergence",                                                    "1/s"           },
+  { 156, 0, "FI",        "geopotential height",                                           "gpm"           },
+  { 159, 0, "USTAR3",    "ustar**3",                                                      "m**3/s**3"     },
+  { 160, 0, "RUNOFF",    "surface runoff",                                                "mm"            },
+  { 162, 0, "ACLC",      "cloud cover",                                                   "fract."        },
+  { 163, 0, "ACLCV",     "total cloud cover",                                             "fract."        },
+  { 164, 0, "ACLCOV",    "total cloud cover",                                             "fract."        },
+  { 165, 0, "U10",       "10m u-velocity",                                                "m/s"           },
+  { 166, 0, "V10",       "10m v-velocity",                                                "m/s"           },
+  { 167, 0, "TEMP2",     "2m temperature",                                                "K"             },
+  { 168, 0, "DEW2",      "2m dew point temperature",                                      "K"             },
+  { 169, 0, "TSURF",     "surface temperature (land)",                                    "K"             },
+  { 170, 0, "TD",        "deep soil temperature",                                         "K"             },
+  { 171, 0, "WIND10",    "10m windspeed",                                                 "m/s"           },
+  { 172, 0, "BLA",       "land sea mask",                                                 "fract."        },
+  { 173, 0, "AZ0",       "surface roughness length",                                      "m"             },
+  { 174, 0, "ALB",       "surface background albedo",                                     "fract."        },
+  { 175, 0, "ALBEDO",    "surface albedo",                                                "fract."        },
+  { 176, 0, "SRADS",     "net surface solar radiation",                                   "W/m**2"        },
+  { 177, 0, "TRADS",     "net surface thermal radiation",                                 "W/m**2"        },
+  { 178, 0, "SRAD0",     "net top solar radiation",                                       "W/m**2"        },
+  { 179, 0, "TRAD0",     "top thermal radiation (OLR)",                                   "W/m**2"        },
+  { 180, 0, "USTR",      "surface u-stress",                                              "Pa"            },
+  { 181, 0, "VSTR",      "surface v-stress",                                              "Pa"            },
+  { 182, 0, "EVAP",      "surface evaporation",                                           "mm"            },
+  { 183, 0, "TDCL",      "soil temperature",                                              "K"             },
+  { 185, 0, "SRAFS",     "net surf. solar radiation   (clear sky)",                       "W/m**2"        },
+  { 186, 0, "TRAFS",     "net surf. thermal radiation (clear sky)",                       "W/m**2"        },
+  { 187, 0, "SRAF0",     "net top solar radiation     (clear sky)",                       "W/m**2"        },
+  { 188, 0, "TRAF0",     "net top thermal radiation   (clear sky)",                       "W/m**2"        },
+  { 189, 0, "SCLFS",     "surface solar cloud forcing",                                   "W/m**2"        },
+  { 190, 0, "TCLFS",     "surface thermal cloud forcing",                                 "W/m**2"        },
+  { 191, 0, "SCLF0",     "top solar cloud forcing",                                       "W/m**2"        },
+  { 192, 0, "TCLF0",     "top thermal cloud forcing",                                     "W/m**2"        },
+  { 194, 0, "WL",        "skin reservoir content",                                        "m"             },
+  { 195, 0, "USTRGW",    "u-gravity wave stress",                                         "Pa"            },
+  { 196, 0, "VSTRGW",    "v-gravity wave stress",                                         "Pa"            },
+  { 197, 0, "VDISGW",    "gravity wave dissipation",                                      "W/m**2"        },
+  { 198, 0, "VGRAT",     "vegetation ratio",                                               NULL           },
+  { 199, 0, "VAROR",     "orographic variance (for surface runoff)",                       NULL           },
+  { 200, 0, "VLT",       "leaf area index",                                                NULL           },
+  { 201, 0, "T2MAX",     "maximum 2m-temperature",                                        "K"             },
+  { 202, 0, "T2MIN",     "minimum 2m-temperature",                                        "K"             },
+  { 203, 0, "SRAD0U",    "top solar radiation upward",                                    "W/m**2"        },
+  { 204, 0, "SRADSU",    "surface solar radiation upward",                                "W/m**2"        },
+  { 205, 0, "TRADSU",    "surface thermal radiation upward",                              "W/m**2"        },
+  { 206, 0, "TSN",       "snow temperature",                                              "K"             },
+  { 207, 0, "TD3",       "soil temperature",                                              "K"             },
+  { 208, 0, "TD4",       "soil temperature",                                              "K"             },
+  { 209, 0, "TD5",       "soil temperature",                                              "K"             },
+  { 210, 0, "SEAICE",    "sea ice cover",                                                 "fract."        },
+  { 211, 0, "SICED",     "sea ice depth",                                                 "m"             },
+  { 212, 0, "FOREST",    "vegetation type",                                                NULL           },
+  { 213, 0, "TEFF",      "(effective) sea-ice skin temperature",                          "K"             },
+  { 214, 0, "TSMAX",     "maximum surface temperature",                                   "K"             },
+  { 215, 0, "TSMIN",     "minimum surface temperature",                                   "K"             },
+  { 216, 0, "WIMAX",     "maximum 10m-wind speed",                                        "m/s"           },
+  { 217, 0, "TOPMAX",    "maximum height of convective cloud tops",                       "Pa"            },
+  { 218, 0, "SNMEL",     "snow melt",                                                     "mm"            },
+  { 220, 0, "TSLIN",     "land: residual surface heat budget",                            "W/m**2"        },
+  { 221, 0, "DSNAC",     "snow depth change",                                             "mm"            },
+  { 222, 0, "EMTER",     "EMTER",                                                          NULL           },
+  { 223, 0, "ACLCAC",    "cloud cover",                                                   "fract."        },
+  { 224, 0, "TKE",       "turbulent kinetic energy",                                       NULL           },
+  { 226, 0, "FAO",       "FAO data set (soil data flags)",                                 NULL           },
+  { 227, 0, "RGCGN",     "heat capacity of soil",                                          NULL           },
+  { 229, 0, "WSMX",      "field capacity of soil",                                         NULL           },
+  { 230, 0, "QVI",       "vertically integrated specific humidity",                       "kg/m**2"       },
+  { 231, 0, "ALWCVI",    "vertically integrated liquid water cont.",                      "kg/m**2"       },
+  { 232, 0, "GLAC",      "glacier mask",                                                   NULL           },
+  { 253, 0, "PHI",       "latitude in real coordinates",                                  "degrees_north" },
+  { 254, 0, "RLA",       "longitude in real coordinates",                                 "degrees_east"  },
+  { 259, 0, "WINDSPEED", "windspeed (sqrt(u**2+v**2))",                                    NULL           },
+  { 260, 0, "PRECIP",    "total precipitation",                                            NULL           },
 };
 
-static PAR cosmo002[] = {
-  {   1, "P",         "pressure",                                          "Pa"         },
-  {   2, "PMSL",      "mean sea level pressure",                           "Pa"         },
-  {   3, "DPSDT",     "surface pressure change",                           "Pa s-1"     },
-  {   6, "FI",        "geopotential",                                      "m2 s-2"     },
-  {   8, "HH",        "height",                                            "m"          },
-  {  10, "TO3",       "vertical integrated ozone content",                 "Dobson"     },
-  {  11, "T",         "temperature",                                       "K"          },
-  {  15, "TMAX",      "2m maximum temperature",                            "K"          },
-  {  16, "TMIN",      "2m minimum temperature",                            "K"          },
-  {  17, "TD",        "2m dew point temperature",                          "K"          },
-  {  31, "DD",        "undefined",                                         "undefined"  },
-  {  32, "FF",        "undefined",                                         "undefined"  },
-  {  33, "U",         "U-component of wind",                               "m s-1"      },
-  {  34, "V",         "V-component of wind",                               "m s-1"      },
-  {  39, "OMEGA",     "omega",                                             "Pa s-1"     },
-  {  40, "W",         "vertical wind velocity",                            "m s-1"      },
-  {  51, "QV",        "specific humidity",                                 "kg kg-1"    },
-  {  52, "RELHUM",    "relative humidity",                                 "%"          },
-  {  54, "TQV",       "precipitable water",                                "kg m-2"     },
-  {  57, "AEVAP",     "surface evaporation",                               "kg m-2"     },
-  {  58, "TQI",       "vertical integrated cloud ice",                     "kg m-2"     },
-  {  59, "TOT_PR",    "total precipitation rate",                          "kg m-2 s-1" },
-  {  61, "TOT_PREC",  "total precipitation amount",                        "kg m-2"     },
-  {  65, "W_SNOW",    "surface snow amount",                               "m"          },
-  {  66, "H_SNOW",    "thickness of snow",                                 "m"          },
-  {  71, "CLCT",      "total cloud cover",                                 "1"          },
-  {  72, "CLC_CON",   "convective cloud area fraction",                    "1"          },
-  {  73, "CLCL",      "low cloud cover",                                   "1"          },
-  {  74, "CLCM",      "medium cloud cover",                                "1"          },
-  {  75, "CLCH",      "high cloud cover",                                  "1"          },
-  {  76, "TQC",       "vertical integrated cloud water",                   "kg m-2"     },
-  {  78, "SNOW_CON",  "convective snowfall",                               "kg m-2"     },
-  {  79, "SNOW_GSP",  "large scale snowfall",                              "kg m-2"     },
-  {  81, "FR_LAND",   "land-sea fraction",                                 "1"          },
-  {  83, "Z0",        "surface roughness length",                          "m"          },
-  {  84, "ALB_RAD",   "surface albedo",                                    "1"          },
-  {  85, "TSOIL",     "soil surface temperature",                          "K"          },
-  {  86, "WSOIL",     "water content of 1. soil layer",                    "m"          },
-  {  87, "PLCOV",     "vegetation area fraction",                          "1"          },
-  {  90, "RUNOFF",    "subsurface runoff",                                 "kg m-2"     },
-  {  91, "FR_ICE",    "sea ice area fraction",                             "1"          },
-  {  92, "H_ICE",     "sea ice thickness",                                 "m"          },
-  { 111, "ASOB",      "averaged surface net downward shortwave radiation", "W m-2"      },
-  { 112, "ATHB",      "averaged surface net downward longwave radiation",  "W m-2"      },
-  { 113, "ASOB",      "averaged TOA net downward shortwave radiation",     "W m-2"      },
-  { 114, "ATHB",      "averaged TOA outgoing longwave radiation",          "W m-2"      },
-  { 115, "ASWDIR",    "direct downward sw radiation at the surface",       "W m-2"      },
-  { 116, "ASWDIFD",   "diffuse downward sw radiation at the surface",      "W m-2"      },
-  { 117, "ASWDIFU",   "diffuse upwnward sw radiation at the surface",      "W m-2"      },
-  { 118, "ALWD",      "downward lw radiation at the surface",              "W m-2"      },
-  { 119, "ALWU",      "upward lw radiation at the surface",                "W m-2"      },
-  { 121, "ALHFL",     "averaged surface latent heat flux",                 "W m-2"      },
-  { 122, "ASHFL",     "averaged surface sensible heat flux",               "W m-2"      },
-  { 124, "AUMFL",     "averaged eastward stress",                          "Pa"         },
-  { 125, "AVMFL",     "averaged northward stress",                         "Pa"         },
-  { 128, "SUNSH",     "undefined",                                         "undefined"  },
-  { 129, "SUNSH2",    "undefined",                                         "undefined"  },
-  { 130, "SUN_SUM",   "undefined",                                         "undefined"  },
-  { 131, "SUN_SUM2",  "undefined",                                         "undefined"  },
-  { 133, "FCOR",      "undefined",                                         "undefined"  },
-  { 134, "SKYVIEW",   "sky-view factor",                                   "1"          },
-  { 137, "SWDIR_COR", "topo correction of direct solar radiarion",         "1"          },
+static const PAR cosmo002[] = {
+  {   1, 0, "P",         "pressure",                                          "Pa"         },
+  {   2, 0, "PMSL",      "mean sea level pressure",                           "Pa"         },
+  {   3, 0, "DPSDT",     "surface pressure change",                           "Pa s-1"     },
+  {   6, 0, "FI",        "geopotential",                                      "m2 s-2"     },
+  {   8, 0, "HH",        "height",                                            "m"          },
+  {  10, 0, "TO3",       "vertical integrated ozone content",                 "Dobson"     },
+  {  11, 0, "T",         "temperature",                                       "K"          },
+  {  15, 0, "TMAX",      "2m maximum temperature",                            "K"          },
+  {  16, 0, "TMIN",      "2m minimum temperature",                            "K"          },
+  {  17, 0, "TD",        "2m dew point temperature",                          "K"          },
+  {  31, 0, "DD",        "undefined",                                         "undefined"  },
+  {  32, 0, "FF",        "undefined",                                         "undefined"  },
+  {  33, 0, "U",         "U-component of wind",                               "m s-1"      },
+  {  34, 0, "V",         "V-component of wind",                               "m s-1"      },
+  {  39, 0, "OMEGA",     "omega",                                             "Pa s-1"     },
+  {  40, 0, "W",         "vertical wind velocity",                            "m s-1"      },
+  {  51, 0, "QV",        "specific humidity",                                 "kg kg-1"    },
+  {  52, 0, "RELHUM",    "relative humidity",                                 "%"          },
+  {  54, 0, "TQV",       "precipitable water",                                "kg m-2"     },
+  {  57, 0, "AEVAP",     "surface evaporation",                               "kg m-2"     },
+  {  58, 0, "TQI",       "vertical integrated cloud ice",                     "kg m-2"     },
+  {  59, 0, "TOT_PR",    "total precipitation rate",                          "kg m-2 s-1" },
+  {  61, 0, "TOT_PREC",  "total precipitation amount",                        "kg m-2"     },
+  {  65, 0, "W_SNOW",    "surface snow amount",                               "m"          },
+  {  66, 0, "H_SNOW",    "thickness of snow",                                 "m"          },
+  {  71, 0, "CLCT",      "total cloud cover",                                 "1"          },
+  {  72, 0, "CLC_CON",   "convective cloud area fraction",                    "1"          },
+  {  73, 0, "CLCL",      "low cloud cover",                                   "1"          },
+  {  74, 0, "CLCM",      "medium cloud cover",                                "1"          },
+  {  75, 0, "CLCH",      "high cloud cover",                                  "1"          },
+  {  76, 0, "TQC",       "vertical integrated cloud water",                   "kg m-2"     },
+  {  78, 0, "SNOW_CON",  "convective snowfall",                               "kg m-2"     },
+  {  79, 0, "SNOW_GSP",  "large scale snowfall",                              "kg m-2"     },
+  {  81, 0, "FR_LAND",   "land-sea fraction",                                 "1"          },
+  {  83, 0, "Z0",        "surface roughness length",                          "m"          },
+  {  84, 0, "ALB_RAD",   "surface albedo",                                    "1"          },
+  {  85, 0, "TSOIL",     "soil surface temperature",                          "K"          },
+  {  86, 0, "WSOIL",     "water content of 1. soil layer",                    "m"          },
+  {  87, 0, "PLCOV",     "vegetation area fraction",                          "1"          },
+  {  90, 0, "RUNOFF",    "subsurface runoff",                                 "kg m-2"     },
+  {  91, 0, "FR_ICE",    "sea ice area fraction",                             "1"          },
+  {  92, 0, "H_ICE",     "sea ice thickness",                                 "m"          },
+  { 111, 0, "ASOB",      "averaged surface net downward shortwave radiation", "W m-2"      },
+  { 112, 0, "ATHB",      "averaged surface net downward longwave radiation",  "W m-2"      },
+  { 113, 0, "ASOB",      "averaged TOA net downward shortwave radiation",     "W m-2"      },
+  { 114, 0, "ATHB",      "averaged TOA outgoing longwave radiation",          "W m-2"      },
+  { 115, 0, "ASWDIR",    "direct downward sw radiation at the surface",       "W m-2"      },
+  { 116, 0, "ASWDIFD",   "diffuse downward sw radiation at the surface",      "W m-2"      },
+  { 117, 0, "ASWDIFU",   "diffuse upwnward sw radiation at the surface",      "W m-2"      },
+  { 118, 0, "ALWD",      "downward lw radiation at the surface",              "W m-2"      },
+  { 119, 0, "ALWU",      "upward lw radiation at the surface",                "W m-2"      },
+  { 121, 0, "ALHFL",     "averaged surface latent heat flux",                 "W m-2"      },
+  { 122, 0, "ASHFL",     "averaged surface sensible heat flux",               "W m-2"      },
+  { 124, 0, "AUMFL",     "averaged eastward stress",                          "Pa"         },
+  { 125, 0, "AVMFL",     "averaged northward stress",                         "Pa"         },
+  { 128, 0, "SUNSH",     "undefined",                                         "undefined"  },
+  { 129, 0, "SUNSH2",    "undefined",                                         "undefined"  },
+  { 130, 0, "SUN_SUM",   "undefined",                                         "undefined"  },
+  { 131, 0, "SUN_SUM2",  "undefined",                                         "undefined"  },
+  { 133, 0, "FCOR",      "undefined",                                         "undefined"  },
+  { 134, 0, "SKYVIEW",   "sky-view factor",                                   "1"          },
+  { 137, 0, "SWDIR_COR", "topo correction of direct solar radiarion",         "1"          },
 };
 
-static PAR cosmo201[] = {
-  {   5, "APAB",      "&",                                                         "W m-2"      },
-  {  13, "SOHR_RAD",  "&",                                                         "K s-1"      },
-  {  14, "THHR_RAD",  "&",                                                         "K s-1"      },
-  {  20, "DURSUN",    "duration of sunshine",                                      "s"          },
-  {  29, "CLC",       "cloud area fraction",                                       "1"          },
-  {  30, "CLC_SGS",   "grid scale cloud area fraction",                            "1"          },
-  {  31, "QC",        "specific cloud liquid water content",                       "kg kg-1"    },
-  {  33, "QI",        "specific cloud ice content",                                "kg kg-1"    },
-  {  35, "QR",        "specific rain content",                                     "kg kg-1"    },
-  {  36, "QS",        "specific snow content",                                     "kg kg-1"    },
-  {  37, "TQR",       "total rain water content vertically integrated",            "kg m-2"     },
-  {  38, "TQS",       "total snow content vertically integrated",                  "kg m-2"     },
-  {  39, "QG",        "specific graupel content",                                  "kg kg-1"    },
-  {  40, "TQG",       "total graupel content vertically integrated",               "kg m-2"     },
-  {  41, "TWATER",    "cloud condensed water content",                             "kg m-2"     },
-  {  42, "TDIV_HUM",  "atmosphere water divergence",                               "kg m-2"     },
-  {  43, "QC_RAD",    "sub scale specific cloud liquid water content",             "kg kg-1"    },
-  {  44, "QI_RAD",    "sub scale specific cloud ice content",                      "kg kg-1"    },
-  {  61, "CLW_CON",   "convective cloud liquid water",                             "1"          },
-  {  68, "HBAS_CON",  "height of convective cloud base",                           "m"          },
-  {  69, "HTOP_CON",  "height of convective cloud top",                            "m"          },
-  {  70, "HBAS_CONI", "height of convective cloud base",                           "m"          },
-  {  71, "HTOP_CONI", "height of convective cloud top",                            "m"          },
-  {  72, "BAS_CON",   "index of convective cloud base",                            "1"          },
-  {  73, "TOP_CON",   "index of convective cloud top",                             "1"          },
-  {  74, "DT_CON",    "convective tendency of temperature",                        "K s-1"      },
-  {  75, "DQV_CON",   "convective tendency of specific humidity",                  "s-1"        },
-  {  78, "DU_CON",    "convective tendency of u-wind component",                   "m s-2"      },
-  {  79, "DV_CON",    "convective tendency of v-wind component",                   "m s-2"      },
-  {  82, "HTOP_DC",   "height of dry convection top",                              "m"          },
-  {  84, "HZEROCL",   "height of freezing level",                                  "m"          },
-  {  85, "SNOWLMT",   "height of the snow fall limit in m above sea level",        "m"          },
-  {  86, "HCBAS",     "height of cloud base",                                      "m"          },
-  {  87, "HCTOP",     "height of cloud top",                                       "m"          },
-  {  91, "C_T_LK",    "&",                                                         "1"          },
-  {  92, "GAMSO_LK",  "&",                                                         "m-1"        },
-  {  93, "DP_BS_LK",  "&",                                                         "m"          },
-  {  94, "H_B1_LK",   "&",                                                         "m"          },
-  {  95, "H_ML_LK",   "&",                                                         "m"          },
-  {  96, "DEPTH_LK",  "lake depth",                                                "m"          },
-  {  97, "FETCH_LK",  "wind fetch over lake",                                      "m"          },
-  {  99, "QRS",       "precipitation water (water loading)",                       "1"          },
-  { 100, "PRR_GSP",   "mass flux density of large scale rainfall",                 "kg m-2 s-1" },
-  { 101, "PRS_GSP",   "mass flux density of large scale snowfall",                 "kg m-2 s-1" },
-  { 102, "RAIN_GSP",  "large scale rainfall",                                      "kg m-2"     },
-  { 111, "PRR_CON",   "mass flux density of convective rainfall",                  "kg m-2 s-1" },
-  { 112, "PRS_CON",   "mass flux density of convective snowfall",                  "kg m-2 s-1" },
-  { 113, "RAIN_CON",  "convective rainfall",                                       "kg m-2"     },
-  { 129, "FRESHSNW",  "freshness of snow",                                         "undefined"  },
-  { 131, "PRG_GSP",   "mass flux density of large scale graupel",                  "kg m-2 s-1" },
-  { 132, "GRAU_GSP",  "large scale graupel",                                       "kg m-2"     },
-  { 133, "RHO_SNOW",  "density of snow",                                           "kg m-3"     },
-  { 139, "PP",        "deviation from reference pressure",                         "Pa"         },
-  { 140, "RCLD",      "standard deviation of saturation deficit",                  "undefined"  },
-  { 143, "CAPE_MU",   "cape of most unstable parcel",                              "J kg-1"     },
-  { 144, "CIN_MU",    "convective inhibition of most unstable parcel",             "J kg-1"     },
-  { 145, "CAPE_ML",   "cape of mean surface layer parcel",                         "J kg-1"     },
-  { 146, "CIN_ML",    "convective inhibition of mean surface layer parcel",        "J kg-1"     },
-  { 147, "TKE_CON",   "convective turbulent kinetic energy",                       "undefined"  },
-  { 148, "TKETENS",   "tendency of turbulent kinetic energy",                      "undefined"  },
-  { 152, "TKE",       "turbulent kinetic energy",                                  "m2 s-2"     },
-  { 153, "TKVM",      "diffusion coefficient of momentum",                         "m2 s-1"     },
-  { 154, "TKVH",      "diffusion coefficient of heat",                             "m2 s-1"     },
-  { 170, "TCM",       "drag coefficient of momentum",                              "1"          },
-  { 171, "TCH",       "drag coefficient of heat",                                  "1"          },
-  { 187, "VMAX",      "maximum turbulent wind gust in 10m",                        "m s-1"      },
-  { 190, "TSOIL",     "&",                                                         "K"          },
-  { 191, "TSOIL",     "&",                                                         "K"          },
-  { 192, "TSOIL",     "&",                                                         "K"          },
-  { 193, "TSOIL",     "mixed layer temperature",                                   "K"          },
-  { 194, "TSOIL",     "mean temperature of water column",                          "K"          },
-  { 197, "TSOIL",     "soil temperature",                                          "K"          },
-  { 198, "W_SO",      "soil water content",                                        "m"          },
-  { 199, "W_SO_ICE",  "soil frozen water content",                                 "m"          },
-  { 200, "W_I",       "canopy water amount",                                       "m"          },
-  { 203, "TSOIL",     "snow surface temperature",                                  "K"          },
-  { 215, "TSOIL",     "temperature of ice upper surface",                          "K"          },
-  { 230, "dBZ",       "unattenuated radar reflectivity in Rayleigh approximation", "1"          },
-  { 240, "MFLX_CON",  "convective mass flux density",                              "kg m-2 s-1" },
-  { 241, "CAPE_CON",  "&",                                                         "J kg-1"     },
-  { 243, "QCVG_CON",  "&",                                                         "s-1"        },
+static const PAR cosmo201[] = {
+  {   5, 0, "APAB",      "&",                                                         "W m-2"      },
+  {  13, 0, "SOHR_RAD",  "&",                                                         "K s-1"      },
+  {  14, 0, "THHR_RAD",  "&",                                                         "K s-1"      },
+  {  20, 0, "DURSUN",    "duration of sunshine",                                      "s"          },
+  {  29, 0, "CLC",       "cloud area fraction",                                       "1"          },
+  {  30, 0, "CLC_SGS",   "grid scale cloud area fraction",                            "1"          },
+  {  31, 0, "QC",        "specific cloud liquid water content",                       "kg kg-1"    },
+  {  33, 0, "QI",        "specific cloud ice content",                                "kg kg-1"    },
+  {  35, 0, "QR",        "specific rain content",                                     "kg kg-1"    },
+  {  36, 0, "QS",        "specific snow content",                                     "kg kg-1"    },
+  {  37, 0, "TQR",       "total rain water content vertically integrated",            "kg m-2"     },
+  {  38, 0, "TQS",       "total snow content vertically integrated",                  "kg m-2"     },
+  {  39, 0, "QG",        "specific graupel content",                                  "kg kg-1"    },
+  {  40, 0, "TQG",       "total graupel content vertically integrated",               "kg m-2"     },
+  {  41, 0, "TWATER",    "cloud condensed water content",                             "kg m-2"     },
+  {  42, 0, "TDIV_HUM",  "atmosphere water divergence",                               "kg m-2"     },
+  {  43, 0, "QC_RAD",    "sub scale specific cloud liquid water content",             "kg kg-1"    },
+  {  44, 0, "QI_RAD",    "sub scale specific cloud ice content",                      "kg kg-1"    },
+  {  61, 0, "CLW_CON",   "convective cloud liquid water",                             "1"          },
+  {  68, 0, "HBAS_CON",  "height of convective cloud base",                           "m"          },
+  {  69, 0, "HTOP_CON",  "height of convective cloud top",                            "m"          },
+  {  70, 0, "HBAS_CONI", "height of convective cloud base",                           "m"          },
+  {  71, 0, "HTOP_CONI", "height of convective cloud top",                            "m"          },
+  {  72, 0, "BAS_CON",   "index of convective cloud base",                            "1"          },
+  {  73, 0, "TOP_CON",   "index of convective cloud top",                             "1"          },
+  {  74, 0, "DT_CON",    "convective tendency of temperature",                        "K s-1"      },
+  {  75, 0, "DQV_CON",   "convective tendency of specific humidity",                  "s-1"        },
+  {  78, 0, "DU_CON",    "convective tendency of u-wind component",                   "m s-2"      },
+  {  79, 0, "DV_CON",    "convective tendency of v-wind component",                   "m s-2"      },
+  {  82, 0, "HTOP_DC",   "height of dry convection top",                              "m"          },
+  {  84, 0, "HZEROCL",   "height of freezing level",                                  "m"          },
+  {  85, 0, "SNOWLMT",   "height of the snow fall limit in m above sea level",        "m"          },
+  {  86, 0, "HCBAS",     "height of cloud base",                                      "m"          },
+  {  87, 0, "HCTOP",     "height of cloud top",                                       "m"          },
+  {  91, 0, "C_T_LK",    "&",                                                         "1"          },
+  {  92, 0, "GAMSO_LK",  "&",                                                         "m-1"        },
+  {  93, 0, "DP_BS_LK",  "&",                                                         "m"          },
+  {  94, 0, "H_B1_LK",   "&",                                                         "m"          },
+  {  95, 0, "H_ML_LK",   "&",                                                         "m"          },
+  {  96, 0, "DEPTH_LK",  "lake depth",                                                "m"          },
+  {  97, 0, "FETCH_LK",  "wind fetch over lake",                                      "m"          },
+  {  99, 0, "QRS",       "precipitation water (water loading)",                       "1"          },
+  { 100, 0, "PRR_GSP",   "mass flux density of large scale rainfall",                 "kg m-2 s-1" },
+  { 101, 0, "PRS_GSP",   "mass flux density of large scale snowfall",                 "kg m-2 s-1" },
+  { 102, 0, "RAIN_GSP",  "large scale rainfall",                                      "kg m-2"     },
+  { 111, 0, "PRR_CON",   "mass flux density of convective rainfall",                  "kg m-2 s-1" },
+  { 112, 0, "PRS_CON",   "mass flux density of convective snowfall",                  "kg m-2 s-1" },
+  { 113, 0, "RAIN_CON",  "convective rainfall",                                       "kg m-2"     },
+  { 129, 0, "FRESHSNW",  "freshness of snow",                                         "undefined"  },
+  { 131, 0, "PRG_GSP",   "mass flux density of large scale graupel",                  "kg m-2 s-1" },
+  { 132, 0, "GRAU_GSP",  "large scale graupel",                                       "kg m-2"     },
+  { 133, 0, "RHO_SNOW",  "density of snow",                                           "kg m-3"     },
+  { 139, 0, "PP",        "deviation from reference pressure",                         "Pa"         },
+  { 140, 0, "RCLD",      "standard deviation of saturation deficit",                  "undefined"  },
+  { 143, 0, "CAPE_MU",   "cape of most unstable parcel",                              "J kg-1"     },
+  { 144, 0, "CIN_MU",    "convective inhibition of most unstable parcel",             "J kg-1"     },
+  { 145, 0, "CAPE_ML",   "cape of mean surface layer parcel",                         "J kg-1"     },
+  { 146, 0, "CIN_ML",    "convective inhibition of mean surface layer parcel",        "J kg-1"     },
+  { 147, 0, "TKE_CON",   "convective turbulent kinetic energy",                       "undefined"  },
+  { 148, 0, "TKETENS",   "tendency of turbulent kinetic energy",                      "undefined"  },
+  { 152, 0, "TKE",       "turbulent kinetic energy",                                  "m2 s-2"     },
+  { 153, 0, "TKVM",      "diffusion coefficient of momentum",                         "m2 s-1"     },
+  { 154, 0, "TKVH",      "diffusion coefficient of heat",                             "m2 s-1"     },
+  { 170, 0, "TCM",       "drag coefficient of momentum",                              "1"          },
+  { 171, 0, "TCH",       "drag coefficient of heat",                                  "1"          },
+  { 187, 0, "VMAX",      "maximum turbulent wind gust in 10m",                        "m s-1"      },
+  { 190, 0, "TSOIL",     "&",                                                         "K"          },
+  { 191, 0, "TSOIL",     "&",                                                         "K"          },
+  { 192, 0, "TSOIL",     "&",                                                         "K"          },
+  { 193, 0, "TSOIL",     "mixed layer temperature",                                   "K"          },
+  { 194, 0, "TSOIL",     "mean temperature of water column",                          "K"          },
+  { 197, 0, "TSOIL",     "soil temperature",                                          "K"          },
+  { 198, 0, "W_SO",      "soil water content",                                        "m"          },
+  { 199, 0, "W_SO_ICE",  "soil frozen water content",                                 "m"          },
+  { 200, 0, "W_I",       "canopy water amount",                                       "m"          },
+  { 203, 0, "TSOIL",     "snow surface temperature",                                  "K"          },
+  { 215, 0, "TSOIL",     "temperature of ice upper surface",                          "K"          },
+  { 230, 0, "dBZ",       "unattenuated radar reflectivity in Rayleigh approximation", "1"          },
+  { 240, 0, "MFLX_CON",  "convective mass flux density",                              "kg m-2 s-1" },
+  { 241, 0, "CAPE_CON",  "&",                                                         "J kg-1"     },
+  { 243, 0, "QCVG_CON",  "&",                                                         "s-1"        },
 };
 
-static PAR cosmo202[] = {
-  {  46, "SSO_STDH",  "standard deviation of subgrid scale height",                "m"         },
-  {  47, "SSO_GAMMA", "anisotropy of topography",                                  "-"         },
-  {  48, "SSO_THETA", "angle between principal axis of orography and global east", "-"         },
-  {  49, "SSO_SIGMA", "mean slope of subgrid scale orography",                     "-"         },
-  {  55, "FR_LAKE",   "fraction of inland lake water",                             "1"         },
-  {  57, "SOILTYP",   "soil type",                                                 "1"         },
-  {  61, "LAI",       "leaf area index",                                           "1"         },
-  {  62, "ROOTDP",    "root depth",                                                "m"         },
-  {  64, "HMO3",      "air pressure at ozone maximum",                             "Pa"        },
-  {  65, "VIO3",      "vertical integrated ozone amount",                          "Pa"        },
-  {  67, "PLCOV_MX",  "vegetation area fraction maximum",                          "1"         },
-  {  68, "PLCOV_MN",  "vegetation area fraction minimum",                          "1"         },
-  {  69, "LAI_MX",    "leaf area index maximum",                                   "1"         },
-  {  70, "LAI_MN",    "leaf area index minimum",                                   "1"         },
-  {  75, "FOR_E",     "ground fraction covered by evergreen forest",               "-"         },
-  {  76, "FOR_D",     "ground fraction covered by deciduous forest",               "-"         },
-  { 104, "DQVDT",     "tendency of water vapor",                                   "s-1"       },
-  { 105, "QVSFLX",    "surface flux of water vapour",                              "s-1m-2"    },
-  { 113, "FC",        "coriolis parameter",                                        "s-1"       },
-  { 114, "RLAT",      "latitude",                                                  "radian"    },
-  { 115, "RLON",      "longitude",                                                 "radian"    },
-  { 121, "ZTD",       "integrated total atmospheric refractivity",                 "undefined" },
-  { 122, "ZWD",       "integrated wet atmospheric refractivity",                   "undefined" },
-  { 123, "ZHD",       "integrated dry atmospheric refractivity",                   "undefined" },
-  { 180, "O3",        "ozone mass mixing ratio",                                   "kg kg-1"   },
-  { 200, "I131a",     "undefined",                                                 "undefined" },
-  { 201, "I131a_DD",  "undefined",                                                 "undefined" },
-  { 202, "I131a_WD",  "undefined",                                                 "undefined" },
-  { 203, "Cs137",     "undefined",                                                 "undefined" },
-  { 204, "Cs137_DD",  "undefined",                                                 "undefined" },
-  { 205, "Cs137_WD",  "undefined",                                                 "undefined" },
-  { 206, "Te132",     "undefined",                                                 "undefined" },
-  { 207, "Te132_DD",  "undefined",                                                 "undefined" },
-  { 208, "Te132_WD",  "undefined",                                                 "undefined" },
-  { 209, "Zr95",      "undefined",                                                 "undefined" },
-  { 210, "Zr95_DD",   "undefined",                                                 "undefined" },
-  { 211, "Zr95_WD",   "undefined",                                                 "undefined" },
-  { 212, "Kr85",      "undefined",                                                 "undefined" },
-  { 213, "Kr85_DD",   "undefined",                                                 "undefined" },
-  { 214, "Kr85_WD",   "undefined",                                                 "undefined" },
-  { 215, "TRACER",    "undefined",                                                 "undefined" },
-  { 216, "TRACER_DD", "undefined",                                                 "undefined" },
-  { 217, "TRACER_WD", "undefined",                                                 "undefined" },
-  { 218, "Xe133",     "undefined",                                                 "undefined" },
-  { 219, "Xe133_DD",  "undefined",                                                 "undefined" },
-  { 220, "Xe133_WD",  "undefined",                                                 "undefined" },
-  { 221, "I131g",     "undefined",                                                 "undefined" },
-  { 222, "I131g_DD",  "undefined",                                                 "undefined" },
-  { 223, "I131g_WD",  "undefined",                                                 "undefined" },
-  { 224, "I131o",     "undefined",                                                 "undefined" },
-  { 225, "I131o_DD",  "undefined",                                                 "undefined" },
-  { 226, "I131o_WD",  "undefined",                                                 "undefined" },
-  { 227, "Ba140",     "undefined",                                                 "undefined" },
-  { 228, "Ba140_DD",  "undefined",                                                 "undefined" },
-  { 229, "Ba140_WD",  "undefined",                                                 "undefined" },
-  { 230, "Sr90",      "undefined",                                                 "undefined" },
-  { 231, "Sr90_DD",   "undefined",                                                 "undefined" },
-  { 232, "Sr90_WD",   "undefined",                                                 "undefined" },
-  { 233, "Ru103",     "undefined",                                                 "undefined" },
-  { 234, "Ru103_DD",  "undefined",                                                 "undefined" },
-  { 235, "Ru103_WD",  "undefined",                                                 "undefined" },
+static const PAR cosmo202[] = {
+  {  46, 0, "SSO_STDH",  "standard deviation of subgrid scale height",                "m"         },
+  {  47, 0, "SSO_GAMMA", "anisotropy of topography",                                  "-"         },
+  {  48, 0, "SSO_THETA", "angle between principal axis of orography and global east", "-"         },
+  {  49, 0, "SSO_SIGMA", "mean slope of subgrid scale orography",                     "-"         },
+  {  55, 0, "FR_LAKE",   "fraction of inland lake water",                             "1"         },
+  {  57, 0, "SOILTYP",   "soil type",                                                 "1"         },
+  {  61, 0, "LAI",       "leaf area index",                                           "1"         },
+  {  62, 0, "ROOTDP",    "root depth",                                                "m"         },
+  {  64, 0, "HMO3",      "air pressure at ozone maximum",                             "Pa"        },
+  {  65, 0, "VIO3",      "vertical integrated ozone amount",                          "Pa"        },
+  {  67, 0, "PLCOV_MX",  "vegetation area fraction maximum",                          "1"         },
+  {  68, 0, "PLCOV_MN",  "vegetation area fraction minimum",                          "1"         },
+  {  69, 0, "LAI_MX",    "leaf area index maximum",                                   "1"         },
+  {  70, 0, "LAI_MN",    "leaf area index minimum",                                   "1"         },
+  {  75, 0, "FOR_E",     "ground fraction covered by evergreen forest",               "-"         },
+  {  76, 0, "FOR_D",     "ground fraction covered by deciduous forest",               "-"         },
+  { 104, 0, "DQVDT",     "tendency of water vapor",                                   "s-1"       },
+  { 105, 0, "QVSFLX",    "surface flux of water vapour",                              "s-1m-2"    },
+  { 113, 0, "FC",        "coriolis parameter",                                        "s-1"       },
+  { 114, 0, "RLAT",      "latitude",                                                  "radian"    },
+  { 115, 0, "RLON",      "longitude",                                                 "radian"    },
+  { 121, 0, "ZTD",       "integrated total atmospheric refractivity",                 "undefined" },
+  { 122, 0, "ZWD",       "integrated wet atmospheric refractivity",                   "undefined" },
+  { 123, 0, "ZHD",       "integrated dry atmospheric refractivity",                   "undefined" },
+  { 180, 0, "O3",        "ozone mass mixing ratio",                                   "kg kg-1"   },
+  { 200, 0, "I131a",     "undefined",                                                 "undefined" },
+  { 201, 0, "I131a_DD",  "undefined",                                                 "undefined" },
+  { 202, 0, "I131a_WD",  "undefined",                                                 "undefined" },
+  { 203, 0, "Cs137",     "undefined",                                                 "undefined" },
+  { 204, 0, "Cs137_DD",  "undefined",                                                 "undefined" },
+  { 205, 0, "Cs137_WD",  "undefined",                                                 "undefined" },
+  { 206, 0, "Te132",     "undefined",                                                 "undefined" },
+  { 207, 0, "Te132_DD",  "undefined",                                                 "undefined" },
+  { 208, 0, "Te132_WD",  "undefined",                                                 "undefined" },
+  { 209, 0, "Zr95",      "undefined",                                                 "undefined" },
+  { 210, 0, "Zr95_DD",   "undefined",                                                 "undefined" },
+  { 211, 0, "Zr95_WD",   "undefined",                                                 "undefined" },
+  { 212, 0, "Kr85",      "undefined",                                                 "undefined" },
+  { 213, 0, "Kr85_DD",   "undefined",                                                 "undefined" },
+  { 214, 0, "Kr85_WD",   "undefined",                                                 "undefined" },
+  { 215, 0, "TRACER",    "undefined",                                                 "undefined" },
+  { 216, 0, "TRACER_DD", "undefined",                                                 "undefined" },
+  { 217, 0, "TRACER_WD", "undefined",                                                 "undefined" },
+  { 218, 0, "Xe133",     "undefined",                                                 "undefined" },
+  { 219, 0, "Xe133_DD",  "undefined",                                                 "undefined" },
+  { 220, 0, "Xe133_WD",  "undefined",                                                 "undefined" },
+  { 221, 0, "I131g",     "undefined",                                                 "undefined" },
+  { 222, 0, "I131g_DD",  "undefined",                                                 "undefined" },
+  { 223, 0, "I131g_WD",  "undefined",                                                 "undefined" },
+  { 224, 0, "I131o",     "undefined",                                                 "undefined" },
+  { 225, 0, "I131o_DD",  "undefined",                                                 "undefined" },
+  { 226, 0, "I131o_WD",  "undefined",                                                 "undefined" },
+  { 227, 0, "Ba140",     "undefined",                                                 "undefined" },
+  { 228, 0, "Ba140_DD",  "undefined",                                                 "undefined" },
+  { 229, 0, "Ba140_WD",  "undefined",                                                 "undefined" },
+  { 230, 0, "Sr90",      "undefined",                                                 "undefined" },
+  { 231, 0, "Sr90_DD",   "undefined",                                                 "undefined" },
+  { 232, 0, "Sr90_WD",   "undefined",                                                 "undefined" },
+  { 233, 0, "Ru103",     "undefined",                                                 "undefined" },
+  { 234, 0, "Ru103_DD",  "undefined",                                                 "undefined" },
+  { 235, 0, "Ru103_WD",  "undefined",                                                 "undefined" },
 };
 
-static PAR cosmo203[] = {
-  { 135, "LCL_ML",   "undefined",                  "undefined" },
-  { 136, "LFC_ML",   "undefined",                  "undefined" },
-  { 137, "CAPE_3KM", "undefined",                  "undefined" },
-  { 138, "SWISS00",  "swiss00 index",              "1"         },
-  { 139, "SWISS12",  "swiss12 index",              "1"         },
-  { 147, "SLI",      "surface lifted index",       "K"         },
-  { 149, "SI",       "showalter index",            "K"         },
-  { 155, "BRN",      "undefined",                  "undefined" },
-  { 156, "HPBL",     "undefined",                  "undefined" },
-  { 203, "CLDEPTH",  "normalized cloud depth",     "1"         },
-  { 204, "CLCT_MOD", "modified_total_cloud_cover", "1"         },
+static const PAR cosmo203[] = {
+  { 135, 0, "LCL_ML",   "undefined",                  "undefined" },
+  { 136, 0, "LFC_ML",   "undefined",                  "undefined" },
+  { 137, 0, "CAPE_3KM", "undefined",                  "undefined" },
+  { 138, 0, "SWISS00",  "swiss00 index",              "1"         },
+  { 139, 0, "SWISS12",  "swiss12 index",              "1"         },
+  { 147, 0, "SLI",      "surface lifted index",       "K"         },
+  { 149, 0, "SI",       "showalter index",            "K"         },
+  { 155, 0, "BRN",      "undefined",                  "undefined" },
+  { 156, 0, "HPBL",     "undefined",                  "undefined" },
+  { 203, 0, "CLDEPTH",  "normalized cloud depth",     "1"         },
+  { 204, 0, "CLCT_MOD", "modified_total_cloud_cover", "1"         },
 };
 
-static PAR cosmo205[] = {
-  {   1, "SYNME5", "synthetic satellite images Meteosat5", "-" },
-  {   2, "SYNME6", "synthetic satellite images Meteosat6", "-" },
-  {   3, "SYNME7", "synthetic satellite images Meteosat7", "-" },
-  {   4, "SYNMSG", "synthetic satellite images MSG",       "-" },
+static const PAR cosmo205[] = {
+  {   1, 0, "SYNME5", "synthetic satellite images Meteosat5", "-" },
+  {   2, 0, "SYNME6", "synthetic satellite images Meteosat6", "-" },
+  {   3, 0, "SYNME7", "synthetic satellite images Meteosat7", "-" },
+  {   4, 0, "SYNMSG", "synthetic satellite images MSG",       "-" },
 };
 
-static PAR cosmo250[] = {
-  {   1, "QNH",       "sea level air pressure",                                         "hPa"                                },
-  {  11, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  12, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  13, "D_T_2M_K",  "kalman correction to 2m temperature",                            "K"                                  },
-  {  14, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  15, "TSOIL",     "2m temperature",                                                 "K"                                  },
-  {  16, "RH_ICE",    "relative humidity over ice",                                     "%"                                  },
-  {  17, "TD",        "dew point temperature",                                          "K"                                  },
-  {  18, "D_TD",      "dew point depression",                                           "K"                                  },
-  {  19, "THETAE",    "equivalent potential temperature",                               "K"                                  },
-  {  20, "TD_2M_K",   "2m dew point temperature",                                       "K"                                  },
-  {  21, "D_TD_2M_K", "kalman correction to 2m dew point temperature",                  "K"                                  },
-  {  22, "TD_2M_OLD", "2m dew point temperature",                                       "K"                                  },
-  {  23, "TD_2M_BUZ", "2m dew point temperature",                                       "K"                                  },
-  {  24, "HI",        "heat index",                                                     "Fahrenheit"                         },
-  {  25, "DURSUN_M",  "maximum duration of sunshine",                                   "s"                                  },
-  {  26, "DURSUN_R",  "relative duration of sunshine",                                  "%"                                  },
-  {  52, "RH_2M_K",   "2m relative humidity",                                           "%"                                  },
-  {  53, "D_RH_2M_K", "kalman correction to 2m relative humidity",                      "%"                                  },
-  {  58, "CLI_RATIO", "cloud ice ratio (Qi/Qc+Qi)",                                     "%"                                  },
-  {  61, "TOT_SNOW",  "total precipitation in snow",                                    "kg/m**2"                            },
-  {  62, "TOT_RAIN",  "total precipitation in rain",                                    "kg/m**2"                            },
-  {  63, "TOT_CON",   "total convective precipitation",                                 "kg/m**2"                            },
-  {  64, "TOT_GSP",   "total large scale precipitation",                                "kg/m**2"                            },
-  {  65, "SNOW_%",    "percentage of precipitation in snow",                            "%"                                  },
-  {  66, "CONV_%",    "percentage of convective precipitation",                         "%"                                  },
-  {  67, "VORTP_ABS", "absolute",                                                       "VORTP_ABS 67 -1 absolute vorticity" },
-  {  68, "VORTP_REL", "relative",                                                       "VORTP_REL 68 -1 relative vorticity" },
-  {  70, "PDIFF_CON", "pressure difference between cloud base and cloud top",           "Pa"                                 },
-  {  71, "TTOP_CON",  "temperature at cloud top",                                       "K"                                  },
-  {  80, "GEM",       "emissivity of the ground",                                       "%"                                  },
-  {  82, "Z0LOC",     "local surface roughness length",                                 "m"                                  },
-  { 110, "LUM",       "luminosity",                                                     "klux"                               },
-  { 111, "GLOB",      "global shortwave radiation at surface",                          "W/m**2"                             },
-  { 112, "LW_IN_TG",  "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 113, "LW_IN_TS",  "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 114, "LW_IN_T2M", "incoming longwave radiation at surface",                         "W/m**2"                             },
-  { 115, "SWISS_WE",  "Swiss",                                                          "SWISS_WE 115 1 Swiss coordinates"   },
-  { 116, "SWISS_SN",  "Swiss",                                                          "SWISS_SN 116 1 Swiss coordinates"   },
-  { 150, "KOINDEX",   "KO index",                                                       "K"                                  },
-  { 151, "TTINDEX",   "total-totals index",                                             "K"                                  },
-  { 152, "DCI",       "deep convection index",                                          "K"                                  },
-  { 153, "SWEAT",     "severe weather thread index",                                    "undefined"                          },
-  { 154, "ADEDO2",    "adedokun 2 index",                                               "K"                                  },
-  { 160, "C_TSTORM",  "thunderstorm index using AdaBoost classifier",                   "undefined"                          },
-  { 161, "CN_TSTORM", "thunderstorm probabilty using AdaBoost classifier",              "%"                                  },
-  { 200, "WSHEARL",   "wind shear between surface and 3 km asl",                        "1/s"                                },
-  { 201, "WSHEARM",   "wind shear between surface and 6 km asl",                        "1/s"                                },
-  { 202, "WSHEARU",   "wind shear between 3 km (or surface) and 6 km asl",              "1/s"                                },
-  { 211, "VWIN",      "maximum OLD turbulent wind gust in 10m",                         "m s-1"                              },
-  { 212, "VW10M_20",  "maximum 10m wind speed",                                         "m s-1"                              },
-  { 213, "VW10M_25",  "duration of VWIN_10M above 25 knots",                            "s"                                  },
-  { 214, "VW10M_30",  "duration of VWIN_10M above 30 knots",                            "s"                                  },
-  { 215, "VW10M_35",  "duration of VWIN_10M above 35 knots",                            "s"                                  },
-  { 216, "VW10M_40",  "duration of VWIN_10M above 40 knots",                            "s"                                  },
-  { 217, "VW10M_45",  "duration of VWIN_10M above 45 knots",                            "s"                                  },
-  { 218, "VW10M_50",  "duration of VWIN_10M above 50 knots",                            "s"                                  },
-  { 219, "VOLD",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
-  { 220, "VJPS",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
-  { 221, "VBRA",      "maximum Brasseur turbulent wind gust in 10m",                    "m s-1"                              },
-  { 222, "VB10M_20",  "duration of VBRA_10M above 20 knots",                            "s"                                  },
-  { 223, "VB10M_25",  "duration of VBRA_10M above 25 knots",                            "s"                                  },
-  { 224, "VB10M_30",  "duration of VBRA_10M above 30 knots",                            "s"                                  },
-  { 225, "VB10M_35",  "duration of VBRA_10M above 35 knots",                            "s"                                  },
-  { 226, "VB10M_40",  "duration of VBRA_10M above 40 knots",                            "s"                                  },
-  { 227, "VB10M_45",  "duration of VBRA_10M above 45 knots",                            "s"                                  },
-  { 228, "VB10M_50",  "duration of VBRA_10M above 50 knots",                            "s"                                  },
-  { 231, "VCON",      "maximum convective wind gust in 10m",                            "m s-1"                              },
-  { 232, "VC10M_20",  "duration of VCON_10M above 20 knots",                            "s"                                  },
-  { 233, "VC10M_25",  "duration of VCON_10M above 25 knots",                            "s"                                  },
-  { 234, "VC10M_30",  "duration of VCON_10M above 30 knots",                            "s"                                  },
-  { 235, "VC10M_35",  "duration of VCON_10M above 35 knots",                            "s"                                  },
-  { 236, "VC10M_40",  "duration of VCON_10M above 40 knots",                            "s"                                  },
-  { 237, "VC10M_45",  "duration of VCON_10M above 45 knots",                            "s"                                  },
-  { 238, "VC10M_50",  "duration of VCON_10M above 50 knots",                            "s"                                  },
-  { 241, "FMAX",      "maximum wind speed at k=ke",                                     "m s-1"                              },
-  { 242, "USTARMAX",  "maximal u*=SQRT(Drag_coef)*fmax_10m",                            "m s-1"                              },
-  { 243, "GLOB_DIF",  "global diffuse shortwave radiation at the surface",              "W/m**2"                             },
-  { 244, "GLOB_DIR",  "global direct (beam) shortwave radiation at the surface",        "W/m**2"                             },
-  { 245, "GLOB_vE",   "global shortwave radiation on a vertical surface facing east",   "W/m**2"                             },
-  { 246, "GLOB_vS",   "global shortwave radiation on a vertical surface facing south",  "W/m**2"                             },
-  { 247, "GLOB_vW",   "global shortwave radiation on a vertical surface facing west",   "W/m**2"                             },
-  { 248, "GLOB_vN",   "global shortwave radiation on a vertical surface facing north",  "W/m**2"                             },
-  { 249, "LW_TG_vS",  "incoming longwave radiation on a vertical surface facing south", "W/m**2"                             },
-  { 250, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
-  { 251, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
-  { 252, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
-  { 253, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
-  { 254, "TW",        "wet bulb temperature",                                           "degC"                               },
-  { 255, "TW",        "wet bulb temperature",                                           "degC"                               },
+static const PAR cosmo250[] = {
+  {   1, 0, "QNH",       "sea level air pressure",                                         "hPa"                                },
+  {  11, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  12, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  13, 0, "D_T_2M_K",  "kalman correction to 2m temperature",                            "K"                                  },
+  {  14, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  15, 0, "TSOIL",     "2m temperature",                                                 "K"                                  },
+  {  16, 0, "RH_ICE",    "relative humidity over ice",                                     "%"                                  },
+  {  17, 0, "TD",        "dew point temperature",                                          "K"                                  },
+  {  18, 0, "D_TD",      "dew point depression",                                           "K"                                  },
+  {  19, 0, "THETAE",    "equivalent potential temperature",                               "K"                                  },
+  {  20, 0, "TD_2M_K",   "2m dew point temperature",                                       "K"                                  },
+  {  21, 0, "D_TD_2M_K", "kalman correction to 2m dew point temperature",                  "K"                                  },
+  {  22, 0, "TD_2M_OLD", "2m dew point temperature",                                       "K"                                  },
+  {  23, 0, "TD_2M_BUZ", "2m dew point temperature",                                       "K"                                  },
+  {  24, 0, "HI",        "heat index",                                                     "Fahrenheit"                         },
+  {  25, 0, "DURSUN_M",  "maximum duration of sunshine",                                   "s"                                  },
+  {  26, 0, "DURSUN_R",  "relative duration of sunshine",                                  "%"                                  },
+  {  52, 0, "RH_2M_K",   "2m relative humidity",                                           "%"                                  },
+  {  53, 0, "D_RH_2M_K", "kalman correction to 2m relative humidity",                      "%"                                  },
+  {  58, 0, "CLI_RATIO", "cloud ice ratio (Qi/Qc+Qi)",                                     "%"                                  },
+  {  61, 0, "TOT_SNOW",  "total precipitation in snow",                                    "kg/m**2"                            },
+  {  62, 0, "TOT_RAIN",  "total precipitation in rain",                                    "kg/m**2"                            },
+  {  63, 0, "TOT_CON",   "total convective precipitation",                                 "kg/m**2"                            },
+  {  64, 0, "TOT_GSP",   "total large scale precipitation",                                "kg/m**2"                            },
+  {  65, 0, "SNOW_%",    "percentage of precipitation in snow",                            "%"                                  },
+  {  66, 0, "CONV_%",    "percentage of convective precipitation",                         "%"                                  },
+  {  67, 0, "VORTP_ABS", "absolute",                                                       "VORTP_ABS 67 -1 absolute vorticity" },
+  {  68, 0, "VORTP_REL", "relative",                                                       "VORTP_REL 68 -1 relative vorticity" },
+  {  70, 0, "PDIFF_CON", "pressure difference between cloud base and cloud top",           "Pa"                                 },
+  {  71, 0, "TTOP_CON",  "temperature at cloud top",                                       "K"                                  },
+  {  80, 0, "GEM",       "emissivity of the ground",                                       "%"                                  },
+  {  82, 0, "Z0LOC",     "local surface roughness length",                                 "m"                                  },
+  { 110, 0, "LUM",       "luminosity",                                                     "klux"                               },
+  { 111, 0, "GLOB",      "global shortwave radiation at surface",                          "W/m**2"                             },
+  { 112, 0, "LW_IN_TG",  "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 113, 0, "LW_IN_TS",  "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 114, 0, "LW_IN_T2M", "incoming longwave radiation at surface",                         "W/m**2"                             },
+  { 115, 0, "SWISS_WE",  "Swiss",                                                          "SWISS_WE 115 1 Swiss coordinates"   },
+  { 116, 0, "SWISS_SN",  "Swiss",                                                          "SWISS_SN 116 1 Swiss coordinates"   },
+  { 150, 0, "KOINDEX",   "KO index",                                                       "K"                                  },
+  { 151, 0, "TTINDEX",   "total-totals index",                                             "K"                                  },
+  { 152, 0, "DCI",       "deep convection index",                                          "K"                                  },
+  { 153, 0, "SWEAT",     "severe weather thread index",                                    "undefined"                          },
+  { 154, 0, "ADEDO2",    "adedokun 2 index",                                               "K"                                  },
+  { 160, 0, "C_TSTORM",  "thunderstorm index using AdaBoost classifier",                   "undefined"                          },
+  { 161, 0, "CN_TSTORM", "thunderstorm probabilty using AdaBoost classifier",              "%"                                  },
+  { 200, 0, "WSHEARL",   "wind shear between surface and 3 km asl",                        "1/s"                                },
+  { 201, 0, "WSHEARM",   "wind shear between surface and 6 km asl",                        "1/s"                                },
+  { 202, 0, "WSHEARU",   "wind shear between 3 km (or surface) and 6 km asl",              "1/s"                                },
+  { 211, 0, "VWIN",      "maximum OLD turbulent wind gust in 10m",                         "m s-1"                              },
+  { 212, 0, "VW10M_20",  "maximum 10m wind speed",                                         "m s-1"                              },
+  { 213, 0, "VW10M_25",  "duration of VWIN_10M above 25 knots",                            "s"                                  },
+  { 214, 0, "VW10M_30",  "duration of VWIN_10M above 30 knots",                            "s"                                  },
+  { 215, 0, "VW10M_35",  "duration of VWIN_10M above 35 knots",                            "s"                                  },
+  { 216, 0, "VW10M_40",  "duration of VWIN_10M above 40 knots",                            "s"                                  },
+  { 217, 0, "VW10M_45",  "duration of VWIN_10M above 45 knots",                            "s"                                  },
+  { 218, 0, "VW10M_50",  "duration of VWIN_10M above 50 knots",                            "s"                                  },
+  { 219, 0, "VOLD",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
+  { 220, 0, "VJPS",      "maximum turbulent wind gust in 10m",                             "m s-1"                              },
+  { 221, 0, "VBRA",      "maximum Brasseur turbulent wind gust in 10m",                    "m s-1"                              },
+  { 222, 0, "VB10M_20",  "duration of VBRA_10M above 20 knots",                            "s"                                  },
+  { 223, 0, "VB10M_25",  "duration of VBRA_10M above 25 knots",                            "s"                                  },
+  { 224, 0, "VB10M_30",  "duration of VBRA_10M above 30 knots",                            "s"                                  },
+  { 225, 0, "VB10M_35",  "duration of VBRA_10M above 35 knots",                            "s"                                  },
+  { 226, 0, "VB10M_40",  "duration of VBRA_10M above 40 knots",                            "s"                                  },
+  { 227, 0, "VB10M_45",  "duration of VBRA_10M above 45 knots",                            "s"                                  },
+  { 228, 0, "VB10M_50",  "duration of VBRA_10M above 50 knots",                            "s"                                  },
+  { 231, 0, "VCON",      "maximum convective wind gust in 10m",                            "m s-1"                              },
+  { 232, 0, "VC10M_20",  "duration of VCON_10M above 20 knots",                            "s"                                  },
+  { 233, 0, "VC10M_25",  "duration of VCON_10M above 25 knots",                            "s"                                  },
+  { 234, 0, "VC10M_30",  "duration of VCON_10M above 30 knots",                            "s"                                  },
+  { 235, 0, "VC10M_35",  "duration of VCON_10M above 35 knots",                            "s"                                  },
+  { 236, 0, "VC10M_40",  "duration of VCON_10M above 40 knots",                            "s"                                  },
+  { 237, 0, "VC10M_45",  "duration of VCON_10M above 45 knots",                            "s"                                  },
+  { 238, 0, "VC10M_50",  "duration of VCON_10M above 50 knots",                            "s"                                  },
+  { 241, 0, "FMAX",      "maximum wind speed at k=ke",                                     "m s-1"                              },
+  { 242, 0, "USTARMAX",  "maximal u*=SQRT(Drag_coef)*fmax_10m",                            "m s-1"                              },
+  { 243, 0, "GLOB_DIF",  "global diffuse shortwave radiation at the surface",              "W/m**2"                             },
+  { 244, 0, "GLOB_DIR",  "global direct (beam) shortwave radiation at the surface",        "W/m**2"                             },
+  { 245, 0, "GLOB_vE",   "global shortwave radiation on a vertical surface facing east",   "W/m**2"                             },
+  { 246, 0, "GLOB_vS",   "global shortwave radiation on a vertical surface facing south",  "W/m**2"                             },
+  { 247, 0, "GLOB_vW",   "global shortwave radiation on a vertical surface facing west",   "W/m**2"                             },
+  { 248, 0, "GLOB_vN",   "global shortwave radiation on a vertical surface facing north",  "W/m**2"                             },
+  { 249, 0, "LW_TG_vS",  "incoming longwave radiation on a vertical surface facing south", "W/m**2"                             },
+  { 250, 0, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
+  { 251, 0, "ENTH",      "enthalpy",                                                       "kJ/kg"                              },
+  { 252, 0, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
+  { 253, 0, "MIXRAT",    "mixing ratio",                                                   "g/kg"                               },
+  { 254, 0, "TW",        "wet bulb temperature",                                           "degC"                               },
+  { 255, 0, "TW",        "wet bulb temperature",                                           "degC"                               },
 };
 
 
-void
+static void
 tableDefault(void)
 {
   int tableID, instID, modelID;
diff --git a/libcdi/src/tablepar.h b/libcdi/src/tablepar.h
index 3564c63..0223f6b 100644
--- a/libcdi/src/tablepar.h
+++ b/libcdi/src/tablepar.h
@@ -1,17 +1,24 @@
 #ifndef _TABLEPAR_H
 #define _TABLEPAR_H
 
+enum {
+  TABLE_DUP_NAME = 1 << 0,
+  TABLE_DUP_LONGNAME = 1 << 1,
+  TABLE_DUP_UNITS = 1 << 2,
+};
+
 typedef struct
 {
   int   id;	     /* Parameter number (GRIB) */
-  char *name;	     /* Parameter name */
-  char *longname;    /* Parameter long name */
-  char *units;	     /* Parameter units */
+  int dupflags;      /* keep track of which attributes got strdup'ed */
+  const char *name;	     /* Parameter name */
+  const char *longname;    /* Parameter long name */
+  const char *units;	     /* Parameter units */
 }
 PAR;
 
 
-void tableLink(int tableID, PAR *pars, int npars);
+static void tableLink(int tableID, const PAR *pars, int npars);
 int tableDef(int modelID, int tablegribID, const char *tablename);
 
 #endif
diff --git a/libcdi/src/taxis.c b/libcdi/src/taxis.c
index 508d98d..585e206 100644
--- a/libcdi/src/taxis.c
+++ b/libcdi/src/taxis.c
@@ -2,6 +2,7 @@
 #  include "config.h"
 #endif
 
+#include <stddef.h>
 #include <string.h>
 
 #include "dmemory.h"
@@ -27,14 +28,15 @@ char *Timeunits[] = {
   "undefined",
   "seconds",
   "minutes",
-  "hours",
-  "days",
-  "months",
-  "years",
   "quarters",
+  "30minutes",
+  "hours",
   "3hours",
   "6hours",
   "12hours",
+  "days",
+  "months",
+  "years",
 };
 
 
@@ -55,6 +57,50 @@ const resOps taxisOps = {
   taxisTxCode
 };
 
+#define container_of(ptr, type, member) \
+  ((type *)((unsigned char *)ptr - offsetof(type,member)))
+
+struct refcount_string
+{
+  int ref_count;
+  char string[];
+};
+
+static char *
+new_refcount_string(size_t len)
+{
+  struct refcount_string *container
+    = xmalloc(sizeof (*container) + len + 1);
+  container->ref_count = 1;
+  return container->string;
+}
+
+static void
+delete_refcount_string(void *p)
+{
+  if (p)
+    {
+      struct refcount_string *container
+        = container_of(p, struct refcount_string, string);
+      if (!--(container->ref_count))
+        free(container);
+    }
+}
+
+static char *
+dup_refcount_string(char *p)
+{
+  if (p)
+    {
+      struct refcount_string *container
+        = container_of(p, struct refcount_string, string);
+      ++(container->ref_count);
+    }
+  return p;
+}
+
+
+#undef container_of
 
 static int  TAXIS_Debug = 0;   /* If set to 1, debugging */
 
@@ -228,16 +274,14 @@ int taxisCreate(int taxistype)
   return (taxisID);
 }
 
-static
-void taxisDestroyKernel( taxis_t * taxisptr )
+void taxisDestroyKernel(taxis_t *taxisptr)
 {
   taxis_check_ptr(__func__, taxisptr);
-
   int id = taxisptr->self;
-
-  free ( taxisptr );
-
-  reshRemove ( id, &taxisOps );
+  delete_refcount_string(taxisptr->name);
+  delete_refcount_string(taxisptr->longname);
+  if (id != CDI_UNDEFID)
+    reshRemove(id, &taxisOps);
 }
 
 /*
@@ -252,27 +296,23 @@ void taxisDestroyKernel( taxis_t * taxisptr )
 */
 void taxisDestroy(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
-
-  if ( taxisptr->name     ) free(taxisptr->name);
-  if ( taxisptr->longname ) free(taxisptr->longname);
-
-  taxisDestroyKernel ( taxisptr );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
+  taxisDestroyKernel(taxisptr);
+  free(taxisptr);
 }
 
 
 void taxisDestroyP( void * taxisptr )
 {
-  taxisDestroyKernel (( taxis_t * ) taxisptr );
+  taxisDestroyKernel((taxis_t *)taxisptr);
+  free(taxisptr);
 }
 
 
 int taxisDuplicate(int taxisID1)
 {
-  taxis_t *taxisptr1 = ( taxis_t * ) reshGetVal ( taxisID1, &taxisOps );
-
+  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps);
   taxis_t *taxisptr2 = taxisNewEntry(CDI_UNDEFID);
-  if ( ! taxisptr2 ) Error("No memory");
 
   int taxisID2 = taxisptr2->self;
 
@@ -280,28 +320,21 @@ int taxisDuplicate(int taxisID1)
     Message("taxisID2: %d", taxisID2);
 
   ptaxisCopy(taxisptr2, taxisptr1);
-  if ( taxisptr1->name     ) taxisptr2->name = strdup(taxisptr1->name);
-  if ( taxisptr1->longname ) taxisptr2->longname = strdup(taxisptr1->longname);
-
-  // taxisptr2->has_bounds = FALSE;
-
   return (taxisID2);
 }
 
 
 void taxisDefType(int taxisID, int type)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->type = type;
+  if (taxisptr->type != type)
+    {
+      taxisptr->type = type;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -320,11 +353,15 @@ The function @func{taxisDefVdate} defines the verification date of a Time axis.
 */
 void taxisDefVdate(int taxisID, int vdate)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->vdate = vdate;
+  if (taxisptr->vdate != vdate)
+    {
+      taxisptr->vdate = vdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -343,11 +380,15 @@ The function @func{taxisDefVtime} defines the verification time of a Time axis.
 */
 void taxisDefVtime(int taxisID, int vtime)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->vtime = vtime;
+  if (taxisptr->vtime != vtime)
+    {
+      taxisptr->vtime = vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -366,17 +407,15 @@ The function @func{taxisDefRdate} defines the reference date of a Time axis.
 */
 void taxisDefRdate(int taxisID, int rdate)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->rdate = rdate;
+  if (taxisptr->rdate != rdate)
+    {
+      taxisptr->rdate = rdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -395,17 +434,15 @@ The function @func{taxisDefRtime} defines the reference time of a Time axis.
 */
 void taxisDefRtime(int taxisID, int rtime)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->rtime = rtime;
+  if (taxisptr->rtime != rtime)
+    {
+      taxisptr->rtime = rtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -424,17 +461,15 @@ The function @func{taxisDefFdate} defines the forecast reference date of a Time
 */
 void taxisDefFdate(int taxisID, int fdate)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fdate = fdate;
+  if (taxisptr->fdate != fdate)
+    {
+      taxisptr->fdate = fdate;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -453,17 +488,15 @@ The function @func{taxisDefFtime} defines the forecast reference time of a Time
 */
 void taxisDefFtime(int taxisID, int ftime)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->ftime = ftime;
+  if (taxisptr->ftime != ftime)
+    {
+      taxisptr->ftime = ftime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -484,81 +517,71 @@ The function @func{taxisDefCalendar} defines the calendar of a Time axis.
 */
 void taxisDefCalendar(int taxisID, int calendar)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->calendar = calendar;
+  if (taxisptr->calendar != calendar)
+    {
+      taxisptr->calendar = calendar;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefTunit(int taxisID, int unit)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->unit = unit;
+  if (taxisptr->unit != unit)
+    {
+      taxisptr->unit = unit;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefForecastTunit(int taxisID, int unit)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fc_unit = unit;
+  if (taxisptr->fc_unit != unit)
+    {
+      taxisptr->fc_unit = unit;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefForecastPeriod(int taxisID, double fc_period)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->fc_period = fc_period;
+  if (taxisptr->fc_period != fc_period)
+    {
+      taxisptr->fc_period = fc_period;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisDefNumavg(int taxisID, int numavg)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->numavg = numavg;
+  if (taxisptr->numavg != numavg)
+    {
+      taxisptr->numavg = numavg;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -567,7 +590,7 @@ The valid CDI time types are TAXIS_ABSOLUTE and TAXIS_RELATIVE.
 */
 int taxisInqType(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -577,7 +600,7 @@ int taxisInqType(int taxisID)
 
 int taxisHasBounds(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -587,29 +610,27 @@ int taxisHasBounds(int taxisID)
 
 void taxisDeleteBounds(int taxisID)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  taxisptr->has_bounds = FALSE;
+  if (taxisptr->has_bounds != FALSE)
+    {
+      taxisptr->has_bounds = FALSE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void taxisCopyTimestep(int taxisID2, int taxisID1)
 {
-  taxis_t *taxisptr1 = ( taxis_t * ) reshGetVal ( taxisID1, &taxisOps );
-  taxis_t *taxisptr2 = ( taxis_t * ) reshGetVal ( taxisID2, &taxisOps );
+  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps),
+    *taxisptr2 = (taxis_t *)reshGetVal(taxisID2, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr1);
   taxis_check_ptr(__func__, taxisptr2);
 
-  reshLock ();
+  reshLock();
 
   taxisptr2->rdate = taxisptr1->rdate;
   taxisptr2->rtime = taxisptr1->rtime;
@@ -631,7 +652,8 @@ void taxisCopyTimestep(int taxisID2, int taxisID1)
   taxisptr2->fc_unit   = taxisptr1->fc_unit;
   taxisptr2->fc_period = taxisptr1->fc_period;
 
-  reshUnlock ();
+  reshSetStatus(taxisID2, &taxisOps, RESH_DESYNC_IN_USE);
+  reshUnlock();
 }
 
 /*
@@ -652,7 +674,7 @@ The function @func{taxisInqVdate} returns the verification date of a Time axis.
 */
 int taxisInqVdate(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -662,7 +684,7 @@ int taxisInqVdate(int taxisID)
 
 void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -673,20 +695,19 @@ void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
 
 void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  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 != TRUE)
+    {
+      taxisptr->vdate_lb = vdate_lb;
+      taxisptr->vdate_ub = vdate_ub;
+      taxisptr->has_bounds = TRUE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -707,7 +728,7 @@ The function @func{taxisInqVtime} returns the verification time of a Time axis.
 */
 int taxisInqVtime(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -717,7 +738,7 @@ int taxisInqVtime(int taxisID)
 
 void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
@@ -728,20 +749,19 @@ void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
 
 void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
 {
-  if ( reshGetStatus ( taxisID, &taxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
   taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
 
   taxis_check_ptr(__func__, taxisptr);
 
-  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 != TRUE)
+    {
+      taxisptr->vtime_lb = vtime_lb;
+      taxisptr->vtime_ub = vtime_ub;
+      taxisptr->has_bounds = TRUE;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -770,6 +790,7 @@ int taxisInqRdate(int taxisID)
     {
       taxisptr->rdate = taxisptr->vdate;
       taxisptr->rtime = taxisptr->vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
   return (taxisptr->rdate);
@@ -801,6 +822,7 @@ int taxisInqRtime(int taxisID)
     {
       taxisptr->rdate = taxisptr->vdate;
       taxisptr->rtime = taxisptr->vtime;
+      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 
   return (taxisptr->rtime);
@@ -939,13 +961,38 @@ int taxisInqNumavg(int taxisID)
 
 taxis_t *taxisPtr(int taxisID)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
 
   taxis_check_ptr(__func__, taxisptr);
 
   return (taxisptr);
 }
 
+void
+ptaxisDefName(taxis_t *taxisptr, const char *name)
+{
+  if (name)
+    {
+      taxis_check_ptr(__func__, taxisptr);
+      size_t len = strlen(name);
+      delete_refcount_string(taxisptr->name);
+      char *taxisname = taxisptr->name = new_refcount_string(len);
+      strcpy(taxisname, name);
+    }
+}
+
+void
+ptaxisDefLongname(taxis_t *taxisptr, const char *longname)
+{
+  if (longname)
+    {
+      taxis_check_ptr(__func__, taxisptr);
+      size_t len = strlen(longname);
+      delete_refcount_string(taxisptr->longname);
+      char *taxislongname = taxisptr->longname = new_refcount_string(len);
+      strcpy(taxislongname, longname);
+    }
+}
 
 void cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
 {
@@ -1007,8 +1054,9 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
     {
       *timevalue = days*86400. + secs;
     }
-  else if ( timeunit == TUNIT_MINUTE ||
-	    timeunit == TUNIT_QUARTER )
+  else if ( timeunit == TUNIT_MINUTE  ||
+	    timeunit == TUNIT_QUARTER ||
+	    timeunit == TUNIT_30MINUTES )
     {
       *timevalue = days*1440. + secs/60.;
     }
@@ -1265,8 +1313,12 @@ void splitTimevalue(double timevalue, int timeunit, int *date, int *time)
       vdate = cdiEncodeDate(year, month, day);
       vtime = cdiEncodeTime(hour, minute, second);
 
-      Warning("Reset wrong date/time to %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d!",
-	      year, month, day, hour, minute, second);
+      if ( lwarn )
+        {
+          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);
+        }
     }
 
   *date = vdate;
@@ -1413,6 +1465,13 @@ void ptaxisCopy(taxis_t *dest, taxis_t *source)
   dest->fc_unit     = source->fc_unit;
   dest->fc_period   = source->fc_period;
 
+  dest->climatology = source->climatology;
+  delete_refcount_string(dest->name);
+  delete_refcount_string(dest->longname);
+  dest->name = dup_refcount_string(source->name);
+  dest->longname = dup_refcount_string(source->longname);
+  if (dest->self != CDI_UNDEFID)
+    reshSetStatus(dest->self, &taxisOps, RESH_DESYNC_IN_USE);
   reshUnlock ();
 }
 
@@ -1510,9 +1569,9 @@ taxisGetPackSize(void *p, void *context)
     = serializeGetSize(taxisNint, DATATYPE_INT, context)
     + serializeGetSize(1, DATATYPE_UINT32, context)
     + (taxisptr->name ?
-       serializeGetSize(strlen(taxisptr->name), DATATYPE_TXT, context) : 0)
+       serializeGetSize((int)strlen(taxisptr->name), DATATYPE_TXT, context) : 0)
     + (taxisptr->longname ?
-       serializeGetSize(strlen(taxisptr->longname), DATATYPE_TXT,
+       serializeGetSize((int)strlen(taxisptr->longname), DATATYPE_TXT,
                         context) : 0);
   return packBufferSize;
 }
@@ -1561,8 +1620,8 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
 
   if (intBuffer[idx])
     {
-      size_t len = intBuffer[idx];
-      char *name = (char*) xmalloc(len + 1);
+      int len = intBuffer[idx];
+      char *name = new_refcount_string((size_t)len);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       name, len, DATATYPE_TXT, context);
       name[len] = '\0';
@@ -1571,8 +1630,8 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
   idx++;
   if (intBuffer[idx])
     {
-      size_t len = intBuffer[idx];
-      char *longname = (char*) xmalloc(len + 1);
+      int len = intBuffer[idx];
+      char *longname = new_refcount_string((size_t)len);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       longname, len, DATATYPE_TXT, context);
       longname[len] = '\0';
diff --git a/libcdi/src/taxis.h b/libcdi/src/taxis.h
index 8ccc14d..00f0f31 100644
--- a/libcdi/src/taxis.h
+++ b/libcdi/src/taxis.h
@@ -42,6 +42,9 @@ double   cdiEncodeTimeval(int date, int time, taxis_t* taxis);
 void     timeval2vtime(double timevalue, taxis_t* taxis, int* vdate, int* vtime);
 double   vtime2timeval(int vdate, int vtime, taxis_t *taxis);
 
+void    ptaxisDefName(taxis_t *taxisptr, const char *name);
+void    ptaxisDefLongname(taxis_t *taxisptr, const char *name);
+void    taxisDestroyKernel(taxis_t *taxisptr);
 #if !defined (SX)
 extern const resOps taxisOps;
 #endif
diff --git a/libcdi/src/timebase.c b/libcdi/src/timebase.c
index 3c1800c..03d2162 100644
--- a/libcdi/src/timebase.c
+++ b/libcdi/src/timebase.c
@@ -194,9 +194,9 @@ double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *d
 
   *secs = (int) sec_of_day;
 
-  seconds = *days*86400. + sec_of_day;
+  seconds = *days * 86400 + sec_of_day;
 
-  return (seconds);
+  return (double)seconds;
 }
 
 
diff --git a/libcdi/src/tsteps.c b/libcdi/src/tsteps.c
index 7eac592..a4c22b6 100644
--- a/libcdi/src/tsteps.c
+++ b/libcdi/src/tsteps.c
@@ -41,7 +41,8 @@ int tstepsNewEntry(stream_t *streamptr)
     {
       if ( tstepsTableSize == 0 ) tstepsTableSize = 1;
       tstepsTableSize = 2*tstepsTableSize;
-      tstepsTable = (tsteps_t *) realloc(tstepsTable, tstepsTableSize*sizeof(tsteps_t));
+      tstepsTable = (tsteps_t *)xrealloc(tstepsTable,
+                                         (size_t)tstepsTableSize * sizeof (tsteps_t));
       if ( tstepsTable == NULL )
 	{
           Message("tstepsTableSize = %d", tstepsTableSize);
@@ -62,8 +63,8 @@ int tstepsNewEntry(stream_t *streamptr)
 
 void cdiCreateTimesteps(stream_t *streamptr)
 {
-  int ntsteps;
-  int tsID;
+  long ntsteps;
+  long tsID;
 
   if ( streamptr->ntsteps < 0 || streamptr->tstepsTableSize > 0 )
     return;
@@ -71,16 +72,14 @@ void cdiCreateTimesteps(stream_t *streamptr)
   if ( streamptr->ntsteps == 0 ) ntsteps = 1;    /* <<<<<-------- */
   else ntsteps = streamptr->ntsteps;
 
-  streamptr->tsteps = (tsteps_t *) malloc(ntsteps*sizeof(tsteps_t));
-  if ( streamptr->tsteps == NULL )
-    SysError("Allocation of tsteps_t failed");
+  streamptr->tsteps = (tsteps_t *)xmalloc((size_t)ntsteps*sizeof(tsteps_t));
 
-  streamptr->tstepsTableSize = ntsteps;
-  streamptr->tstepsNextID    = ntsteps;
+  streamptr->tstepsTableSize = (int)ntsteps;
+  streamptr->tstepsNextID    = (int)ntsteps;
 
   for ( tsID = 0; tsID < ntsteps; tsID++ )
     {
-      tstepsInitEntry(streamptr, tsID);
+      tstepsInitEntry(streamptr, (int)tsID);
       streamptr->tsteps[tsID].taxis.used = TRUE;
     }
 }
diff --git a/libcdi/src/varscan.c b/libcdi/src/varscan.c
index 2d29cd9..de8a0d8 100644
--- a/libcdi/src/varscan.c
+++ b/libcdi/src/varscan.c
@@ -14,7 +14,8 @@
 #include "zaxis.h"
 
 
-extern void zaxisGetIndexList ( int, int * );
+extern void zaxisGetIndexList(int, int *);
+extern void zaxisDefLtype2(int zaxisID, int ltype2);
 
 
 #undef  UNDEFID
@@ -45,7 +46,8 @@ typedef struct
   int           timaccu;
   int           gridID;
   int           zaxistype;
-  int           ltype;     /* GRIB level type */
+  int           ltype1;     /* GRIB first level type */
+  int           ltype2;     /* GRIB second level type */
   int           lbounds;
   int           level_sf;
   int           level_unit;
@@ -66,6 +68,7 @@ typedef struct
   char         *units;
   ensinfo_t    *ensdata;
   int           typeOfGeneratingProcess;
+  int           productDefinitionTemplate;
 #if  defined  (HAVE_LIBGRIB_API)
   /* (Optional) list of keyword/double value pairs */
   int           opt_grib_dbl_nentries;
@@ -80,10 +83,9 @@ typedef struct
 vartable_t;
 
 
-int vartableInit = 0;
-vartable_t *vartable;
+static vartable_t *vartable;
 static int varTablesize = 0;
-int nvars = 0;
+static int nvars = 0;
 
 
 static
@@ -96,7 +98,8 @@ void paramInitEntry(int varID, int param)
   vartable[varID].timaccu        = 0;
   vartable[varID].gridID         = UNDEFID;
   vartable[varID].zaxistype      = 0;
-  vartable[varID].ltype          = 0;
+  vartable[varID].ltype1         = 0;
+  vartable[varID].ltype2         = -1;
   vartable[varID].lbounds        = 0;
   vartable[varID].level_sf       = 0;
   vartable[varID].level_unit     = 0;
@@ -106,7 +109,8 @@ void paramInitEntry(int varID, int param)
   vartable[varID].instID         = UNDEFID;
   vartable[varID].modelID        = UNDEFID;
   vartable[varID].tableID        = UNDEFID;
-  vartable[varID].typeOfGeneratingProcess  = UNDEFID;
+  vartable[varID].typeOfGeneratingProcess   = UNDEFID;
+  vartable[varID].productDefinitionTemplate = UNDEFID;
   vartable[varID].comptype       = COMPRESS_NONE;
   vartable[varID].complevel      = 1;
   vartable[varID].lmissval       = 0;
@@ -119,15 +123,16 @@ void paramInitEntry(int varID, int param)
 }
 
 static
-int varGetEntry(int param, int zaxistype, int ltype, const char *name)
+int varGetEntry(int param, int zaxistype, int ltype1, int tsteptype, const char *name)
 {
   int varID;
 
   for ( varID = 0; varID < varTablesize; varID++ )
     {
-      if ( vartable[varID].param     == param     &&
-	   vartable[varID].zaxistype == zaxistype &&
-	   vartable[varID].ltype     == ltype )
+      if ( vartable[varID].param      == param       &&
+	   vartable[varID].zaxistype  == zaxistype   &&
+	   vartable[varID].ltype1     == ltype1      &&
+	   vartable[varID].tsteptype  == tsteptype )
         {
           if ( name && name[0] && vartable[varID].name && vartable[varID].name[0] )
             {
@@ -193,7 +198,8 @@ int levelNewEntry(int varID, int level1, int level2)
       int i;
 
       levelTableSize = 2;
-      levelTable = (leveltable_t *) malloc(levelTableSize*sizeof(leveltable_t));
+      levelTable = (leveltable_t *)xmalloc((size_t)levelTableSize
+                                           * sizeof (leveltable_t));
       if( levelTable == NULL )
 	{
           Message("levelTableSize = %d", levelTableSize);
@@ -219,7 +225,8 @@ int levelNewEntry(int varID, int level1, int level2)
       int i;
 
       levelTableSize = 2*levelTableSize;
-      levelTable = (leveltable_t *) realloc(levelTable, levelTableSize*sizeof(leveltable_t));
+      levelTable = (leveltable_t *)xrealloc(levelTable, (size_t)levelTableSize
+                                            * sizeof (leveltable_t));
       if( levelTable == NULL )
 	{
           Message("levelTableSize = %d", levelTableSize);
@@ -258,7 +265,8 @@ int paramNewEntry(int param)
       int i;
 
       varTablesize = 2;
-      vartable = (vartable_t *) malloc(varTablesize*sizeof(vartable_t));
+      vartable = (vartable_t *)xmalloc((size_t)varTablesize
+                                       * sizeof (vartable_t));
       if( vartable == NULL )
 	{
           Message("varTablesize = %d", varTablesize);
@@ -289,8 +297,9 @@ int paramNewEntry(int param)
     {
       int i;
 
-      varTablesize = 2*varTablesize;
-      vartable = (vartable_t *) realloc(vartable, varTablesize*sizeof(vartable_t));
+      varTablesize = 2 * varTablesize;
+      vartable = (vartable_t *)xrealloc(vartable, (size_t)varTablesize
+                                        * sizeof (vartable_t));
       if( vartable == NULL )
 	{
           Message("varTablesize = %d", varTablesize);
@@ -316,26 +325,27 @@ int paramNewEntry(int param)
 
 void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
 		  int level1, int level2, int level_sf, int level_unit, int prec,
-		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype,
+		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
 		  const char *name, const char *stdname, const char *longname, const char *units)
 {
   int varID = UNDEFID;
   int levelID = -1;
 
   if ( ! (cdiSplitLtype105 == 1 && zaxistype == ZAXIS_HEIGHT) )
-    varID = varGetEntry(param, zaxistype, ltype, name);
+    varID = varGetEntry(param, zaxistype, ltype1, tsteptype, name);
 
   if ( varID == UNDEFID )
     {
       nvars++;
       varID = paramNewEntry(param);
-      vartable[varID].gridID    = gridID;
-      vartable[varID].zaxistype = zaxistype;
-      vartable[varID].ltype     = ltype;
-      vartable[varID].lbounds   = lbounds;
-      vartable[varID].level_sf  = level_sf;
+      vartable[varID].gridID     = gridID;
+      vartable[varID].zaxistype  = zaxistype;
+      vartable[varID].ltype1     = ltype1;
+      vartable[varID].ltype2     = ltype2;
+      vartable[varID].lbounds    = lbounds;
+      vartable[varID].level_sf   = level_sf;
       vartable[varID].level_unit = level_unit;
-      if ( tsteptype != UNDEFID ) vartable[varID].tsteptype = tsteptype;
+      vartable[varID].tsteptype  = tsteptype;
       if ( numavg ) vartable[varID].timave = 1;
 
       if ( name )     if ( name[0] )     vartable[varID].name     = strdup(name);
@@ -351,12 +361,12 @@ void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
       if ( vartable[varID].gridID != gridID )
 	{
 	  Message("param = %s gridID = %d", paramstr, gridID);
-	  Error("horizontal grid must not change for same param!");
+	  Error("horizontal grid must not change for same parameter!");
 	}
       if ( vartable[varID].zaxistype != zaxistype )
 	{
 	  Message("param = %s zaxistype = %d", paramstr, zaxistype);
-	  Error("zaxistype must not change for same param!");
+	  Error("zaxistype must not change for same parameter!");
 	}
     }
 
@@ -437,7 +447,7 @@ void cdi_generate_vars(stream_t *streamptr)
 {
   int varID, gridID, zaxisID, levelID;
   int instID, modelID, tableID;
-  int param, nlevels, zaxistype, lindex, ltype;
+  int param, nlevels, zaxistype, ltype1, ltype2, lindex;
   int prec;
   int tsteptype;
   int timave, timaccu;
@@ -447,32 +457,29 @@ void cdi_generate_vars(stream_t *streamptr)
   double *dlevels = NULL;
   double *dlevels1 = NULL;
   double *dlevels2 = NULL;
-  int vlistID;
-  int *varids, index, varid;
+  int index, varid;
   double level_sf = 1;
+  int vlistID = streamptr->vlistID;
 
-  vlistID =  streamptr->vlistID;
-
-  varids = (int *) malloc(nvars*sizeof(int));
+  int *varids = (int *)xmalloc((size_t)nvars*sizeof(int));
   for ( varID = 0; varID < nvars; varID++ ) varids[varID] = varID;
 
   if ( streamptr->sortname )
     {
-      int index;
       param_t **varInfo;
-      varInfo    = (param_t **) malloc(nvars*sizeof(param_t *));
-      varInfo[0] = (param_t *)  malloc(nvars*sizeof(param_t));
+      varInfo    = (param_t **)xmalloc((size_t)nvars * sizeof (param_t *));
+      varInfo[0] = (param_t *)xmalloc((size_t)nvars * sizeof (param_t));
 
-      for ( index = 1; index < nvars; index++ )
+      for ( int index = 1; index < nvars; index++ )
 	varInfo[index] = varInfo[0] + index;
 
       for ( varid = 0; varid < nvars; varid++ )
 	{
 	  varInfo[varid]->varid = varids[varid];
 	  varInfo[varid]->param = vartable[varid].param;
-	  varInfo[varid]->ltype = vartable[varid].ltype;
+	  varInfo[varid]->ltype = vartable[varid].ltype1;
 	}
-      qsort(varInfo[0], nvars, sizeof(param_t), cmpparam);
+      qsort(varInfo[0], (size_t)nvars, sizeof(param_t), cmpparam);
       for ( varid = 0; varid < nvars; varid++ )
 	{
 	  varids[varid] = varInfo[varid]->varid;
@@ -483,32 +490,33 @@ void cdi_generate_vars(stream_t *streamptr)
 
   for ( index = 0; index < nvars; index++ )
     {
-      varid     = varids[index];
+      varid      = varids[index];
 
-      gridID    = vartable[varid].gridID;
-      param     = vartable[varid].param;
-      nlevels   = vartable[varid].nlevels;
-      ltype     = vartable[varid].ltype;
+      gridID     = vartable[varid].gridID;
+      param      = vartable[varid].param;
+      nlevels    = vartable[varid].nlevels;
+      ltype1     = vartable[varid].ltype1;
+      ltype2     = vartable[varid].ltype2;
       zaxistype = vartable[varid].zaxistype;
-      if ( ltype == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
+      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
 	zaxistype = cdiDefaultLeveltype;
-      lbounds   = vartable[varid].lbounds;
-      prec      = vartable[varid].prec;
-      instID    = vartable[varid].instID;
-      modelID   = vartable[varid].modelID;
-      tableID   = vartable[varid].tableID;
-      tsteptype = vartable[varid].tsteptype;
-      timave    = vartable[varid].timave;
-      timaccu   = vartable[varid].timaccu;
-      comptype  = vartable[varid].comptype;
+      lbounds    = vartable[varid].lbounds;
+      prec       = vartable[varid].prec;
+      instID     = vartable[varid].instID;
+      modelID    = vartable[varid].modelID;
+      tableID    = vartable[varid].tableID;
+      tsteptype  = vartable[varid].tsteptype;
+      timave     = vartable[varid].timave;
+      timaccu    = vartable[varid].timaccu;
+      comptype   = vartable[varid].comptype;
 
       level_sf  = 1;
       if ( vartable[varid].level_sf != 0 ) level_sf = 1./vartable[varid].level_sf;
 
       zaxisID = UNDEFID;
 
-      if ( ltype == 0 && zaxistype == ZAXIS_GENERIC && nlevels == 1 &&
-	   ! (fabs(vartable[varid].levelTable[0].level1)>0) )
+      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && nlevels == 1 &&
+	   vartable[varid].levelTable[0].level1 == 0 )
 	zaxistype = ZAXIS_SURFACE;
 
       dlevels = (double *) malloc(nlevels*sizeof(double));
@@ -578,7 +586,12 @@ void cdi_generate_vars(stream_t *streamptr)
 
       char *unitptr = cdiUnitNamePtr(vartable[varid].level_unit);
       zaxisID = varDefZaxis(vlistID, zaxistype, nlevels, dlevels, lbounds, dlevels1, dlevels2,
-                            Vctsize, Vct, NULL, NULL, unitptr, 0, 0, ltype);
+                            (int)Vctsize, Vct, NULL, NULL, unitptr, 0, 0, ltype1);
+
+      if ( ltype1 != ltype2 && ltype2 != -1 )
+        {
+          zaxisDefLtype2(zaxisID, ltype2);
+        }
 
       if ( zaxisInqType(zaxisID) == ZAXIS_REFERENCE )
         {
@@ -603,6 +616,9 @@ void cdi_generate_vars(stream_t *streamptr)
       if ( vartable[varid].typeOfGeneratingProcess != UNDEFID )
         vlistDefVarTypeOfGeneratingProcess(vlistID, varID, vartable[varid].typeOfGeneratingProcess);
 
+      if ( vartable[varid].productDefinitionTemplate != UNDEFID )
+        vlistDefVarProductDefinitionTemplate(vlistID, varID, vartable[varid].productDefinitionTemplate);
+
       if ( vartable[varid].lmissval ) vlistDefVarMissval(vlistID, varID, vartable[varid].missval);
 
       if ( vartable[varid].name )     vlistDefVarName(vlistID, varID, vartable[varid].name);
@@ -627,6 +643,7 @@ void cdi_generate_vars(stream_t *streamptr)
           int idx = vlistptr->vars[varID].opt_grib_int_nentries;
           vlistptr->vars[varID].opt_grib_int_nentries++;
           if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
+          vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
           vlistptr->vars[varID].opt_grib_int_val[idx] = vartable[varid].opt_grib_int_val[idx];
           vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(vartable[varid].opt_grib_int_keyword[idx]);
         }
@@ -635,6 +652,7 @@ void cdi_generate_vars(stream_t *streamptr)
           int idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
           vlistptr->vars[varID].opt_grib_dbl_nentries++;
           if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
+          vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
           vlistptr->vars[varID].opt_grib_dbl_val[idx] = vartable[varid].opt_grib_dbl_val[idx];
           vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(vartable[varid].opt_grib_dbl_keyword[idx]);
         }
@@ -802,14 +820,14 @@ int varDefGrid(int vlistID, grid_t grid, int mode)
 }
 
 
-int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *levels, char *longname, char *units, int ltype)
+int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *levels, char *longname, char *units, int ltype1)
 {
   int differ = 1;
   int levelID;
   int zlbounds = 0;
   int ltype_is_equal = FALSE;
 
-  if ( ltype == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
+  if ( ltype1 == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
 
   if ( ltype_is_equal && (zaxistype == zaxisInqType(zaxisID) || zaxistype == ZAXIS_GENERIC) )
     {
@@ -851,7 +869,7 @@ int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, double *l
 
 int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
 		double *levels1, double *levels2, int vctsize, double *vct, char *name,
-		char *longname, char *units, int prec, int mode, int ltype)
+		char *longname, char *units, int prec, int mode, int ltype1)
 {
   /*
     mode: 0 search in vlist and zaxis table
@@ -875,7 +893,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
       {
 	zaxisID = vlistptr->zaxisIDs[index];
 
-	if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype) == 0 )
+	if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype1) == 0 )
 	  {
 	    zaxisdefined = 1;
 	    break;
@@ -893,7 +911,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
           for ( i = 0; i < nzaxis; i++ )
             {
               zaxisID = zaxisIndexList[i];
-              if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype) == 0 )
+              if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, longname, units, ltype1) == 0 )
                 {
                   zaxisglobdefined = 1;
                   break;
@@ -938,7 +956,7 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
 	  zaxisDefLongname(zaxisID, longname);
 	  zaxisDefUnits(zaxisID, units);
 	  zaxisDefPrec(zaxisID, prec);
-	  zaxisDefLtype(zaxisID, ltype);
+	  zaxisDefLtype(zaxisID, ltype1);
 	}
 
       nzaxis = vlistptr->nzaxis;
@@ -1023,6 +1041,12 @@ void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess)
 }
 
 
+void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate)
+{
+  vartable[varID].productDefinitionTemplate = productDefinitionTemplate;
+}
+
+
 void varDefOptGribInt(int varID, long lval, const char *keyword)
 {
 #if  defined  (HAVE_LIBGRIB_API)
diff --git a/libcdi/src/varscan.h b/libcdi/src/varscan.h
index cee34b2..87e34d4 100644
--- a/libcdi/src/varscan.h
+++ b/libcdi/src/varscan.h
@@ -8,7 +8,7 @@
 
 void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
 		  int level1, int level2, int level_sf, int level_unit, int prec,
-		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype,
+		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
 		  const char *name, const char *stdname, const char *longname, const char *units);
 
 void varDefVCT(size_t vctsize, double *vctptr);
@@ -30,6 +30,7 @@ int  varInqTable(int varID);
 void varDefEnsembleInfo(int varID, int ens_idx, int ens_count, int forecast_type);
 
 void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess);
+void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate);
 
 
 void varDefOptGribInt(int varID, long lval, const char *keyword);
diff --git a/libcdi/src/version.c b/libcdi/src/version.c
index 2201cc0..35a18bf 100644
--- a/libcdi/src/version.c
+++ b/libcdi/src/version.c
@@ -7,7 +7,7 @@
  */
 
 #if defined (VERSION)
-   static char cdi_libvers[] = VERSION " of "__DATE__" "__TIME__;
+   static const char cdi_libvers[] = VERSION " of "__DATE__" "__TIME__;
 #else
 #  error "VERSION undefined"
 #endif
@@ -15,12 +15,12 @@
 #if defined(__cplusplus)
 extern "C" {
 #endif
-char *cdiLibraryVersion(void);
+const char *cdiLibraryVersion(void);
 #if defined(__cplusplus)
 }
 #endif
 */
-char *cdiLibraryVersion(void)
+const char *cdiLibraryVersion(void)
 {
   return (cdi_libvers);
 }
diff --git a/libcdi/src/vlist.c b/libcdi/src/vlist.c
index 70951ce..224d27d 100644
--- a/libcdi/src/vlist.c
+++ b/libcdi/src/vlist.c
@@ -57,9 +57,9 @@ vlist_compare(vlist_t *a, vlist_t *b)
   int nvars = a->nvars;
   for (int varID = 0; varID < nvars; ++varID)
     diff |= vlistVarCompare(a, varID, b, varID);
-  int natts = a->atts.nelems;
-  for (int attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, attID);
+  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);
   return diff;
 }
 
@@ -86,15 +86,16 @@ resOps vlist_ops = {
 };
 
 
-vlist_t *vlist_to_pointer(int code)
+vlist_t *vlist_to_pointer(int vlistID)
 {
   VLIST_INIT();
-  return (vlist_t*) reshGetVal(code, &vlist_ops );
+  return (vlist_t*) reshGetVal(vlistID, &vlist_ops );
 }
 
 static
 void vlist_init_entry(vlist_t *vlistptr)
 {
+  vlistptr->locked         = 0;
   vlistptr->self           = CDI_UNDEFID;
   vlistptr->nvars          = 0;
   vlistptr->vars           = NULL;
@@ -155,9 +156,7 @@ void vlist_initialize(void)
 static
 void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
 {
-  int vlistID2;
-
-  vlistID2 = vlistptr2->self;
+  int vlistID2 = vlistptr2->self;
   memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
   vlistptr2->atts.nelems = 0;
   vlistptr2->self = vlistID2;
@@ -170,6 +169,34 @@ void vlist_check_ptr(const char *caller, vlist_t *vlistptr)
     Errorc("vlist undefined!");
 }
 
+
+void vlist_lock(int vlistID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlist_check_ptr(__func__, vlistptr);
+
+  if ( !vlistptr->locked )
+    {
+      vlistptr->locked = 1;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
+}
+
+
+void vlist_unlock(int vlistID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlist_check_ptr(__func__, vlistptr);
+
+  if ( vlistptr->locked )
+    {
+      vlistptr->locked = 0;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
+}
+
 /*
 @Function  vlistCreate
 @Title     Create a variable list
@@ -197,18 +224,12 @@ vlistDestroy(vlistID);
 */
 int vlistCreate(void)
 {
-  int vlistID = 0;
-  vlist_t *vlistptr;
-
   cdiInitialize();
 
   VLIST_INIT();
 
-  vlistptr = vlist_new_entry(CDI_UNDEFID);
-
-  vlistID = vlistptr->self;
-
-  return (vlistID);
+  vlist_t *vlistptr = vlist_new_entry(CDI_UNDEFID);
+  return (vlistptr->self);
 }
 
 static void
@@ -233,12 +254,11 @@ vlist_delete(vlist_t *vlistptr)
       if ( vlistptr->vars[varID].ensdata )  free(vlistptr->vars[varID].ensdata);
 
 #if  defined  (HAVE_LIBGRIB_API)
-      int i;
-      for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
+      for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
 	if ( vlistptr->vars[varID].opt_grib_int_keyword[i] )
 	  free(vlistptr->vars[varID].opt_grib_int_keyword[i]);
       }
-      for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
+      for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
 	if ( vlistptr->vars[varID].opt_grib_dbl_keyword[i] )
 	  free(vlistptr->vars[varID].opt_grib_dbl_keyword[i]);
       }
@@ -265,11 +285,12 @@ vlist_delete(vlist_t *vlistptr)
 */
 void vlistDestroy(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  vlist_delete(vlistptr);
+  if ( vlistptr->locked )
+    Warning("Destroying of a locked object (vlistID=%d) failed!", vlistID);
+  else
+    vlist_delete(vlistptr);
 }
 
 /*
@@ -296,6 +317,7 @@ void vlistCopy(int vlistID2, int vlistID1)
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
+  var_t *vlist2vars = vlistptr2->vars;
   vlist_copy(vlistptr2, vlistptr1);
 
   vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
@@ -303,13 +325,15 @@ void vlistCopy(int vlistID2, int vlistID1)
   if ( vlistptr1->vars )
     {
       int nvars = vlistptr1->nvars;
-      int varID;
 
       //vlistptr2->varsAllocated = nvars;
-      vlistptr2->vars = (var_t *) malloc(vlistptr2->varsAllocated*sizeof(var_t));
-      memcpy(vlistptr2->vars, vlistptr1->vars, vlistptr2->varsAllocated*sizeof(var_t));
+      vlistptr2->vars
+        = xrealloc(vlist2vars,
+                   (size_t)vlistptr2->varsAllocated * sizeof (var_t));
+      memcpy(vlistptr2->vars, vlistptr1->vars,
+             (size_t)vlistptr2->varsAllocated * sizeof (var_t));
 
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
         {
           if ( vlistptr1->vars[varID].name )
             vlistptr2->vars[varID].name = strdupx(vlistptr1->vars[varID].name);
@@ -334,19 +358,20 @@ void vlistCopy(int vlistID2, int vlistID1)
           /* Local change: 2013-01-28, FP (DWD) */
           /* ---------------------------------- */
 
-	  int i;
 	  vlistptr2->vars[varID].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
-	  for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
+	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
 	    if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 	      vlistptr2->vars[varID].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 	      vlistptr2->vars[varID].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+	      vlistptr2->vars[varID].opt_grib_int_update[i]  = TRUE;
 	    }
 	  }
 	  vlistptr2->vars[varID].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
-	  for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
+	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
 	    if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 	      vlistptr2->vars[varID].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 	      vlistptr2->vars[varID].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+	      vlistptr2->vars[varID].opt_grib_dbl_update[i]  = TRUE;
 	    }
 	  }
 #endif
@@ -356,10 +381,13 @@ void vlistCopy(int vlistID2, int vlistID1)
 
           if ( vlistptr1->vars[varID].levinfo )
             {
-              int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-              vlistptr2->vars[varID].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
+              size_t nlevs
+                = (size_t)zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+              vlistptr2->vars[varID].levinfo
+                = xmalloc(nlevs * sizeof (levinfo_t));
               memcpy(vlistptr2->vars[varID].levinfo,
-                     vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+                     vlistptr1->vars[varID].levinfo,
+                     nlevs * sizeof (levinfo_t));
             }
 	}
     }
@@ -384,9 +412,7 @@ The function @func{vlistDuplicate} duplicates the variable list from vlistID1.
 int vlistDuplicate(int vlistID)
 {
   int vlistIDnew;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -401,9 +427,7 @@ int vlistDuplicate(int vlistID)
 void vlistClearFlag(int vlistID)
 {
   int varID, levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   for ( varID = 0; varID < vlistptr->nvars; varID++ )
     {
@@ -423,24 +447,19 @@ static
 int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels,
                          double *lbounds, double *ubounds, int vctsize, const double *vct)
 {
-  int zaxisdefined;
-  int nzaxis;
   int zaxisID = CDI_UNDEFID;
-  int index;
   int zaxisglobdefined = 0;
   int has_bounds = FALSE;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  zaxisdefined = 0;
-  nzaxis = vlistptr->nzaxis;
+  int zaxisdefined = 0;
+  int nzaxis = vlistptr->nzaxis;
 
   if ( lbounds && ubounds ) has_bounds = TRUE;
 
-  for ( index = 0; index < nzaxis; ++index )
+  for ( int index = 0; index < nzaxis; ++index )
     {
       zaxisID = vlistptr->zaxisIDs[index];
 
@@ -456,10 +475,10 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels
       nzaxis = zaxisSize();
       if ( nzaxis > 0 )
         {
-          int *zaxisIndexList;
-          zaxisIndexList = (int *) malloc ( nzaxis * sizeof ( int ));
+          int *zaxisIndexList = (int *)xmalloc((size_t)nzaxis * sizeof (int));
+          reshLock();
           zaxisGetIndexList ( nzaxis, zaxisIndexList );
-          for ( index = 0; index < nzaxis; ++index )
+          for ( int index = 0; index < nzaxis; ++index )
             {
               zaxisID = zaxisIndexList[index];
               if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
@@ -468,7 +487,8 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels
                   break;
                 }
             }
-          if ( zaxisIndexList ) free ( zaxisIndexList );
+          reshUnlock();
+          free(zaxisIndexList);
         }
     }
 
@@ -517,10 +537,8 @@ The function @func{vlistCopyFlag} copies all entries with a flag from vlistID1 t
 */
 void vlistCopyFlag(int vlistID2, int vlistID1)
 {
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
@@ -532,31 +550,29 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
   if ( vlistptr1->vars )
     {
       int nvars = vlistptr1->nvars;
-      int nvars2 = 0, levID2;
-      int nlevs, nlevs2, levID, varID, varID2;
-      int gridID, zaxisID;
-      int index;
+      int nvars2 = 0;
+      int varID2;
 
       vlistptr2->ngrids = 0;
       vlistptr2->nzaxis = 0;
 
-      for ( varID = 0; varID < nvars; varID++ )
-        if ( vlistptr1->vars[varID].flag ) nvars2++;
+      for ( int varID = 0; varID < nvars; varID++ )
+        nvars2 += (vlistptr1->vars[varID].flag != 0);
 
       vlistptr2->nvars = nvars2;
       vlistptr2->varsAllocated = nvars2;
       if ( nvars2 > 0 )
-        vlistptr2->vars  = (var_t *) malloc(nvars2*sizeof(var_t));
+        vlistptr2->vars  = (var_t *)xmalloc((size_t)nvars2*sizeof(var_t));
       else
         vlistptr2->vars  = NULL;
 
       varID2 = 0;
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
 	if ( vlistptr1->vars[varID].flag )
 	  {
 	    vlistptr2->vars[varID2].flag = FALSE;
-	    zaxisID = vlistptr1->vars[varID].zaxisID;
-	    gridID  = vlistptr1->vars[varID].gridID;
+	    int zaxisID = vlistptr1->vars[varID].zaxisID;
+	    int gridID  = vlistptr1->vars[varID].gridID;
 
 	    memcpy(&vlistptr2->vars[varID2], &vlistptr1->vars[varID], sizeof(var_t));
 
@@ -579,7 +595,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 
             if ( vlistptr1->vars[varID].ensdata )
               {
-                vlistptr2->vars[varID2].ensdata = (ensinfo_t *) malloc(sizeof(ensinfo_t));
+                vlistptr2->vars[varID2].ensdata = (ensinfo_t *)xmalloc(sizeof(ensinfo_t));
                 memcpy(vlistptr2->vars[varID2].ensdata,
                        vlistptr1->vars[varID].ensdata, sizeof(ensinfo_t));
               }
@@ -595,6 +611,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	      if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 		vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 		vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+                vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
 	      }
 	    }
 	    vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
@@ -602,6 +619,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	      if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 		vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 		vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+                vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
 	      }
 	    }
 #endif
@@ -609,38 +627,34 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 	    vlistptr2->vars[varID2].atts.nelems = 0;
 	    vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
-	    nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-	    nlevs2 = 0;
+	    int nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+	    int nlevs2 = 0;
             if ( vlistptr1->vars[varID].levinfo )
-              for ( levID = 0; levID < nlevs; levID++ )
-                if ( vlistptr1->vars[varID].levinfo[levID].flag ) nlevs2++;
+              for ( int levID = 0; levID < nlevs; levID++ )
+                nlevs2 += (vlistptr1->vars[varID].levinfo[levID].flag != 0);
 
-	    vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs2*sizeof(levinfo_t));
+	    vlistptr2->vars[varID2].levinfo = (levinfo_t *)xmalloc((size_t)nlevs2 * sizeof (levinfo_t));
 
 	    if ( nlevs != nlevs2 )
 	      {
-		int zaxisType;
-		int zaxisID2;
 		int nvct = 0;
-		double *levels;
 		double *lbounds = NULL, *ubounds = NULL;
 		const double *vct = NULL;
                 char ctemp[CDI_MAX_NAME];
 
 		zaxisID = vlistptr1->vars[varID].zaxisID;
-		levels = (double *) malloc(nlevs2*sizeof(double));
-		levID2 = 0;
+		double *levels = (double *)xmalloc((size_t)nlevs2 * sizeof (double));
+                int levID2 = 0;
                 if (!vlistptr1->vars[varID].levinfo)
                   cdiVlistCreateVarLevInfo(vlistptr1, varID);
-		for ( levID = 0; levID < nlevs; ++levID )
-		  if ( vlistptr1->vars[varID].levinfo[levID].flag )
-		    {
-		      vlistptr1->vars[varID].levinfo[levID].flevelID = levID2;
-		      vlistptr1->vars[varID].levinfo[levID].mlevelID = levID2;
-		      levels[levID2++] = zaxisInqLevel(zaxisID, levID);
-		    }
-
-		zaxisType = zaxisInqType(zaxisID);
+                for ( int levID = 0; levID < nlevs; ++levID )
+                  if ( vlistptr1->vars[varID].levinfo[levID].flag )
+                    {
+                      vlistptr1->vars[varID].levinfo[levID].flevelID = levID2;
+                      vlistptr1->vars[varID].levinfo[levID].mlevelID = levID2;
+                      levels[levID2++] = zaxisInqLevel(zaxisID, levID);
+                    }
+		int zaxisType = zaxisInqType(zaxisID);
 
 		if ( zaxisType == ZAXIS_HYBRID )
 		  {
@@ -650,18 +664,17 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 
                 if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
                   {
-                    double *lbounds1, *ubounds1;
-                    lbounds1 = (double *) malloc(nlevs*sizeof(double));
-                    ubounds1 = (double *) malloc(nlevs*sizeof(double));
+                    lbounds = (double *)xmalloc(2 * (size_t)nlevs2 * sizeof (double));
+                    ubounds = lbounds + nlevs2;
+
+                    double *lbounds1 = (double *)xmalloc(2 * (size_t)nlevs * sizeof (double)),
+                      *ubounds1 = lbounds1 + nlevs;
 
                     zaxisInqLbounds(zaxisID, lbounds1);
                     zaxisInqUbounds(zaxisID, ubounds1);
 
-                    lbounds = (double *) malloc(nlevs2*sizeof(double));
-                    ubounds = (double *) malloc(nlevs2*sizeof(double));
-
-                    levID2 = 0;
-                    for ( levID = 0; levID < nlevs; ++levID )
+                    int levID2 = 0;
+                    for ( int levID = 0; levID < nlevs; ++levID )
                       if ( vlistptr1->vars[varID].levinfo[levID].flag )
                         {
                           lbounds[levID2] = lbounds1[levID];
@@ -670,13 +683,11 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
                         }
 
                     free(lbounds1);
-                    free(ubounds1);
                   }
 
-		zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
+		int zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
 		free(levels);
-                if ( lbounds ) free(lbounds);
-                if ( ubounds ) free(ubounds);
+                free(lbounds);
 
                 zaxisInqName(zaxisID, ctemp);
                 zaxisDefName(zaxisID2, ctemp);
@@ -689,14 +700,14 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 		vlistptr2->vars[varID2].zaxisID = zaxisID2;
 	      }
 
-	    for ( levID = 0; levID < nlevs2; levID++ )
+	    for ( int levID = 0; levID < nlevs2; levID++ )
 	      {
 		vlistptr2->vars[varID2].levinfo[levID].flag  = FALSE;
 		vlistptr2->vars[varID2].levinfo[levID].index = -1;
 	      }
 
-	    levID2 = 0;
-	    for ( levID = 0; levID < nlevs; levID++ )
+	    int levID2 = 0;
+	    for ( int levID = 0; levID < nlevs; levID++ )
 	      if ( vlistptr1->vars[varID].levinfo[levID].flag )
 		{
 		  vlistptr2->vars[varID2].levinfo[levID2].flevelID = levID;
@@ -704,25 +715,8 @@ void vlistCopyFlag(int vlistID2, int vlistID1)
 		  levID2++;
 		}
 
-	    for ( index = 0; index <vlistptr2->ngrids; index++ )
-	      if (vlistptr2->gridIDs[index] == gridID ) break;
-
-	    if ( index == vlistptr2->ngrids )
-	      {
-		vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
-		if (vlistptr2->ngrids >= MAX_GRIDS_PS )
-		  Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
-	      }
-
-	    for ( index = 0; index < vlistptr2->nzaxis; index++ )
-	      if ( vlistptr2->zaxisIDs[index] == zaxisID ) break;
-
-	    if ( index == vlistptr2->nzaxis )
-	      {
-		vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
-		if (vlistptr2->nzaxis >= MAX_ZAXES_PS )
-		  Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
-	      }
+            vlistAdd2GridIDs(vlistptr2, gridID);
+            vlistAdd2ZaxisIDs(vlistptr2, zaxisID);
 
 	    varID2++;
 	  }
@@ -745,32 +739,29 @@ Concatenate the variable list vlistID1 at the end of vlistID2.
 */
 void vlistCat(int vlistID2, int vlistID1)
 {
-  int nvars, nvars1, nvars2;
-  int varID, varID2, nlevs;
-  int index, gridID, zaxisID;
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
-  nvars1 = vlistptr1->nvars;
-  nvars2 = vlistptr2->nvars;
-  nvars = nvars1 + nvars2;
+  int nvars1 = vlistptr1->nvars;
+  int nvars2 = vlistptr2->nvars;
+  int nvars = nvars1 + nvars2;
   vlistptr2->nvars = nvars;
 
   if ( nvars > vlistptr2->varsAllocated )
     {
       vlistptr2->varsAllocated = nvars;
-      vlistptr2->vars = (var_t *) realloc(vlistptr2->vars, nvars*sizeof(var_t));
+      vlistptr2->vars = xrealloc(vlistptr2->vars,
+                                 (size_t)nvars * sizeof (var_t));
     }
-  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars, nvars1*sizeof(var_t));
+  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars,
+         (size_t)nvars1 * sizeof (var_t));
 
-  for ( varID = 0; varID < nvars1; varID++ )
+  for (int varID = 0; varID < nvars1; varID++ )
     {
-      varID2 = varID + nvars2;
+      int varID2 = varID + nvars2;
       vlistptr1->vars[varID].fvarID = varID2;
       vlistptr2->vars[varID2].fvarID = varID;
 
@@ -797,11 +788,14 @@ void vlistCat(int vlistID2, int vlistID1)
       if ( vlistptr1->vars[varID].units )
         vlistptr2->vars[varID2].units = strdupx(vlistptr1->vars[varID].units);
 
-      nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+      int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
       if (vlistptr1->vars[varID].levinfo)
         {
-          vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
-          memcpy(vlistptr2->vars[varID2].levinfo, vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+          vlistptr2->vars[varID2].levinfo
+            = (levinfo_t *)xmalloc((size_t)nlevs * sizeof (levinfo_t));
+          memcpy(vlistptr2->vars[varID2].levinfo,
+                 vlistptr1->vars[varID].levinfo,
+                 (size_t)nlevs * sizeof (levinfo_t));
         }
 
       if ( vlistptr1->vars[varID].ensdata )
@@ -815,19 +809,22 @@ void vlistCat(int vlistID2, int vlistID1)
       /* Local change: 2013-01-28, FP (DWD) */
       /* ---------------------------------- */
 
-      int i;
       vlistptr2->vars[varID2].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
-      for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
+      int n = vlistptr1->vars[varID].opt_grib_int_nentries;
+      for (int i = 0; i < n; ++i) {
 	if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
 	  vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
 	  vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
+          vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
 	}
       }
       vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
-      for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
+      n = vlistptr1->vars[varID].opt_grib_dbl_nentries;
+      for (int i = 0; i < n; i++) {
 	if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
 	  vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
 	  vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
+          vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
 	}
       }
 #endif
@@ -835,27 +832,8 @@ void vlistCat(int vlistID2, int vlistID1)
       vlistptr2->vars[varID2].atts.nelems = 0;
       vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);
 
-      gridID = vlistptr1->vars[varID].gridID;
-      for ( index = 0; index < vlistptr2->ngrids; index++ )
-        if ( gridID == vlistptr2->gridIDs[index] ) break;
-
-      if ( index == vlistptr2->ngrids )
-	{
-	  vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
-	  if ( vlistptr2->ngrids >= MAX_GRIDS_PS )
-	    Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
-	}
-
-      zaxisID = vlistptr1->vars[varID].zaxisID;
-      for ( index = 0; index < vlistptr2->nzaxis; index++ )
-        if ( zaxisID == vlistptr2->zaxisIDs[index] ) break;
-
-      if ( index == vlistptr2->nzaxis )
-	{
-	  vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
-	  if ( vlistptr2->nzaxis >= MAX_ZAXES_PS )
-	    Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
-	}
+      vlistAdd2GridIDs(vlistptr2, vlistptr1->vars[varID].gridID);
+      vlistAdd2ZaxisIDs(vlistptr2, vlistptr1->vars[varID].zaxisID);
     }
 }
 
@@ -875,22 +853,15 @@ Merge the variable list vlistID1 to the variable list vlistID2.
 */
 void vlistMerge(int vlistID2, int vlistID1)
 {
-  int nvars1, nvars2;
-  int varID = 0, varID2, levID, nlevs, nlevs1, nlevs2;
-  int index, zaxisID;
-  int zaxisID1, zaxisID2;
-  int *lvar;
-  double *levels;
-  vlist_t *vlistptr1, *vlistptr2;
-
-  vlistptr1 = vlist_to_pointer(vlistID1);
-  vlistptr2 = vlist_to_pointer(vlistID2);
+  int varID = 0;
+  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
+    *vlistptr2 = vlist_to_pointer(vlistID2);
 
   vlist_check_ptr(__func__, vlistptr1);
   vlist_check_ptr(__func__, vlistptr2);
 
-  nvars1 = vlistptr1->nvars;
-  nvars2 = vlistptr2->nvars;
+  int nvars1 = vlistptr1->nvars;
+  int nvars2 = vlistptr2->nvars;
 
   if ( nvars1 == nvars2 )
     {
@@ -919,71 +890,72 @@ void vlistMerge(int vlistID2, int vlistID1)
           vlistptr1->vars[varID].mvarID = varID;
           vlistptr2->vars[varID].mvarID = varID;
 
-          nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
-          nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
+          int nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
+          int nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
 
-          nlevs = nlevs1 + nlevs2;
+          int nlevs = nlevs1 + nlevs2;
 
           /*
           fprintf(stderr, "var %d %d %d %d %d\n", varID, nlevs1, nlevs2, nlevs, sizeof(levinfo_t));
           */
           if (vlistptr1->vars[varID].levinfo)
             {
-              vlistptr2->vars[varID].levinfo = (levinfo_t*)
-                xrealloc(vlistptr2->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
+              vlistptr2->vars[varID].levinfo =
+                (levinfo_t*)xrealloc(vlistptr2->vars[varID].levinfo,
+                                     (size_t)nlevs * sizeof(levinfo_t));
 
               memcpy(vlistptr2->vars[varID].levinfo+nlevs2,
-                     vlistptr1->vars[varID].levinfo, nlevs1*sizeof(levinfo_t));
+                     vlistptr1->vars[varID].levinfo,
+                     (size_t)nlevs1 * sizeof (levinfo_t));
             }
           else
             cdiVlistCreateVarLevInfo(vlistptr1, varID);
-	  for ( levID = 0; levID < nlevs1; levID++ )
+	  for ( int levID = 0; levID < nlevs1; levID++ )
 	    {
 	      vlistptr1->vars[varID].levinfo[levID].mlevelID = nlevs2 + levID;
 	    }
 	}
 
-      lvar = (int *) malloc(nvars2*sizeof(int));
-      for ( varID = 0; varID < nvars2; varID++ ) lvar[varID] = FALSE;
+      int *lvar = (int *)xcalloc((size_t)nvars2, sizeof(int));
 
       for ( varID = 0; varID < nvars2; varID++ )
         {
           if ( lvar[varID] == TRUE ) continue;
 
-          zaxisID1 = vlistptr1->vars[varID].zaxisID;
-          zaxisID2 = vlistptr2->vars[varID].zaxisID;
+          int zaxisID1 = vlistptr1->vars[varID].zaxisID;
+          int zaxisID2 = vlistptr2->vars[varID].zaxisID;
           /*
           nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
           nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
           */
-          nlevs1 = zaxisInqSize(zaxisID1);
-          nlevs2 = zaxisInqSize(zaxisID2);
+          int nlevs1 = zaxisInqSize(zaxisID1);
+          int nlevs2 = zaxisInqSize(zaxisID2);
           /*
           fprintf(stderr, "zaxis %d %d %d %d\n", zaxisID1, zaxisID2, nlevs1, nlevs2);
           */
-          nlevs = nlevs1 + nlevs2;
+          int nlevs = nlevs1 + nlevs2;
 
-          zaxisID = zaxisDuplicate(zaxisID2);
+          int zaxisID = zaxisDuplicate(zaxisID2);
 
           zaxisResize(zaxisID, nlevs);
 
-          levels = (double *) malloc(nlevs1*sizeof(double));
+          double *levels = (double *)xmalloc((size_t)nlevs1 * sizeof(double));
 
           zaxisInqLevels(zaxisID1, levels);
           /*
           for ( levID = 0; levID < nlevs1; levID++ )
             fprintf(stderr, "%d %d %d %d %d %g\n", varID, levID, nlevs1, nlevs2, vlistptr2->vars[varID].nlevs, levels[levID]);
           */
-          for ( levID = 0; levID < nlevs1; levID++ )
+          for ( int levID = 0; levID < nlevs1; levID++ )
             zaxisDefLevel(zaxisID, nlevs2+levID, levels[levID]);
 
           free(levels);
 
-          for ( index = 0; index < vlistptr2->nzaxis; index++ )
+          for ( int index = 0; index < vlistptr2->nzaxis; index++ )
             if ( vlistptr2->zaxisIDs[index] == zaxisID2 )
               vlistptr2->zaxisIDs[index] = zaxisID;
 
-          for ( varID2 = 0; varID2 < nvars2; varID2++ )
+          for ( int varID2 = 0; varID2 < nvars2; varID2++ )
             if ( lvar[varID2] == FALSE && vlistptr2->vars[varID2].zaxisID == zaxisID2 )
               {
                 vlistptr2->vars[varID2].zaxisID = zaxisID;
@@ -1017,9 +989,7 @@ The function @func{vlistNvars} returns the number of variables in the variable l
 */
 int vlistNvars(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1029,14 +999,12 @@ int vlistNvars(int vlistID)
 
 int vlistNrecs(int vlistID)
 {
-  int varID, nrecs = 0;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int nrecs = 0;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( varID = 0; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     nrecs +=  zaxisInqSize(vlistptr->vars[varID].zaxisID);
 
   return (nrecs);
@@ -1045,10 +1013,8 @@ int vlistNrecs(int vlistID)
 
 int vlistNumber(int vlistID)
 {
-  int varID, number, number2, datatype;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int number, number2, datatype;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1058,7 +1024,7 @@ int vlistNumber(int vlistID)
   else
     number = CDI_REAL;
 
-  for ( varID = 1; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 1; varID < vlistptr->nvars; varID++ )
     {
       datatype = vlistptr->vars[varID].datatype;
       if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
@@ -1094,9 +1060,7 @@ The function @func{vlistNgrids} returns the number of grids in the variable list
 */
 int vlistNgrids(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1121,9 +1085,7 @@ The function @func{vlistNzaxis} returns the number of zaxis in the variable list
 */
 int vlistNzaxis(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1133,27 +1095,21 @@ int vlistNzaxis(int vlistID)
 
 void vlistDefNtsteps(int vlistID, int nts)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->ntsteps != nts)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->ntsteps = nts;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->ntsteps = nts;
 }
 
 
 int vlistNtsteps(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1163,46 +1119,39 @@ int vlistNtsteps(int vlistID)
 static void
 vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
 {
-  int nvars, flag, index;
-  int varID, fvarID, mvarID, flevID, mlevID, levID;
-  int param, gridID, zaxisID, tsteptype, nlevs;
-  int dtype;
-
-  int iorank;
-
   char paramstr[32];
-  char *name, *longname, *units;
-  double level;
 
   vlist_check_ptr(__func__, vlistptr);
 
   fprintf ( fp, "#\n# vlistID %d\n#\n", vlistptr->self);
 
-  nvars = vlistptr->nvars;
+  int nvars = vlistptr->nvars;
 
-  fprintf ( fp, "nvars   %d\n", nvars);
-  fprintf ( fp, "ngrids  %d\n", vlistptr->ngrids);
-  fprintf ( fp, "nzaxis  %d\n", vlistptr->nzaxis);
-  fprintf ( fp, "taxisID %d\n", vlistptr->taxisID);
-  fprintf ( fp, "instID  %d\n", vlistptr->instID);
-  fprintf ( fp, "modelID %d\n", vlistptr->modelID);
-  fprintf ( fp, "tableID %d\n", vlistptr->tableID);
+  fprintf(fp, "nvars   %d\n"
+          "ngrids  %d\n"
+          "nzaxis  %d\n"
+          "taxisID %d\n"
+          "instID  %d\n"
+          "modelID %d\n"
+          "tableID %d\n",
+          nvars, vlistptr->ngrids, vlistptr->nzaxis, vlistptr->taxisID,
+          vlistptr->instID, vlistptr->modelID, vlistptr->tableID);
 
   if ( nvars > 0 )
     {
       fprintf(fp, " varID param    gridID zaxisID tsteptype flag "
               " name     longname iorank\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
         {
-          param    = vlistptr->vars[varID].param;
-          gridID   = vlistptr->vars[varID].gridID;
-          zaxisID  = vlistptr->vars[varID].zaxisID;
-	  tsteptype= vlistptr->vars[varID].tsteptype;
-          name     = vlistptr->vars[varID].name;
-          longname = vlistptr->vars[varID].longname;
-          units    = vlistptr->vars[varID].units;
-          flag     = vlistptr->vars[varID].flag;
-          iorank   = vlistptr->vars[varID].iorank;
+          int param = vlistptr->vars[varID].param;
+          int gridID = vlistptr->vars[varID].gridID;
+          int zaxisID = vlistptr->vars[varID].zaxisID;
+	  int tsteptype = vlistptr->vars[varID].tsteptype;
+          const char *name = vlistptr->vars[varID].name;
+          const char *longname = vlistptr->vars[varID].longname;
+          const char *units = vlistptr->vars[varID].units;
+          int flag = vlistptr->vars[varID].flag;
+          int iorank = vlistptr->vars[varID].iorank;
 
           cdiParamToString(param, paramstr, sizeof(paramstr));
           fprintf(fp, "%6d %-8s %6d %6d %6d %5d %-8s"
@@ -1211,31 +1160,31 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
                   name ? name : "", longname ? longname : "",
                   iorank);
 
-          if ( units ) fprintf ( fp, "   [%s]", units);
-          fprintf ( fp, "\n");
+          if ( units ) fprintf(fp, "   [%s]", units);
+          fputs("\n", fp);
         }
 
-      fprintf(fp, "\n");
-      fprintf(fp, " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      fputs("\n"
+            " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n", fp);
+      for ( int varID = 0; varID < nvars; varID++ )
         {
-          zaxisID  = vlistptr->vars[varID].zaxisID;
-          nlevs    = zaxisInqSize(zaxisID);
-          fvarID   = vlistptr->vars[varID].fvarID;
-          mvarID   = vlistptr->vars[varID].mvarID;
-          dtype    = vlistptr->vars[varID].datatype;
-          for ( levID = 0; levID < nlevs; levID++ )
+          int zaxisID = vlistptr->vars[varID].zaxisID;
+          int nlevs = zaxisInqSize(zaxisID);
+          int fvarID = vlistptr->vars[varID].fvarID;
+          int mvarID = vlistptr->vars[varID].mvarID;
+          int dtype    = vlistptr->vars[varID].datatype;
+          for ( int levID = 0; levID < nlevs; levID++ )
             {
               levinfo_t li;
               if (vlistptr->vars[varID].levinfo)
                 li = vlistptr->vars[varID].levinfo[levID];
               else
                 li = DEFAULT_LEVINFO(levID);
-              flevID = li.flevelID;
-              mlevID = li.mlevelID;
-              index  = li.index;
-              flag   = li.flag;
-              level  = zaxisInqLevel(zaxisID, levID);
+              int flevID = li.flevelID;
+              int mlevID = li.mlevelID;
+              int index  = li.index;
+              int flag   = li.flag;
+              double level  = zaxisInqLevel(zaxisID, levID);
 
               fprintf(fp, "%6d %6d %6d %6d %6d %6d %6d %6d %5d  %.9g\n",
                       varID, levID, fvarID, flevID, mvarID, mlevID, index,
@@ -1243,9 +1192,9 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
             }
         }
 
-      fprintf(fp, "\n");
-      fprintf(fp, " varID  size iorank\n");
-      for ( varID = 0; varID < nvars; varID++ )
+      fputs("\n"
+            " varID  size iorank\n", fp);
+      for ( int varID = 0; varID < nvars; varID++ )
         fprintf(fp, "%3d %8d %6d\n", varID,
                 zaxisInqSize(vlistptr->vars[varID].zaxisID)
                 * gridInqSize(vlistptr->vars[varID].gridID),
@@ -1256,11 +1205,8 @@ vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
 
 void vlistPrint(int vlistID)
 {
-  vlist_t *vlistptr;
-
   if ( vlistID == CDI_UNDEFID ) return;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   vlist_check_ptr(__func__, vlistptr);
   vlistPrintKernel(vlistptr, stdout);
 }
@@ -1281,19 +1227,15 @@ The function @func{vlistDefTaxis} defines the time axis of a variable list.
 */
 void vlistDefTaxis(int vlistID, int taxisID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->taxisID != taxisID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->taxisID = taxisID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->taxisID = taxisID;
 }
 
 /*
@@ -1314,9 +1256,7 @@ The function @func{vlistInqTaxis} returns the time axis of a variable list.
 */
 int vlistInqTaxis(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1324,29 +1264,23 @@ int vlistInqTaxis(int vlistID)
 }
 
 
-void  vlistDefTable(int vlistID, int tableID)
+void vlistDefTable(int vlistID, int tableID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->tableID != tableID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->tableID = tableID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->tableID = tableID;
 }
 
 
 int vlistInqTable(int vlistID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1356,38 +1290,31 @@ int vlistInqTable(int vlistID)
 
 void vlistDefInstitut(int vlistID, int instID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->instID != instID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->instID = instID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->instID = instID;
 }
 
 
 int vlistInqInstitut(int vlistID)
 {
-  int varID, instID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  instID = vlistptr->instID;
+  int instID = vlistptr->instID;
 
   if ( instID == CDI_UNDEFID )
     {
       instID  = vlistInqVarInstitut(vlistID, 0);
 
-      for ( varID = 1; varID < vlistptr->nvars; varID++ )
+      for ( int varID = 1; varID < vlistptr->nvars; varID++ )
         if ( instID != vlistInqVarInstitut(vlistID, varID) )
           {
             instID = CDI_UNDEFID;
@@ -1402,38 +1329,31 @@ int vlistInqInstitut(int vlistID)
 
 void vlistDefModel(int vlistID, int modelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->modelID != modelID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->modelID = modelID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->modelID = modelID;
 }
 
 
 int vlistInqModel(int vlistID)
 {
-  int varID, modelID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  modelID = vlistptr->modelID;
+  int modelID = vlistptr->modelID;
 
   if ( modelID == CDI_UNDEFID )
     {
       modelID = vlistInqVarModel(vlistID, 0);
 
-      for ( varID = 1; varID < vlistptr->nvars; varID++ )
+      for ( int varID = 1; varID < vlistptr->nvars; varID++ )
         if ( modelID != vlistInqVarModel(vlistID, varID) )
           {
             modelID = CDI_UNDEFID;
@@ -1449,18 +1369,15 @@ int vlistInqModel(int vlistID)
 
 int vlistGridsizeMax(int vlistID)
 {
-  int gridsize, gridsizemax = 0;
-  int gridID, index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int gridsizemax = 0;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( index = 0 ; index < vlistptr->ngrids ; index++ )
+  for ( int index = 0 ; index < vlistptr->ngrids ; index++ )
     {
-      gridID = vlistptr->gridIDs[index];
-      gridsize = gridInqSize(gridID);
+      int gridID = vlistptr->gridIDs[index];
+      int gridsize = gridInqSize(gridID);
       if ( gridsize > gridsizemax ) gridsizemax = gridsize;
     }
 
@@ -1471,9 +1388,7 @@ int vlistGridsizeMax(int vlistID)
 int vlistGrid(int vlistID, int index)
 {
   int gridID = CDI_UNDEFID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1487,9 +1402,7 @@ int vlistGrid(int vlistID, int index)
 int vlistGridIndex(int vlistID, int gridID)
 {
   int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1504,69 +1417,54 @@ int vlistGridIndex(int vlistID, int gridID)
 
 void vlistChangeGridIndex(int vlistID, int index, int gridID)
 {
-  int gridIDold;
-  int varID, nvars;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int gridIDold = vlistptr->gridIDs[index];
+  if (gridIDold != gridID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
+      vlistptr->gridIDs[index] = gridID;
 
-  gridIDold = vlistptr->gridIDs[index];
-  vlistptr->gridIDs[index] = gridID;
-
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].gridID == gridIDold )
-      vlistptr->vars[varID].gridID = gridID;
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].gridID == gridIDold )
+          vlistptr->vars[varID].gridID = gridID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistChangeGrid(int vlistID, int gridID1, int gridID2)
 {
-  int varID, nvars;
-  int index, ngrids;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  ngrids = vlistptr->ngrids;
-  for ( index = 0; index < ngrids; index++ )
+  if (gridID1 != gridID2)
     {
-      if ( vlistptr->gridIDs[index] == gridID1 )
+      int ngrids = vlistptr->ngrids;
+      for ( int index = 0; index < ngrids; index++ )
         {
-          vlistptr->gridIDs[index] = gridID2;
-          break;
+          if ( vlistptr->gridIDs[index] == gridID1 )
+            {
+              vlistptr->gridIDs[index] = gridID2;
+              break;
+            }
         }
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].gridID == gridID1 )
+          vlistptr->vars[varID].gridID = gridID2;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].gridID == gridID1 )
-      vlistptr->vars[varID].gridID = gridID2;
 }
 
 
 int vlistZaxis(int vlistID, int index)
 {
   int zaxisID = CDI_UNDEFID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
@@ -1578,13 +1476,11 @@ int vlistZaxis(int vlistID, int index)
 
 int vlistZaxisIndex(int vlistID, int zaxisID)
 {
-  int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
+  int index;
   for ( index = 0 ; index < vlistptr->nzaxis ; index++ )
     if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
 
@@ -1596,63 +1492,44 @@ int vlistZaxisIndex(int vlistID, int zaxisID)
 
 void vlistChangeZaxisIndex(int vlistID, int index, int zaxisID)
 {
-  int zaxisIDold;
-  int varID, nvars;
-  int nlevs, levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int zaxisIDold = vlistptr->zaxisIDs[index];
+  if (zaxisIDold != zaxisID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  zaxisIDold = vlistptr->zaxisIDs[index];
-  vlistptr->zaxisIDs[index] = zaxisID;
-
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
-    if ( vlistptr->vars[varID].zaxisID == zaxisIDold )
-      {
-        vlistptr->vars[varID].zaxisID = zaxisID;
+      vlistptr->zaxisIDs[index] = zaxisID;
 
-        nlevs = zaxisInqSize(zaxisID);
-        if ( vlistptr->vars[varID].levinfo
-             && nlevs != zaxisInqSize(zaxisIDold) )
+      int nlevs = zaxisInqSize(zaxisID),
+        nlevsOld = zaxisInqSize(zaxisIDold);
+      int nvars = vlistptr->nvars;
+      for ( int varID = 0; varID < nvars; varID++ )
+        if ( vlistptr->vars[varID].zaxisID == zaxisIDold )
           {
-            vlistptr->vars[varID].levinfo = (levinfo_t *) realloc(vlistptr->vars[varID].levinfo,
-                                                                     nlevs*sizeof(levinfo_t));
+            vlistptr->vars[varID].zaxisID = zaxisID;
+            if ( vlistptr->vars[varID].levinfo && nlevs != nlevsOld )
+              {
+                vlistptr->vars[varID].levinfo = (levinfo_t *)xrealloc(vlistptr->vars[varID].levinfo, (size_t)nlevs * sizeof (levinfo_t));
 
-            for ( levID = 0; levID < nlevs; levID++ )
-              vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+                for ( int levID = 0; levID < nlevs; levID++ )
+                  vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+              }
           }
-      }
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
 {
-  int varID, nvars;
-  int index, nzaxis;
-  int nlevs1 = zaxisInqSize(zaxisID1), nlevs2 = zaxisInqSize(zaxisID2), levID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  int nlevs1 = zaxisInqSize(zaxisID1), nlevs2 = zaxisInqSize(zaxisID2);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  nzaxis = vlistptr->nzaxis;
-  for ( index = 0; index < nzaxis; index++ )
+  int nzaxis = vlistptr->nzaxis;
+  for ( int index = 0; index < nzaxis; index++ )
     {
       if ( vlistptr->zaxisIDs[index] == zaxisID1 )
         {
@@ -1661,8 +1538,8 @@ void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
         }
     }
 
-  nvars = vlistptr->nvars;
-  for ( varID = 0; varID < nvars; varID++ )
+  int nvars = vlistptr->nvars;
+  for ( int varID = 0; varID < nvars; varID++ )
     if ( vlistptr->vars[varID].zaxisID == zaxisID1 )
       {
         vlistptr->vars[varID].zaxisID = zaxisID2;
@@ -1670,27 +1547,25 @@ void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2)
         if ( vlistptr->vars[varID].levinfo && nlevs2 != nlevs1 )
           {
             vlistptr->vars[varID].levinfo
-              = (levinfo_t*) realloc(vlistptr->vars[varID].levinfo,
-                                     nlevs2 * sizeof(levinfo_t));
+              = (levinfo_t *)xrealloc(vlistptr->vars[varID].levinfo,
+                                      (size_t)nlevs2 * sizeof(levinfo_t));
 
-            for ( levID = 0; levID < nlevs2; levID++ )
+            for ( int levID = 0; levID < nlevs2; levID++ )
               vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
           }
       }
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistHasTime(int vlistID)
 {
-  int varID;
   int hastime = FALSE;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlist_check_ptr(__func__, vlistptr);
 
-  for ( varID = 0; varID <  vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID <  vlistptr->nvars; varID++ )
     if ( vlistptr->vars[varID].tsteptype != TSTEP_CONSTANT )
       {
         hastime = TRUE;
@@ -1764,6 +1639,20 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
     vlistVarUnpack(targetID, buf, size, position, originNamespace, context);
 }
 
+
+void vlist_check_contents(int vlistID)
+{
+  int index, nzaxis, zaxisID;
+
+  nzaxis = vlistNzaxis(vlistID);
+
+  for ( index = 0; index < nzaxis; index++ )
+    {
+      zaxisID = vlistZaxis(vlistID, index);
+      if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
+	cdiCheckZaxis(zaxisID);
+    }
+}
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/vlist.h b/libcdi/src/vlist.h
index 899730d..6d6352f 100644
--- a/libcdi/src/vlist.h
+++ b/libcdi/src/vlist.h
@@ -86,6 +86,7 @@ typedef struct
   int         timave;
   int         timaccu;
   int         typeOfGeneratingProcess;
+  int         productDefinitionTemplate;
   int         chunktype;
   int         xyz;
   int         missvalused; /* TRUE if missval is defined */
@@ -113,10 +114,12 @@ typedef struct
   /* (Optional) list of keyword/double value pairs */
   int    opt_grib_dbl_nentries;
   char*  opt_grib_dbl_keyword[MAX_OPT_GRIB_ENTRIES];
+  int    opt_grib_dbl_update[MAX_OPT_GRIB_ENTRIES];
   double opt_grib_dbl_val[MAX_OPT_GRIB_ENTRIES];
   /* (Optional) list of keyword/integer value pairs */
   int    opt_grib_int_nentries;
   char*  opt_grib_int_keyword[MAX_OPT_GRIB_ENTRIES];
+  int    opt_grib_int_update[MAX_OPT_GRIB_ENTRIES];
   int    opt_grib_int_val[MAX_OPT_GRIB_ENTRIES];
 #endif
 }
@@ -125,6 +128,7 @@ var_t;
 
 typedef struct
 {
+  int         locked;
   int         self;
   int         nvars;        /* number of variables                */
   int         ngrids;
@@ -167,8 +171,42 @@ void    vlistDefVarValidrange(int vlistID, int varID, const double *validrange);
 /*      vlistInqVarValidrange: Get the valid range of a Variable */
 int     vlistInqVarValidrange(int vlistID, int varID, double *validrange);
 
-int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB,
-                      int attnum);
+int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
+
+void vlist_lock(int vlistID);
+void vlist_unlock(int vlistID);
+
+static inline void
+vlistAdd2GridIDs(vlist_t *vlistptr, int gridID)
+{
+  int index, ngrids = vlistptr->ngrids;
+  for ( index = 0; index < ngrids; index++ )
+    if (vlistptr->gridIDs[index] == gridID ) break;
+  if ( index == ngrids )
+    {
+      if (ngrids >= MAX_GRIDS_PS)
+        Error("Internal limit exceeded: more than %d grids.", MAX_GRIDS_PS);
+      ++(vlistptr->ngrids);
+      vlistptr->gridIDs[ngrids] = gridID;
+    }
+}
+
+static inline void
+vlistAdd2ZaxisIDs(vlist_t *vlistptr, int zaxisID)
+{
+  int index, nzaxis = vlistptr->nzaxis;
+  for ( index = 0; index < nzaxis; index++ )
+    if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
+
+  if ( index == nzaxis )
+    {
+      if ( nzaxis >= MAX_ZAXES_PS )
+	Error("Internal limit exceeded: more than %d zaxis.", MAX_ZAXES_PS);
+      vlistptr->zaxisIDs[nzaxis] = zaxisID;
+      vlistptr->nzaxis++;
+    }
+}
+
 
 #if  defined  (HAVE_LIBGRIB_API)
 extern int   cdiNAdditionalGRIBKeys;
diff --git a/libcdi/src/vlist_att.c b/libcdi/src/vlist_att.c
index 02fa786..c35ff70 100644
--- a/libcdi/src/vlist_att.c
+++ b/libcdi/src/vlist_att.c
@@ -2,9 +2,10 @@
 #  include "config.h"
 #endif
 
+#include <assert.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 #include "dmemory.h"
 
@@ -121,11 +122,11 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp)
   cdi_atts_t *attsp;
 
   vlistptr = vlist_to_pointer(vlistID);
-  
+
   attsp = get_attsp(vlistptr, varID);
   xassert(attsp != NULL);
 
-  *nattsp = attsp->nelems;
+  *nattsp = (int)attsp->nelems;
 
   return (status);
 }
@@ -139,7 +140,7 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp)
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} 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 
+    @Item  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 @func{CDI_MAX_NAME}.
     @Item  typep    Pointer to location for returned attribute type.
@@ -153,15 +154,13 @@ The function @func{vlistInqAtt} gets information about an attribute.
 int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
 {
   int status = CDI_NOERR;
-  vlist_t *vlistptr;
   cdi_att_t *attp = NULL;
-  cdi_atts_t *attsp;
 
   xassert(name != NULL);
 
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  attsp = get_attsp(vlistptr, varID);
+  cdi_atts_t *attsp = get_attsp(vlistptr, varID);
   xassert(attsp != NULL);
 
   if ( attnum >= 0 && attnum < (int)attsp->nelems )
@@ -171,13 +170,14 @@ int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int
     {
       memcpy(name, attp->name, attp->namesz+1);
       *typep  = attp->exdtype;
-      *lenp   = attp->nelems;
+      *lenp   = (int)attp->nelems;
     }
   else
     {
       name[0] =  0;
       *typep  = -1;
       *lenp   =  0;
+      status  = -1;
     }
 
   return (status);
@@ -214,6 +214,10 @@ int vlistDelAtt(int vlistID, int varID, const char *name)
 {
   int status = CDI_NOERR;
 
+  UNUSED(vlistID);
+  UNUSED(varID);
+  UNUSED(name);
+
   fprintf(stderr, "vlistDelAtt not implemented!\n");
 
   return (status);
@@ -279,11 +283,13 @@ int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t
       else
 	{
 	  Warning("Attribute %s has wrong data type!", name);
+          status = -2;
 	}
     }
   else
     {
-      Warning("Internal problem, attribute %s not found!", name);
+      //Warning("Internal problem, attribute %s not found!", name);
+      status = -1;
     }
 
   return (status);
@@ -333,7 +339,7 @@ The function @func{vlistDefAttInt} defines an integer attribute.
 */
 int vlistDefAttInt(int vlistID, 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, len*sizeof(int), (const void *) ip);
+  return vlist_def_att(DATATYPE_INT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (int), ip);
 }
 
 /*
@@ -357,7 +363,7 @@ The function @func{vlistDefAttFlt} defines a floating point attribute.
 */
 int vlistDefAttFlt(int vlistID, 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, len*sizeof(double), (const void *) dp);
+  return vlist_def_att(DATATYPE_FLT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (double), dp);
 }
 
 /*
@@ -380,7 +386,7 @@ The function @func{vlistDefAttTxt} defines a text attribute.
 */
 int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)
 {
-  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t) len, len*sizeof(char), (const void *) tp);
+  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (char), tp);
 }
 
 /*
@@ -402,7 +408,7 @@ The function @func{vlistInqAttInt} gets the values(s) of an integer attribute.
 */
 int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
 {
-  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, mlen*sizeof(int), (void *) ip);
+  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, (size_t)mlen * sizeof (int), ip);
 }
 
 /*
@@ -424,7 +430,7 @@ The function @func{vlistInqAttFlt} gets the values(s) of a floating point attrib
 */
 int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
 {
-  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, mlen*sizeof(double), (void *) dp);
+  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, (size_t)mlen * sizeof (double), dp);
 }
 
 /*
@@ -446,7 +452,7 @@ The function @func{vlistInqAttTxt} gets the values(s) of a text attribute.
 */
 int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
 {
-  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, mlen*sizeof(char), (void *) tp);
+  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, (size_t)mlen * sizeof (char), tp);
 }
 
 enum {
@@ -509,7 +515,7 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
   attp = &(attsp->value[attnum]);
   int txsize = serializeGetSize(vlist_att_nints, DATATYPE_INT, context)
-    + serializeGetSize(attp->namesz, DATATYPE_TXT, context);
+    + serializeGetSize((int)attp->namesz, DATATYPE_TXT, context);
   txsize += serializeGetSize((int)attp->nelems, vlistAttTypeLookup(attp), context);
   return txsize;
 }
@@ -517,12 +523,11 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
 int
 vlistAttsGetSize(vlist_t *p, int varID, void *context)
 {
-  int numAtts, i;
   cdi_atts_t *attsp = get_attsp(p, varID);
   int txsize = serializeGetSize(1, DATATYPE_INT, context);
-  numAtts = attsp->nelems;
-  for (i = 0; i < numAtts; ++i)
-    txsize += vlistAttGetSize(p, varID, i, context);
+  size_t numAtts = attsp->nelems;
+  for (size_t i = 0; i < numAtts; ++i)
+    txsize += vlistAttGetSize(p, varID, (int)i, context);
   return txsize;
 }
 
@@ -537,12 +542,12 @@ vlistAttPack(vlist_t *vlistptr, int varID, int attnum,
   xassert(attsp = get_attsp(vlistptr, varID));
   xassert(attnum >= 0 && attnum < (int)attsp->nelems);
   attp = &(attsp->value[attnum]);
-  tempbuf[0] = attp->namesz;
+  tempbuf[0] = (int)attp->namesz;
   tempbuf[1] = attp->exdtype;
   tempbuf[2] = attp->indtype;
-  tempbuf[3] = attp->nelems;
+  tempbuf[3] = (int)attp->nelems;
   serializePack(tempbuf, vlist_att_nints, DATATYPE_INT, buf, size, position, context);
-  serializePack(attp->name, attp->namesz, DATATYPE_TXT, buf, size, position, context);
+  serializePack(attp->name, (int)attp->namesz, DATATYPE_TXT, buf, size, position, context);
   serializePack(attp->xvalue, (int)attp->nelems, vlistAttTypeLookup(attp),
                 buf, size, position, context);
 }
@@ -551,28 +556,28 @@ void
 vlistAttsPack(vlist_t *p, int varID,
               void * buf, int size, int *position, void *context)
 {
-  int numAtts, i;
   cdi_atts_t *attsp = get_attsp(p, varID);
-  numAtts = attsp->nelems;
-  serializePack(&numAtts, 1, DATATYPE_INT, buf, size, position, context);
-  for (i = 0; i < numAtts; ++i)
-    vlistAttPack(p, varID, i, buf, size, position, context);
+  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);
 }
 
 static void
 vlistAttUnpack(int vlistID, int varID,
                void * buf, int size, int *position, void *context)
 {
-  char *attName;
   int tempbuf[vlist_att_nints];
-  int attVDt;
-  int elemSize;
 
   serializeUnpack(buf, size, position,
                   tempbuf, vlist_att_nints, DATATYPE_INT, context);
-  attName = (char*) xmalloc(tempbuf[0] + 1);
+  char *attName = (char *)xmalloc((size_t)tempbuf[0] + 1);
   serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context);
   attName[tempbuf[0]] = '\0';
+  int attVDt;
+  size_t elemSize;
   switch (tempbuf[2])
   {
   case DATATYPE_FLT:
@@ -591,10 +596,10 @@ vlistAttUnpack(int vlistID, int varID,
     xabort("Unknown datatype encountered in attribute %s: %d\n",
            attName, tempbuf[2]);
   }
-  void *attData = xmalloc(elemSize * tempbuf[3]);
+  void *attData = (void *)xmalloc(elemSize * (size_t)tempbuf[3]);
   serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
   vlist_def_att(tempbuf[2], tempbuf[1], vlistID, varID, attName,
-                tempbuf[3], tempbuf[3] * elemSize, attData);
+                (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
   free(attName);
   free(attData);
 }
diff --git a/libcdi/src/vlist_var.c b/libcdi/src/vlist_var.c
index f602cf1..60cf0b5 100644
--- a/libcdi/src/vlist_var.c
+++ b/libcdi/src/vlist_var.c
@@ -24,9 +24,7 @@ resOps vlist_ops;
 static
 void vlistvarInitEntry(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistptr->vars[varID].fvarID        = varID;
   vlistptr->vars[varID].mvarID        = varID;
@@ -36,9 +34,10 @@ void vlistvarInitEntry(int vlistID, int varID)
   vlistptr->vars[varID].tsteptype     = TSTEP_INSTANT;
   vlistptr->vars[varID].timave        = 0;
   vlistptr->vars[varID].timaccu       = 0;
-  vlistptr->vars[varID].typeOfGeneratingProcess = 0;
+  vlistptr->vars[varID].typeOfGeneratingProcess   = 0;
+  vlistptr->vars[varID].productDefinitionTemplate = -1;
   vlistptr->vars[varID].chunktype     = cdiChunkType;
-  vlistptr->vars[varID].xyz           = 0;
+  vlistptr->vars[varID].xyz           = 321;
   vlistptr->vars[varID].gridID        = CDI_UNDEFID;
   vlistptr->vars[varID].zaxisID       = CDI_UNDEFID;
   vlistptr->vars[varID].instID        = CDI_UNDEFID;
@@ -73,8 +72,10 @@ void vlistvarInitEntry(int vlistID, int varID)
   vlistptr->vars[varID].opt_grib_int_nentries = 0;
   int i;
   for (i=0; i<MAX_OPT_GRIB_ENTRIES; i++) {
-    vlistptr->vars[varID].opt_grib_dbl_val[i] = 0.0;
     vlistptr->vars[varID].opt_grib_int_val[i] =   0;
+    vlistptr->vars[varID].opt_grib_dbl_val[i] = 0.0;
+    vlistptr->vars[varID].opt_grib_int_update[i] = FALSE;
+    vlistptr->vars[varID].opt_grib_dbl_update[i] = FALSE;
     vlistptr->vars[varID].opt_grib_int_keyword[i] = NULL;
     vlistptr->vars[varID].opt_grib_dbl_keyword[i] = NULL;
   } // for
@@ -87,9 +88,7 @@ int vlistvarNewEntry(int vlistID)
   int varID = 0;
   int vlistvarSize;
   var_t *vlistvar;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistvarSize = vlistptr->varsAllocated;
   vlistvar     = vlistptr->vars;
@@ -99,17 +98,9 @@ int vlistvarNewEntry(int vlistID)
   */
   if ( ! vlistvarSize )
     {
-      int i;
-
       vlistvarSize = 2;
-      vlistvar = (var_t *) malloc(vlistvarSize*sizeof(var_t));
-      if ( vlistvar == NULL )
-	{
-          Message("vlistvarSize = %d", vlistvarSize);
-	  SysError("Allocation of var_t failed");
-	}
-
-      for ( i = 0; i < vlistvarSize; i++ )
+      vlistvar = (var_t *)xmalloc((size_t)vlistvarSize * sizeof (var_t));
+      for (int i = 0; i < vlistvarSize; i++ )
 	vlistvar[i].isUsed = FALSE;
     }
   else
@@ -125,12 +116,8 @@ int vlistvarNewEntry(int vlistID)
       int i;
 
       vlistvarSize = 2*vlistvarSize;
-      vlistvar = (var_t *) realloc(vlistvar, vlistvarSize*sizeof(var_t));
-      if ( vlistvar == NULL )
-	{
-          Message("vlistvarSize = %d", vlistvarSize);
-	  SysError("Reallocation of var_t failed");
-	}
+      vlistvar = (var_t *)xrealloc(vlistvar,
+                                   (size_t)vlistvarSize * sizeof(var_t));
       varID = vlistvarSize/2;
 
       for ( i = varID; i < vlistvarSize; i++ )
@@ -150,9 +137,7 @@ int vlistvarNewEntry(int vlistID)
 static
 void vlistCheckVarID(const char *caller, int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr == NULL )
     Errorc("vlist undefined!");
@@ -203,21 +188,11 @@ vlistDestroy(vlistID);
 */
 int vlistDefVar(int vlistID, int gridID, int zaxisID, int tsteptype)
 {
-  int varID;
-  int index;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return CDI_UNDEFID;
-    }
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   if ( CDI_Debug )
     Message("gridID = %d  zaxisID = %d  tsteptype = %d", gridID, zaxisID, tsteptype);
 
-  varID = vlistvarNewEntry(vlistID);
+  int varID = vlistvarNewEntry(vlistID);
 
   vlistptr->nvars++;
 
@@ -231,32 +206,11 @@ int vlistDefVar(int vlistID, int gridID, int zaxisID, int tsteptype)
       vlistptr->vars[varID].tsteptype = TSTEP_INSTANT;
     }
 
-  for ( index = 0; index < vlistptr->ngrids; index++ )
-    if ( gridID == vlistptr->gridIDs[index] ) break;
-
-  if ( index == vlistptr->ngrids )
-    {
-      if ( vlistptr->ngrids + 1 >= MAX_GRIDS_PS )
-	Error("Maximum of %d grids reached", MAX_GRIDS_PS);
-
-      vlistptr->gridIDs[vlistptr->ngrids] = gridID;
-      vlistptr->ngrids++;
-    }
-
-  for ( index = 0; index < vlistptr->nzaxis; index++ )
-    if ( zaxisID == vlistptr->zaxisIDs[index] ) break;
-
-  if ( index == vlistptr->nzaxis )
-    {
-      if ( vlistptr->nzaxis + 1 >= MAX_ZAXES_PS )
-	Error("Maximum of %d zaxis reached", MAX_ZAXES_PS);
-
-      vlistptr->zaxisIDs[vlistptr->nzaxis] = zaxisID;
-      vlistptr->nzaxis++;
-    }
+  vlistAdd2GridIDs(vlistptr, gridID);
+  vlistAdd2ZaxisIDs(vlistptr, zaxisID);
 
   vlistptr->vars[varID].param = cdiEncodeParam(-(varID + 1), 255, 255);
-
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
   return (varID);
 }
 
@@ -266,12 +220,13 @@ cdiVlistCreateVarLevInfo(vlist_t *vlistptr, int varID)
   xassert(varID >= 0 && varID < vlistptr->nvars
           && vlistptr->vars[varID].levinfo == NULL);
   int zaxisID = vlistptr->vars[varID].zaxisID;
-  int nlevs = zaxisInqSize(zaxisID);
+  size_t nlevs = (size_t)zaxisInqSize(zaxisID);
 
-  vlistptr->vars[varID].levinfo = (levinfo_t*) malloc(nlevs * sizeof(levinfo_t));
+  vlistptr->vars[varID].levinfo
+    = (levinfo_t*)xmalloc((size_t)nlevs * sizeof(levinfo_t));
 
-  for (int levID = 0; levID < nlevs; levID++ )
-      vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO(levID);
+  for (size_t levID = 0; levID < nlevs; levID++ )
+    vlistptr->vars[varID].levinfo[levID] = DEFAULT_LEVINFO((int)levID);
 }
 
 /*
@@ -291,19 +246,15 @@ The function @func{vlistDefVarParam} defines the parameter number of a variable.
 */
 void vlistDefVarParam(int vlistID, int varID, int param)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].param != param)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].param = param;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].param = param;
 }
 
 /*
@@ -323,32 +274,25 @@ The function @func{vlistDefVarCode} defines the code number of a variable.
 */
 void vlistDefVarCode(int vlistID, int varID, int code)
 {
-  vlist_t *vlistptr;
-  int param, pnum, pcat, pdis;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  int param = vlistptr->vars[varID].param;
+  int pnum, pcat, pdis;
+  cdiDecodeParam(param, &pnum, &pcat, &pdis);
+  int newParam = cdiEncodeParam(code, pcat, pdis);
+  if (vlistptr->vars[varID].param != newParam)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].param = newParam;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  param = vlistptr->vars[varID].param;
-
-  cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
-  vlistptr->vars[varID].param = cdiEncodeParam(code, pcat, pdis);
 }
 
 
 void vlistInqVar(int vlistID, int varID, int *gridID, int *zaxisID, int *tsteptype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -378,9 +322,7 @@ The function @func{vlistInqVarGrid} returns the grid ID of a variable.
 */
 int vlistInqVarGrid(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -406,9 +348,7 @@ The function @func{vlistInqVarZaxis} returns the zaxis ID of a variable.
 */
 int vlistInqVarZaxis(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -434,16 +374,11 @@ The function @func{vlistInqVarParam} returns the parameter number of a variable.
 */
 int vlistInqVarParam(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int param;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  param = vlistptr->vars[varID].param;
-
-  return (param);
+  return (vlistptr->vars[varID].param);
 }
 
 /*
@@ -465,18 +400,14 @@ The function @func{vlistInqVarCode} returns the code number of a variable.
 */
 int vlistInqVarCode(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int param, code = -varID-1;
-  int pdis, pcat, pnum;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  param = vlistptr->vars[varID].param;
+  int param = vlistptr->vars[varID].param;
+  int pdis, pcat, pnum;
   cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
-  if ( pdis == 255 ) code = pnum;
+  int code = pdis == 255 ? pnum : -varID-1;
 
   if ( code < 0 && vlistptr->vars[varID].tableID != -1 && vlistptr->vars[varID].name != NULL )
     {
@@ -489,9 +420,7 @@ int vlistInqVarCode(int vlistID, int varID)
 
 const char *vlistInqVarNamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -501,9 +430,7 @@ const char *vlistInqVarNamePtr(int vlistID, int varID)
 
 const char *vlistInqVarLongnamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -513,9 +440,7 @@ const char *vlistInqVarLongnamePtr(int vlistID, int varID)
 
 const char *vlistInqVarStdnamePtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -525,9 +450,7 @@ const char *vlistInqVarStdnamePtr(int vlistID, int varID)
 
 const char *vlistInqVarUnitsPtr(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -542,7 +465,7 @@ const char *vlistInqVarUnitsPtr(int vlistID, int varID)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  name     Returned variable name. The caller must allocate space for the 
+    @Item  name     Returned variable 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 @func{CDI_MAX_NAME}.
 
@@ -557,23 +480,19 @@ otherwise the result is an empty string.
 */
 void vlistInqVarName(int vlistID, int varID, char *name)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   if ( vlistptr->vars[varID].name == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+	  int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParName(tableID, code, name) != 0 )
 	    sprintf(name, "var%d", code);
 	}
@@ -581,7 +500,7 @@ void vlistInqVarName(int vlistID, int varID, char *name)
 	{
 	  sprintf(name, "param%d.%d.%d", pnum, pcat, pdis);
 	}
-    }  
+    }
   else
     strcpy(name, vlistptr->vars[varID].name);
 
@@ -596,7 +515,7 @@ void vlistInqVarName(int vlistID, int varID, char *name)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  longname Long name of the variable. The caller must allocate space for the 
+    @Item  longname Long name of the variable. The caller must allocate space for the
                     returned string. The maximum possible length, in characters, of
                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
 
@@ -611,12 +530,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarLongname(int vlistID, int varID, char *longname)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -624,16 +538,17 @@ void vlistInqVarLongname(int vlistID, int varID, char *longname)
 
   if ( vlistptr->vars[varID].longname == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+          int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParLongname(tableID, code, longname) != 0 )
 	    longname[0] = '\0';
 	}
-    }  
+    }
   else
     strcpy(longname, vlistptr->vars[varID].longname);
 
@@ -648,7 +563,7 @@ void vlistInqVarLongname(int vlistID, int varID, char *longname)
 @Parameter
     @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
     @Item  varID    Variable identifier.
-    @Item  stdname  Standard name of the variable. The caller must allocate space for the 
+    @Item  stdname  Standard name of the variable. The caller must allocate space for the
                     returned string. The maximum possible length, in characters, of
                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
 
@@ -663,9 +578,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarStdname(int vlistID, int varID, char *stdname)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -702,12 +615,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarUnits(int vlistID, int varID, char *units)
 {
-  int tableID;
-  int param;
-  int pdis, pcat, pnum;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -715,12 +623,13 @@ void vlistInqVarUnits(int vlistID, int varID, char *units)
 
   if ( vlistptr->vars[varID].units == NULL )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pdis == 255 )
 	{
 	  int code = pnum;
-	  tableID = vlistptr->vars[varID].tableID;
+	  int tableID = vlistptr->vars[varID].tableID;
 	  if ( tableInqParUnits(tableID, code, units) != 0 )
 	    units[0] = '\0';
 	}
@@ -734,15 +643,12 @@ void vlistInqVarUnits(int vlistID, int varID, char *units)
 /* used in MPIOM ! */
 int vlistInqVarID(int vlistID, int code)
 {
-  int varID;
-  vlist_t *vlistptr;
-  int param, pdis, pcat, pnum;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  for ( varID = 0; varID < vlistptr->nvars; varID++ )
+  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
     {
-      param = vlistptr->vars[varID].param;
+      int param = vlistptr->vars[varID].param;
+      int pdis, pcat, pnum;
       cdiDecodeParam(param, &pnum, &pcat, &pdis);
       if ( pnum == code ) return (varID);
     }
@@ -753,20 +659,17 @@ int vlistInqVarID(int vlistID, int code)
 
 int vlistInqVarSize(int vlistID, int varID)
 {
-  int size;
-  int zaxisID, gridID;
-  int nlevs, gridsize;
-  int tsteptype;
-
   vlistCheckVarID(__func__, vlistID, varID);
 
+  int zaxisID, gridID;
+  int tsteptype;
   vlistInqVar(vlistID, varID, &gridID, &zaxisID, &tsteptype);
 
-  nlevs = zaxisInqSize(zaxisID);
+  int nlevs = zaxisInqSize(zaxisID);
 
-  gridsize = gridInqSize(gridID);
+  int gridsize = gridInqSize(gridID);
 
-  size = gridsize*nlevs;
+  int size = gridsize*nlevs;
 
   return (size);
 }
@@ -793,9 +696,7 @@ The valid CDI data types are @func{DATATYPE_PACK8}, @func{DATATYPE_PACK16}, @fun
 */
 int vlistInqVarDatatype(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -805,13 +706,11 @@ int vlistInqVarDatatype(int vlistID, int varID)
 
 int vlistInqVarNumber(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-  int number = CDI_REAL;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
+  int number = CDI_REAL;
   if ( vlistptr->vars[varID].datatype == DATATYPE_CPX32 ||
        vlistptr->vars[varID].datatype == DATATYPE_CPX64 )
     number = CDI_COMP;
@@ -839,123 +738,88 @@ The function @func{vlistDefVarDatatype} defines the data type of a variable.
 */
 void vlistDefVarDatatype(int vlistID, int varID, int datatype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
+  if (vlistptr->vars[varID].datatype != datatype)
+    {
+      vlistptr->vars[varID].datatype = datatype;
+
+      if ( vlistptr->vars[varID].missvalused == FALSE )
+        switch (datatype)
+          {
+          case DATATYPE_INT8:   vlistptr->vars[varID].missval = -SCHAR_MAX; break;
+          case DATATYPE_UINT8:  vlistptr->vars[varID].missval =  UCHAR_MAX; break;
+          case DATATYPE_INT16:  vlistptr->vars[varID].missval = -SHRT_MAX;  break;
+          case DATATYPE_UINT16: vlistptr->vars[varID].missval =  USHRT_MAX; break;
+          case DATATYPE_INT32:  vlistptr->vars[varID].missval = -INT_MAX;   break;
+          case DATATYPE_UINT32: vlistptr->vars[varID].missval =  UINT_MAX;  break;
+          }
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].datatype = datatype;
-
-  if ( vlistptr->vars[varID].missvalused == FALSE )
-    switch (datatype)
-      {
-      case DATATYPE_INT8:   vlistptr->vars[varID].missval = -SCHAR_MAX; break;
-      case DATATYPE_UINT8:  vlistptr->vars[varID].missval =  UCHAR_MAX; break;
-      case DATATYPE_INT16:  vlistptr->vars[varID].missval = -SHRT_MAX;  break;
-      case DATATYPE_UINT16: vlistptr->vars[varID].missval =  USHRT_MAX; break;
-      case DATATYPE_INT32:  vlistptr->vars[varID].missval = -INT_MAX;   break;
-      case DATATYPE_UINT32: vlistptr->vars[varID].missval =  UINT_MAX;  break;
-      }
 }
 
 
 void vlistDefVarInstitut(int vlistID, int varID, int instID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].instID != instID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].instID = instID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].instID = instID;
 }
 
 
 int vlistInqVarInstitut(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].instID);
 }
 
 
 void vlistDefVarModel(int vlistID, int varID, int modelID)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].modelID != modelID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
+      vlistptr->vars[varID].modelID = modelID;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].modelID = modelID;
 }
 
 
 int vlistInqVarModel(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].modelID);
 }
 
 
 void vlistDefVarTable(int vlistID, int varID, int tableID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].tableID != tableID)
     {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].tableID = tableID;
-
-  {
-    int param, pnum, pcat, pdis;
-    int tablenum;
-    tablenum = tableInqNum(tableID);
-
-    param = vlistptr->vars[varID].param;
+      vlistptr->vars[varID].tableID = tableID;
+      int tablenum = tableInqNum(tableID);
 
-    cdiDecodeParam(param, &pnum, &pcat, &pdis);
+      int param = vlistptr->vars[varID].param;
 
-    vlistptr->vars[varID].param = cdiEncodeParam(pnum, tablenum, pdis);
-  }
+      int pnum, pcat, pdis;
+      cdiDecodeParam(param, &pnum, &pcat, &pdis);
+      vlistptr->vars[varID].param = cdiEncodeParam(pnum, tablenum, pdis);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarTable(int vlistID, int varID)
 {
-  int tableID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  tableID = vlistptr->vars[varID].tableID;
-
-  return (tableID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  return (vlistptr->vars[varID].tableID);
 }
 
 /*
@@ -975,15 +839,7 @@ The function @func{vlistDefVarName} defines the name of a variable.
 */
 void vlistDefVarName(int vlistID, int varID, const char *name)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -996,6 +852,7 @@ void vlistDefVarName(int vlistID, int varID, const char *name)
 	}
 
       vlistptr->vars[varID].name = strdupx(name);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -1016,15 +873,7 @@ The function @func{vlistDefVarLongname} defines the long name of a variable.
 */
 void vlistDefVarLongname(int vlistID, int varID, const char *longname)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1037,6 +886,7 @@ void vlistDefVarLongname(int vlistID, int varID, const char *longname)
 	}
 
       vlistptr->vars[varID].longname = strdupx(longname);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -1057,15 +907,7 @@ The function @func{vlistDefVarStdname} defines the standard name of a variable.
 */
 void vlistDefVarStdname(int vlistID, int varID, const char *stdname)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1078,6 +920,7 @@ void vlistDefVarStdname(int vlistID, int varID, const char *stdname)
 	}
 
       vlistptr->vars[varID].stdname = strdupx(stdname);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -1098,15 +941,7 @@ The function @func{vlistDefVarUnits} defines the units of a variable.
 */
 void vlistDefVarUnits(int vlistID, int varID, const char *units)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1119,6 +954,7 @@ void vlistDefVarUnits(int vlistID, int varID, const char *units)
 	}
 
       vlistptr->vars[varID].units = strdupx(units);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -1141,9 +977,7 @@ The function @func{vlistInqVarMissval} returns the missing value of a variable.
 */
 double vlistInqVarMissval(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1167,9 +1001,7 @@ The function @func{vlistDefVarMissval} defines the missing value of a variable.
 */
 void vlistDefVarMissval(int vlistID, int varID, double missval)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1194,15 +1026,7 @@ The function @func{vlistDefVarExtra} defines the extra information of a variable
 */
 void vlistDefVarExtra(int vlistID, int varID, const char *extra)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1215,6 +1039,7 @@ void vlistDefVarExtra(int vlistID, int varID, const char *extra)
 	}
 
       vlistptr->vars[varID].extra = strdupx(extra);
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -1241,9 +1066,7 @@ otherwise the result is an empty string.
 */
 void vlistInqVarExtra(int vlistID, int varID, char *extra)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1258,9 +1081,7 @@ void vlistInqVarExtra(int vlistID, int varID, char *extra)
 
 int vlistInqVarValidrange(int vlistID, int varID, double *validrange)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1276,29 +1097,20 @@ int vlistInqVarValidrange(int vlistID, int varID, double *validrange)
 
 void vlistDefVarValidrange(int vlistID, int varID, const double *validrange)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   vlistptr->vars[varID].validrange[0] = validrange[0];
   vlistptr->vars[varID].validrange[1] = validrange[1];
   vlistptr->vars[varID].lvalidrange = TRUE;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 double vlistInqVarScalefactor(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return 1.0;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1308,232 +1120,195 @@ double vlistInqVarScalefactor(int vlistID, int varID)
 
 double vlistInqVarAddoffset(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   return (vlistptr->vars[varID].addoffset);
 }
 
+
 void vlistDefVarScalefactor(int vlistID, int varID, double scalefactor)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed." );
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].scalefactor = scalefactor;
+  if ( IS_NOT_EQUAL(vlistptr->vars[varID].scalefactor, scalefactor) )
+    {
+      vlistptr->vars[varID].scalefactor = scalefactor;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistDefVarAddoffset(int vlistID, int varID, double addoffset)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].addoffset = addoffset;
+  if ( IS_NOT_EQUAL(vlistptr->vars[varID].addoffset, addoffset))
+    {
+      vlistptr->vars[varID].addoffset = addoffset;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].tsteptype != tsteptype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].tsteptype = tsteptype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].tsteptype = tsteptype;
 }
 
 
 int vlistInqVarTsteptype(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].tsteptype);
 }
 
 
 void vlistDefVarTimave(int vlistID, int varID, int timave)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].timave != timave)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].timave = timave;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].timave = timave;
 }
 
 
 int vlistInqVarTimave(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].timave);
 }
 
 
 void vlistDefVarTimaccu(int vlistID, int varID, int timaccu)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].timaccu != timaccu)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].timaccu = timaccu;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].timaccu = timaccu;
 }
 
 
 int vlistInqVarTimaccu(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].timaccu);
 }
 
 
 void vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGeneratingProcess)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  if (vlistptr->vars[varID].typeOfGeneratingProcess != typeOfGeneratingProcess)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].typeOfGeneratingProcess = typeOfGeneratingProcess;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr = vlist_to_pointer(vlistID);
-
-  vlistptr->vars[varID].typeOfGeneratingProcess = typeOfGeneratingProcess;
 }
 
 
 int vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  return (vlistptr->vars[varID].typeOfGeneratingProcess);
+}
 
-  vlistptr = vlist_to_pointer(vlistID);
 
-  return (vlistptr->vars[varID].typeOfGeneratingProcess);
+void vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDefinitionTemplate)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  if (vlistptr->vars[varID].productDefinitionTemplate != productDefinitionTemplate)
+    {
+      vlistptr->vars[varID].productDefinitionTemplate = productDefinitionTemplate;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
-void vlistDestroyVarName(int vlistID, int varID)
+int vlistInqVarProductDefinitionTemplate(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  vlistptr = vlist_to_pointer(vlistID);
+  return (vlistptr->vars[varID].productDefinitionTemplate);
+}
 
+
+void vlistDestroyVarName(int vlistID, int varID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   if ( vlistptr->vars[varID].name )
     {
       free(vlistptr->vars[varID].name);
       vlistptr->vars[varID].name = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarLongname(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].longname )
     {
       free(vlistptr->vars[varID].longname);
       vlistptr->vars[varID].longname = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarStdname(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].stdname )
     {
       free(vlistptr->vars[varID].stdname);
       vlistptr->vars[varID].stdname = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 void vlistDestroyVarUnits(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if ( vlistptr->vars[varID].units )
     {
       free(vlistptr->vars[varID].units);
       vlistptr->vars[varID].units = NULL;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
 }
 
 
 int vlistInqVarMissvalUsed(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].missvalused);
 }
 
 
 void vlistDefFlag(int vlistID, int varID, int levID, int flag)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   levinfo_t li = DEFAULT_LEVINFO(levID);
   if (vlistptr->vars[varID].levinfo)
@@ -1556,14 +1331,14 @@ void vlistDefFlag(int vlistID, int varID, int levID, int flag)
           break;
         }
     }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqFlag(int vlistID, int varID, int levID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return (vlistptr->vars[varID].levinfo[levID].flag);
@@ -1578,9 +1353,7 @@ int vlistInqFlag(int vlistID, int varID, int levID)
 int vlistFindVar(int vlistID, int fvarID)
 {
   int varID;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   for ( varID = 0; varID < vlistptr->nvars; varID++ )
     {
@@ -1599,13 +1372,10 @@ int vlistFindVar(int vlistID, int fvarID)
 
 int vlistFindLevel(int vlistID, int fvarID, int flevelID)
 {
-  int varID;
   int levelID = -1;
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  varID = vlistFindVar(vlistID, fvarID);
+  int varID = vlistFindVar(vlistID, fvarID);
 
   if ( varID != -1 )
     {
@@ -1629,19 +1399,14 @@ int vlistFindLevel(int vlistID, int fvarID, int flevelID)
 
 int vlistMergedVar(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
-
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
   return (vlistptr->vars[varID].mvarID);
 }
 
 
 int vlistMergedLevel(int vlistID, int varID, int levelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return vlistptr->vars[varID].levinfo[levelID].mlevelID;
@@ -1655,15 +1420,7 @@ int vlistMergedLevel(int vlistID, int varID, int levelID)
 
 void vlistDefIndex(int vlistID, int varID, int levelID, int index)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   levinfo_t li = DEFAULT_LEVINFO(levelID);
   if (vlistptr->vars[varID].levinfo)
@@ -1673,14 +1430,13 @@ void vlistDefIndex(int vlistID, int varID, int levelID, int index)
   else
     return;
   vlistptr->vars[varID].levinfo[levelID].index = index;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqIndex(int vlistID, int varID, int levelID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   if (vlistptr->vars[varID].levinfo)
     return (vlistptr->vars[varID].levinfo[levelID].index);
@@ -1694,71 +1450,46 @@ int vlistInqIndex(int vlistID, int varID, int levelID)
 
 void vlistChangeVarZaxis(int vlistID, int varID, int zaxisID)
 {
-  int nlevs1, nlevs2;
-  int nvars, index;
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  nlevs1 = zaxisInqSize(vlistptr->vars[varID].zaxisID);
-  nlevs2 = zaxisInqSize(zaxisID);
+  int nlevs1 = zaxisInqSize(vlistptr->vars[varID].zaxisID);
+  int nlevs2 = zaxisInqSize(zaxisID);
 
   if ( nlevs1 != nlevs2 ) Error("Number of levels must not change!");
 
-  nvars = vlistptr->nvars;
-  for ( index = 0; index < nvars; index++ )
-    if ( index != varID )
-      if ( vlistptr->vars[index].zaxisID == vlistptr->vars[varID].zaxisID ) break;
+  int nvars = vlistptr->nvars;
+  int found = 0;
+  int oldZaxisID = vlistptr->vars[varID].zaxisID;
+  for ( int i = 0; i < varID; ++i)
+    found |= (vlistptr->vars[i].zaxisID == oldZaxisID);
+  for ( int i = varID + 1; i < nvars; ++i)
+    found |= (vlistptr->vars[i].zaxisID == oldZaxisID);
 
-  if ( index == nvars )
+  if (found)
     {
-      for ( index = 0; index < vlistptr->nzaxis; index++ )
-	if ( vlistptr->zaxisIDs[index] == vlistptr->vars[varID].zaxisID )
-	  vlistptr->zaxisIDs[index] = zaxisID;
+      int nzaxis = vlistptr->nzaxis;
+      for (int i = 0; i < nzaxis; ++i)
+	if (vlistptr->zaxisIDs[i] == oldZaxisID )
+	  vlistptr->zaxisIDs[i] = zaxisID;
     }
   else
-    {
-      for ( index = 0; index < vlistptr->nzaxis; index++ )
-	if ( vlistptr->zaxisIDs[index] == zaxisID ) break;
+    vlistAdd2ZaxisIDs(vlistptr, zaxisID);
 
-      if ( index == vlistptr->nzaxis )
-	{
-	  if ( vlistptr->nzaxis + 1 >= MAX_ZAXES_PS )
-	    Error("Maximum of %d zaxis reached", MAX_ZAXES_PS);
-
-	  vlistptr->zaxisIDs[vlistptr->nzaxis] = zaxisID;
-	  vlistptr->nzaxis++;
-	}
-    }
-  
   vlistptr->vars[varID].zaxisID = zaxisID;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 void vlistChangeVarGrid(int vlistID, int varID, int gridID)
 {
-  int nvars, index;
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  nvars = vlistptr->nvars;
+  int nvars = vlistptr->nvars;
+  int index;
   for ( index = 0; index < nvars; index++ )
     if ( index != varID )
       if ( vlistptr->vars[index].gridID == vlistptr->vars[varID].gridID ) break;
@@ -1770,47 +1501,30 @@ void vlistChangeVarGrid(int vlistID, int varID, int gridID)
 	  vlistptr->gridIDs[index] = gridID;
     }
   else
-    {
-      for ( index = 0; index < vlistptr->ngrids; index++ )
-	if ( vlistptr->gridIDs[index] == gridID ) break;
+    vlistAdd2GridIDs(vlistptr, gridID);
 
-      if ( index == vlistptr->ngrids )
-	{
-	  if ( vlistptr->ngrids + 1 >= MAX_GRIDS_PS )
-	    Error("Maximum of %d grids reached", MAX_GRIDS_PS);
-
-	  vlistptr->gridIDs[vlistptr->ngrids] = gridID;
-	  vlistptr->ngrids++;
-	}
-    }
-  
   vlistptr->vars[varID].gridID = gridID;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 void vlistDefVarCompType(int vlistID, int varID, int comptype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].comptype != comptype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].comptype = comptype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].comptype = comptype;
 }
 
 
 int vlistInqVarCompType(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1820,27 +1534,21 @@ int vlistInqVarCompType(int vlistID, int varID)
 
 void vlistDefVarCompLevel(int vlistID, int varID, int complevel)
 {
-  vlist_t *vlistptr;
-
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].complevel = complevel;
+  if (vlistptr->vars[varID].complevel != complevel)
+    {
+      vlistptr->vars[varID].complevel = complevel;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarCompLevel(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1850,33 +1558,46 @@ int vlistInqVarCompLevel(int vlistID, int varID)
 
 void  vlistDefVarChunkType(int vlistID, int varID, int chunktype)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  vlistptr->vars[varID].chunktype = chunktype;
+  if (vlistptr->vars[varID].chunktype != chunktype)
+    {
+      vlistptr->vars[varID].chunktype = chunktype;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
+    }
 }
 
 
 int vlistInqVarChunkType(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   return (vlistptr->vars[varID].chunktype);
 }
 
+static
+int vlistEncodeXyz(int (*dimorder)[3])
+{
+  return (*dimorder)[0]*100 + (*dimorder)[1]*10 + (*dimorder)[2];
+}
 
-void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
+
+static
+void vlistDecodeXyz(int xyz, int (*outDimorder)[3])
 {
-  vlist_t *vlistptr;
+  (*outDimorder)[0] = xyz/100, xyz -= (*outDimorder)[0]*100;
+  (*outDimorder)[1] = xyz/10, xyz -= (*outDimorder)[1]*10;
+  (*outDimorder)[2] = xyz;
+}
 
-  vlistptr = vlist_to_pointer(vlistID);
+
+void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1885,32 +1606,36 @@ void  vlistDefVarXYZ(int vlistID, int varID, int xyz)
   /* check xyz dimension order */
   {
     int dimorder[3];
+    vlistDecodeXyz(xyz, &dimorder);
     int dimx = 0, dimy = 0, dimz = 0;
-    dimorder[0] = xyz/100;
-    dimorder[1] = (xyz-dimorder[0]*100)/10;
-    dimorder[2] = (xyz-dimorder[0]*100-dimorder[1]*10);
     for ( int id = 0; id < 3; ++id )
       {
-        if      ( dimorder[id] == 3 ) { dimz++; }
-        else if ( dimorder[id] == 2 ) { dimy++; }
-        else if ( dimorder[id] == 1 ) { dimx++; }
-      }
+        switch ( dimorder[id] )
+          {
+            case 1: dimx++; break;
+            case 2: dimy++; break;
+            case 3: dimz++; break;
+            default: dimorder[id] = 0; break;    //Ensure that we assign a valid dimension to this position.
+          }
+     }
     if ( dimz > 1 || dimy > 1 || dimx > 1 ) xyz = 321; // ZYX
     else
       {
-        int lchanged = 0;
-        if ( dimz == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 3; lchanged++; break;}
-        if ( dimy == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 2; lchanged++; break;}
-        if ( dimx == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 1; lchanged++; break;}
-        if ( lchanged ) xyz = dimorder[0]*100 + dimorder[1]*10 + dimorder[2];
+        if ( dimz == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 3; break;}
+        if ( dimy == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 2; break;}
+        if ( dimx == 0 ) for ( int id = 0; id < 3; ++id ) if ( dimorder[id] == 0 ) {dimorder[id] = 1; break;}
+        xyz = vlistEncodeXyz(&dimorder);
       }
   }
 
+  assert(xyz == 123 || xyz == 312 || xyz == 231 || xyz == 321 || xyz == 132 || xyz == 213);
+
   vlistptr->vars[varID].xyz = xyz;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
-int vlistInqVarXYZ(int vlistID, int varID)
+void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3])
 {
   vlist_t *vlistptr;
 
@@ -1918,34 +1643,41 @@ int vlistInqVarXYZ(int vlistID, int varID)
 
   vlistCheckVarID(__func__, vlistID, varID);
 
-  return (vlistptr->vars[varID].xyz);
+  vlistDecodeXyz(vlistptr->vars[varID].xyz, outDimorder);
 }
 
 
+int vlistInqVarXYZ(int vlistID, int varID)
+{
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+  vlistCheckVarID(__func__, vlistID, varID);
+
+  return (vlistptr->vars[varID].xyz);
+}
+
 /* Ensemble Info Routines */
 void vlistDefVarEnsemble(int vlistID, int varID, int ensID, int ensCount, int forecast_type )
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
   if ( vlistptr->vars[varID].ensdata == NULL )
-    vlistptr->vars[varID].ensdata = (ensinfo_t *) malloc( sizeof( ensinfo_t ) );
+    vlistptr->vars[varID].ensdata
+      = (ensinfo_t *)xmalloc( sizeof( ensinfo_t ) );
 
   vlistptr->vars[varID].ensdata->ens_index          = ensID;
   vlistptr->vars[varID].ensdata->ens_count          = ensCount;
   vlistptr->vars[varID].ensdata->forecast_init_type = forecast_type;
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 }
 
 
 int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int *forecast_type )
 {
-  vlist_t *vlistptr;
   int status = 0;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -1969,17 +1701,35 @@ int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int
 void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  int idx;
 
-  int idx = vlistptr->vars[varID].opt_grib_int_nentries;
-  vlistptr->vars[varID].opt_grib_int_nentries++;
-  if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
-  vlistptr->vars[varID].opt_grib_int_val[idx] = value;
-  if ( name )
-    vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(name);
+  if ( !vlistptr->locked )
+    Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
+          "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+
+  for ( idx=0; idx<vlistptr->vars[varID].opt_grib_int_nentries; idx++)
+    if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[idx]) == 0 ) break;
+
+  if ( idx < vlistptr->vars[varID].opt_grib_int_nentries )
+    {
+      vlistptr->vars[varID].opt_grib_int_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
+    }
   else
-    Error("Internal error!");
+    {
+      idx = vlistptr->vars[varID].opt_grib_int_nentries;
+      vlistptr->vars[varID].opt_grib_int_nentries++;
+      if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/integer value pairs!");
+      vlistptr->vars[varID].opt_grib_int_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_int_update[idx] = TRUE;
+      if ( name )
+        vlistptr->vars[varID].opt_grib_int_keyword[idx] = strdupx(name);
+      else
+        Error("Internal error, name undefined!");
+    }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 #endif
 }
 
@@ -1987,17 +1737,35 @@ void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
 void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
+  int idx;
 
-  int idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
-  vlistptr->vars[varID].opt_grib_dbl_nentries++;
-  if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
-  vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
-  if ( name )
-    vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(name);
+  if ( !vlistptr->locked )
+    Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
+          "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+
+  for ( idx=0; idx<vlistptr->vars[varID].opt_grib_dbl_nentries; idx++)
+    if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[idx]) == 0 ) break;
+
+  if ( idx < vlistptr->vars[varID].opt_grib_dbl_nentries )
+    {
+      vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
+    }
   else
-    Error("Internal error!");
+    {
+      idx = vlistptr->vars[varID].opt_grib_dbl_nentries;
+      vlistptr->vars[varID].opt_grib_dbl_nentries++;
+      if ( idx >= MAX_OPT_GRIB_ENTRIES ) Error("Too many optional keyword/double value pairs!");
+      vlistptr->vars[varID].opt_grib_dbl_val[idx] = value;
+      vlistptr->vars[varID].opt_grib_dbl_update[idx] = TRUE;
+      if ( name )
+        vlistptr->vars[varID].opt_grib_dbl_keyword[idx] = strdupx(name);
+      else
+        Error("Internal error, name undefined!");
+    }
+
+  reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
 #endif
 }
 
@@ -2011,8 +1779,7 @@ void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
 void cdiClearAdditionalKeys()
 {
 #if  defined  (HAVE_LIBGRIB_API)
-  int i;
-  for (i=0; i<cdiNAdditionalGRIBKeys; i++)  free(cdiAdditionalGRIBKeys[i]);
+  for (int i=0; i<cdiNAdditionalGRIBKeys; i++)  free(cdiAdditionalGRIBKeys[i]);
   cdiNAdditionalGRIBKeys = 0;
 #endif
 }
@@ -2036,17 +1803,15 @@ int vlistHasVarKey(int vlistID, int varID, const char* name)
 {
 #if  defined  (HAVE_LIBGRIB_API)
   /* check if the GRIB key was previously read and is stored */
-  vlist_t *vlistptr;
-  int      i;
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
     {
       if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[i]) == 0 )
 	return 1;
     }
 
-  for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
     {
       if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[i]) == 0 )
 	return 1;
@@ -2060,13 +1825,10 @@ double vlistInqVarDblKey(int vlistID, int varID, const char* name)
 {
   double value = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  /* check if the GRIB key was previously read and is stored in
-     "opt_grib_dbl_val" */
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  /* check if the GRIB key was previously read and is stored in "opt_grib_dbl_val" */
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  int i;
-  for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++)
     if ( strcmp(name, vlistptr->vars[varID].opt_grib_dbl_keyword[i]) == 0 )
       return vlistptr->vars[varID].opt_grib_dbl_val[i];
 #endif
@@ -2079,13 +1841,10 @@ int vlistInqVarIntKey(int vlistID, int varID, const char* name)
 {
   long int value = 0;
 #if  defined  (HAVE_LIBGRIB_API)
-  /* check if the GRIB key was previously read and is stored in
-     "opt_grib_int_val" */
-  vlist_t *vlistptr;
-  vlistptr = vlist_to_pointer(vlistID);
+  /* check if the GRIB key was previously read and is stored in "opt_grib_int_val" */
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
-  int i;
-  for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
+  for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++)
     if ( strcmp(name, vlistptr->vars[varID].opt_grib_int_keyword[i]) == 0 )
       return vlistptr->vars[varID].opt_grib_int_val[i];
 #endif
@@ -2093,29 +1852,23 @@ int vlistInqVarIntKey(int vlistID, int varID, const char* name)
 }
 
 
-void     vlistDefVarIOrank   ( int vlistID, int varID, int iorank )
+void vlistDefVarIOrank(int vlistID, int varID, int iorank)
 {
-  vlist_t * vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID );
+  vlist_t *vlistptr = vlist_to_pointer(vlistID );
 
   vlistCheckVarID ( __func__, vlistID, varID );
 
-  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
+  if (vlistptr->vars[varID].iorank != iorank)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      vlistptr->vars[varID].iorank = iorank;
+      reshSetStatus(vlistID, &vlist_ops, RESH_DESYNC_IN_USE);
     }
-
-  vlistptr->vars[varID].iorank = iorank;
 }
 
 
 int vlistInqVarIOrank(int vlistID, int varID)
 {
-  vlist_t *vlistptr;
-
-  vlistptr = vlist_to_pointer(vlistID);
+  vlist_t *vlistptr = vlist_to_pointer(vlistID);
 
   vlistCheckVarID(__func__, vlistID, varID);
 
@@ -2130,6 +1883,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
           && varIDB >= 0 && varIDB < b->nvars);
   var_t *pva = a->vars + varIDA, *pvb = b->vars + varIDB;
 #define FCMP(f) ((pva->f) != (pvb->f))
+#define FCMPFLT(f) (IS_NOT_EQUAL((pva->f), (pvb->f)))
 #define FCMPSTR(fs) ((pva->fs) != (pvb->fs) && strcmp((pva->fs), (pvb->fs)))
 #define FCMP2(f) (namespaceResHDecode(pva->f).idx       \
                   != namespaceResHDecode(pvb->f).idx)
@@ -2137,28 +1891,29 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
     | FCMP(datatype) | FCMP(tsteptype) | FCMP(timave) | FCMP(timaccu)
     | FCMP(chunktype) | FCMP(xyz) | FCMP2(gridID) | FCMP2(zaxisID)
     | FCMP2(instID) | FCMP2(modelID) | FCMP2(tableID) | FCMP(missvalused)
-    | FCMP(missval) | FCMP(addoffset) | FCMP(scalefactor) | FCMPSTR(name)
+    | FCMPFLT(missval) | FCMPFLT(addoffset) | FCMPFLT(scalefactor) | FCMPSTR(name)
     | FCMPSTR(longname) | FCMPSTR(stdname) | FCMPSTR(units) | FCMPSTR(extra)
     | FCMP(comptype) | FCMP(complevel) | FCMP(lvalidrange)
-    | FCMP(validrange[0]) | FCMP(validrange[1]);
+    | FCMPFLT(validrange[0]) | FCMPFLT(validrange[1]);
 #undef FCMP
+#undef FCMPFLT
 #undef FCMP2
   if ((diff |= ((pva->levinfo == NULL) ^ (pvb->levinfo == NULL))))
     return 1;
   if (pva->levinfo)
     {
       int zaxisID = pva->zaxisID;
-      int nlevs = zaxisInqSize(zaxisID);
+      size_t nlevs = (size_t)zaxisInqSize(zaxisID);
       diff |= (memcmp(pva->levinfo, pvb->levinfo, sizeof (levinfo_t) * nlevs)
                != 0);
       if (diff)
         return 1;
     }
-  int natts = a->vars[varIDA].atts.nelems;
+  size_t natts = a->vars[varIDA].atts.nelems;
   if (natts != b->vars[varIDB].atts.nelems)
     return 1;
-  for (int attID = 0; attID < natts; ++attID)
-    diff |= vlist_att_compare(a, varIDA, b, varIDB, attID);
+  for (size_t attID = 0; attID < natts; ++attID)
+    diff |= vlist_att_compare(a, varIDA, b, varIDB, (int)attID);
   if ((diff |= ((pva->ensdata == NULL) ^ (pvb->ensdata == NULL))))
     return 1;
   if (pva->ensdata)
@@ -2179,13 +1934,13 @@ int vlistVarGetPackSize(vlist_t *p, int varID, void *context)
   int varsize = serializeGetSize(vlistvar_nints, DATATYPE_INT, context)
     + serializeGetSize(vlistvar_ndbls, DATATYPE_FLT64, context);
   if (var->name)
-    varsize += serializeGetSize(strlen(var->name), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->name), DATATYPE_TXT, context);
   if (var->longname)
-    varsize += serializeGetSize(strlen(var->longname), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->longname), DATATYPE_TXT, context);
   if (var->stdname)
-    varsize += serializeGetSize(strlen(var->stdname), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->stdname), DATATYPE_TXT, context);
   if (var->units)
-    varsize += serializeGetSize(strlen(var->units), DATATYPE_TXT, context);
+    varsize += serializeGetSize((int)strlen(var->units), DATATYPE_TXT, context);
   varsize += serializeGetSize(4 * zaxisInqSize(var->zaxisID),
                               DATATYPE_INT, context);
   varsize += vlistAttsGetSize(p, varID, context);
@@ -2203,10 +1958,10 @@ void vlistVarPack(vlist_t *p, int varID, char * buf, int size, int *position,
   tempbuf[1] = var->gridID;
   tempbuf[2] = var->zaxisID;
   tempbuf[3] = var->tsteptype;
-  tempbuf[4] = namesz = var->name?strlen(var->name):0;
-  tempbuf[5] = longnamesz = var->longname?strlen(var->longname):0;
-  tempbuf[6] = stdnamesz = var->stdname?strlen(var->stdname):0;
-  tempbuf[7] = unitssz = var->units?strlen(var->units):0;
+  tempbuf[4] = namesz = var->name?(int)strlen(var->name):0;
+  tempbuf[5] = longnamesz = var->longname?(int)strlen(var->longname):0;
+  tempbuf[6] = stdnamesz = var->stdname?(int)strlen(var->stdname):0;
+  tempbuf[7] = unitssz = var->units?(int)strlen(var->units):0;
   tempbuf[8] = var->datatype;
   tempbuf[9] = var->param;
   tempbuf[10] = var->instID;
@@ -2266,7 +2021,6 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
 {
   double dtempbuf[vlistvar_ndbls];
   int tempbuf[vlistvar_nints];
-  int newvar;
   char *varname = NULL;
   vlist_t *vlistptr = vlist_to_pointer(vlistID);
   serializeUnpack(buf, size, position,
@@ -2274,13 +2028,14 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
   serializeUnpack(buf, size, position,
                   dtempbuf, vlistvar_ndbls, DATATYPE_FLT64, context);
 
-  newvar = vlistDefVar ( vlistID,
+  int newvar = vlistDefVar ( vlistID,
 			 namespaceAdaptKey ( tempbuf[1], originNamespace ),
 			 namespaceAdaptKey ( tempbuf[2], originNamespace ),
 			 tempbuf[3]);
   if (tempbuf[4] || tempbuf[5] || tempbuf[6] || tempbuf[7])
-    varname = (char*) xmalloc(imax(imax(imax(tempbuf[4],tempbuf[5]),tempbuf[6]),
-                           tempbuf[7])+ 1);
+    varname = (char *)xmalloc((size_t)imax(imax(imax(tempbuf[4],tempbuf[5]),
+                                                tempbuf[6]),
+                                           tempbuf[7]) + 1);
   if (tempbuf[4])
   {
     serializeUnpack(buf, size, position,
@@ -2309,7 +2064,7 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position,
     varname[tempbuf[7]] = '\0';
     vlistDefVarUnits(vlistID, newvar, varname);
   }
-  if ( varname ) free ( varname );
+  free(varname);
   vlistDefVarDatatype(vlistID, newvar, tempbuf[8]);
   vlistDefVarInstitut ( vlistID, newvar,
 			namespaceAdaptKey ( tempbuf[10], originNamespace ));
diff --git a/libcdi/src/zaxis.c b/libcdi/src/zaxis.c
index 2ddcfd4..ea95210 100644
--- a/libcdi/src/zaxis.c
+++ b/libcdi/src/zaxis.c
@@ -76,6 +76,7 @@ typedef struct {
   int      prec;
   int      type;
   int      ltype;    /* GRIB level type */
+  int      ltype2;
   int      size;
   int      direction;
   int      vctsize;
@@ -105,7 +106,7 @@ static const resOps zaxisOps = {
 static int  ZAXIS_Debug = 0;   /* If set to 1, debugging */
 
 static
-void zaxisDefaultValue ( zaxis_t *zaxisptr )
+void zaxisDefaultValue(zaxis_t *zaxisptr)
 {
   zaxisptr->self        = CDI_UNDEFID;
   zaxisptr->name[0]     = 0;
@@ -118,6 +119,7 @@ void zaxisDefaultValue ( zaxis_t *zaxisptr )
   zaxisptr->weights     = NULL;
   zaxisptr->type        = CDI_UNDEFID;
   zaxisptr->ltype       = 0;
+  zaxisptr->ltype2      = -1;
   zaxisptr->positive    = 0;
   zaxisptr->direction   = 0;
   zaxisptr->prec        = 0;
@@ -189,6 +191,7 @@ zaxisCreate_(int zaxistype, int size, int id)
 {
   zaxis_t *zaxisptr = zaxisNewEntry(id);
 
+  xassert(size >= 0);
   zaxisptr->type = zaxistype;
   zaxisptr->size = size;
 
@@ -205,7 +208,8 @@ zaxisCreate_(int zaxistype, int size, int id)
 
   zaxisptr->positive = ZaxistypeEntry[zaxistype].positive;
 
-  double *vals = zaxisptr->vals = (double *)xmalloc(size*sizeof(double));
+  double *vals = zaxisptr->vals
+    = (double *)xmalloc((size_t)size * sizeof(double));
 
   for ( int ilev = 0; ilev < size; ilev++ )
     vals[ilev] = 0.0;
@@ -342,15 +346,7 @@ The function @func{zaxisDefName} defines the name of a Z-axis.
 */
 void zaxisDefName(int zaxisID, const char *name)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -358,6 +354,7 @@ void zaxisDefName(int zaxisID, const char *name)
     {
       strncpy(zaxisptr->name, name, CDI_MAX_NAME - 1);
       zaxisptr->name[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -377,15 +374,7 @@ The function @func{zaxisDefLongname} defines the longname of a Z-axis.
 */
 void zaxisDefLongname(int zaxisID, const char *longname)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -393,6 +382,7 @@ void zaxisDefLongname(int zaxisID, const char *longname)
     {
       strncpy(zaxisptr->longname, longname, CDI_MAX_NAME - 1);
       zaxisptr->longname[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -412,15 +402,7 @@ The function @func{zaxisDefUnits} defines the units of a Z-axis.
 */
 void zaxisDefUnits(int zaxisID, const char *units)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -428,6 +410,7 @@ void zaxisDefUnits(int zaxisID, const char *units)
     {
       strncpy(zaxisptr->units, units, CDI_MAX_NAME - 1);
       zaxisptr->units[CDI_MAX_NAME - 1] = '\0';
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
 }
 
@@ -528,19 +511,15 @@ void zaxisInqStdname(int zaxisID, char *stdname)
 
 void zaxisDefPrec(int zaxisID, int prec)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->prec = prec;
+  if (zaxisptr->prec != prec)
+    {
+      zaxisptr->prec = prec;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -556,19 +535,15 @@ int zaxisInqPrec(int zaxisID)
 
 void zaxisDefPositive(int zaxisID, int positive)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->positive = positive;
+  if (zaxisptr->positive != positive)
+    {
+      zaxisptr->positive = (unsigned char)positive;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -584,29 +559,49 @@ int zaxisInqPositive(int zaxisID)
 
 void zaxisDefLtype(int zaxisID, int ltype)
 {
-  zaxis_t *zaxisptr;
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
+
+  zaxis_check_ptr(zaxisID, zaxisptr);
 
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
+  if (zaxisptr->ltype != ltype)
     {
-      Warning("%s", "Operation not executed.");
-      return;
+      zaxisptr->ltype = ltype;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
+}
+
 
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+int zaxisInqLtype(int zaxisID)
+{
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->ltype = ltype;
+  return (zaxisptr->ltype);
 }
 
 
-int zaxisInqLtype(int zaxisID)
+void zaxisDefLtype2(int zaxisID, int ltype2)
 {
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  return (zaxisptr->ltype);
+  if (zaxisptr->ltype2 != ltype2)
+    {
+      zaxisptr->ltype2 = ltype2;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
+}
+
+
+int zaxisInqLtype2(int zaxisID)
+{
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
+
+  zaxis_check_ptr(zaxisID, zaxisptr);
+
+  return (zaxisptr->ltype2);
 }
 
 /*
@@ -625,15 +620,7 @@ The function @func{zaxisDefLevels} defines the levels of a Z-axis.
 */
 void zaxisDefLevels(int zaxisID, const double *levels)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
@@ -643,6 +630,7 @@ void zaxisDefLevels(int zaxisID, const double *levels)
 
   for (int ilev = 0; ilev < size; ilev++ )
     vals[ilev] = levels[ilev];
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -662,38 +650,27 @@ The function @func{zaxisDefLevel} defines one level of a Z-axis.
 */
 void zaxisDefLevel(int zaxisID, int levelID, double level)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   if ( levelID >= 0 && levelID < zaxisptr->size )
     zaxisptr->vals[levelID] = level;
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefNlevRef(int zaxisID, const int nhlev)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->nhlev = nhlev;
+  if (zaxisptr->nhlev != nhlev)
+    {
+      zaxisptr->nhlev = nhlev;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 
@@ -722,19 +699,15 @@ The function @func{zaxisDefNumber} defines the reference number for a generalize
 */
 void zaxisDefNumber(int zaxisID, const int number)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxisptr->number = number;
+  if (zaxisptr->number != number)
+    {
+      zaxisptr->number = number;
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
+    }
 }
 
 /*
@@ -777,21 +750,12 @@ The function @func{zaxisDefUUID} defines the UUID for a generalized  Z-axis.
 */
 void zaxisDefUUID(int zaxisID, const char *uuid)
 {
-  zaxis_t *zaxisptr;
-
-    if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   memcpy(zaxisptr->uuid, uuid, 16);
-
-  return;
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 /*
@@ -1095,23 +1059,16 @@ void cdiCheckZaxis(int zaxisID)
 
 void zaxisDefVct(int zaxisID, int size, const double *vct)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   if ( zaxisptr->vct == 0 )
     {
       zaxisptr->vctsize = size;
-      zaxisptr->vct = (double *) malloc(size*sizeof(double));
-      memcpy(zaxisptr->vct, vct, size*sizeof(double));
+      zaxisptr->vct = (double *)xmalloc((size_t)size * sizeof (double));
+      memcpy(zaxisptr->vct, vct, (size_t)size * sizeof (double));
+      reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
     }
   else
     if ( zaxisptr->vctsize != size )
@@ -1125,7 +1082,7 @@ void zaxisInqVct(int zaxisID, double *vct)
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  memcpy(vct, zaxisptr->vct, zaxisptr->vctsize*sizeof(double));
+  memcpy(vct, zaxisptr->vct, (size_t)zaxisptr->vctsize * sizeof (double));
 }
 
 
@@ -1151,19 +1108,11 @@ const double *zaxisInqVctPtr(int zaxisID)
 
 void zaxisDefLbounds(int zaxisID, const double *lbounds)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->lbounds != NULL )
@@ -1173,24 +1122,17 @@ void zaxisDefLbounds(int zaxisID, const double *lbounds)
     zaxisptr->lbounds = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->lbounds, lbounds, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefUbounds(int zaxisID, const double *ubounds)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->ubounds != NULL )
@@ -1200,24 +1142,17 @@ void zaxisDefUbounds(int zaxisID, const double *ubounds)
     zaxisptr->ubounds = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->ubounds, ubounds, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
 void zaxisDefWeights(int zaxisID, const double *weights)
 {
-  zaxis_t *zaxisptr;
-
-  if ( reshGetStatus ( zaxisID, &zaxisOps ) == RESH_CLOSED )
-    {
-      Warning("%s", "Operation not executed.");
-      return;
-    }
-
-  zaxisptr = ( zaxis_t * ) reshGetVal ( zaxisID, &zaxisOps );
+  zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  size_t size = zaxisptr->size;
+  size_t size = (size_t)zaxisptr->size;
 
   if ( CDI_Debug )
     if ( zaxisptr->weights != NULL )
@@ -1227,6 +1162,7 @@ void zaxisDefWeights(int zaxisID, const double *weights)
     zaxisptr->weights = (double *)xmalloc(size*sizeof(double));
 
   memcpy(zaxisptr->weights, weights, size*sizeof(double));
+  reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
 }
 
 
@@ -1244,26 +1180,25 @@ void zaxisResize(int zaxisID, int size)
 {
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
+  xassert(size >= 0);
   zaxis_check_ptr(zaxisID, zaxisptr);
 
   zaxisptr->size = size;
 
   if ( zaxisptr->vals )
-    zaxisptr->vals = (double *)xrealloc(zaxisptr->vals, size*sizeof(double));
+    zaxisptr->vals = (double *)xrealloc(zaxisptr->vals, (size_t)size * sizeof(double));
 }
 
 
 int zaxisDuplicate(int zaxisID)
 {
   int zaxisIDnew;
-  int zaxistype, zaxissize;
-  int size;
   zaxis_t *zaxisptr = reshGetVal(zaxisID, &zaxisOps);
 
   zaxis_check_ptr(zaxisID, zaxisptr);
 
-  zaxistype = zaxisInqType(zaxisID);
-  zaxissize = zaxisInqSize(zaxisID);
+  int zaxistype = zaxisInqType(zaxisID);
+  int zaxissize = zaxisInqSize(zaxisID);
 
   zaxisIDnew = zaxisCreate(zaxistype, zaxissize);
   zaxis_t *zaxisptrnew = reshGetVal(zaxisIDnew, &zaxisOps);
@@ -1276,37 +1211,37 @@ int zaxisDuplicate(int zaxisID)
 
   if ( zaxisptr->vals != NULL )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->vals = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->vals, zaxisptr->vals, size*sizeof(double));
+      zaxisptrnew->vals = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->vals, zaxisptr->vals, size * sizeof (double));
     }
 
   if ( zaxisptr->lbounds )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->lbounds = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->lbounds, zaxisptr->lbounds, size*sizeof(double));
+      zaxisptrnew->lbounds = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->lbounds, zaxisptr->lbounds, size * sizeof(double));
     }
 
   if ( zaxisptr->ubounds )
     {
-      size = zaxissize;
+      size_t size = (size_t)zaxissize;
 
-      zaxisptrnew->ubounds = (double *)xmalloc(size*sizeof(double));
-      memcpy(zaxisptrnew->ubounds, zaxisptr->ubounds, size*sizeof(double));
+      zaxisptrnew->ubounds = (double *)xmalloc(size * sizeof (double));
+      memcpy(zaxisptrnew->ubounds, zaxisptr->ubounds, size * sizeof (double));
     }
 
   if ( zaxisptr->vct != NULL )
     {
-      size = zaxisptr->vctsize;
+      size_t size = (size_t)zaxisptr->vctsize;
 
       if ( size )
         {
-          zaxisptrnew->vctsize = size;
-          zaxisptrnew->vct = (double *)xmalloc(size*sizeof(double));
-          memcpy(zaxisptrnew->vct, zaxisptr->vct, size*sizeof(double));
+          zaxisptrnew->vctsize = (int)size;
+          zaxisptrnew->vct = (double *)xmalloc(size * sizeof (double));
+          memcpy(zaxisptrnew->vct, zaxisptr->vct, size * sizeof (double));
         }
     }
 
@@ -1631,10 +1566,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & vals)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->vals = (double*) xmalloc(size * sizeof ( double ));
+      zaxisP->vals = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->vals, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -1644,10 +1579,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & lbounds)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->lbounds = (double*) xmalloc(size * sizeof (double));
+      zaxisP->lbounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->lbounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -1657,10 +1592,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & ubounds)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->ubounds = (double*) xmalloc(size * sizeof (double));
+      zaxisP->ubounds = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->ubounds, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -1670,10 +1605,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if (memberMask & weights)
     {
-      int size;
-      xassert((size = zaxisP->size));
+      int size = zaxisP->size;
+      xassert(size >= 0);
 
-      zaxisP->weights = (double*) xmalloc(size * sizeof (double));
+      zaxisP->weights = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->weights, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
@@ -1683,10 +1618,10 @@ zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
 
   if ( memberMask & vct )
     {
-      int size;
-      xassert((size = zaxisP->vctsize));
+      int size = zaxisP->vctsize;
+      xassert(size >= 0);
 
-      zaxisP->vct = (double*) xmalloc(size * sizeof (double));
+      zaxisP->vct = (double *)xmalloc((size_t)size * sizeof (double));
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
                       zaxisP->vct, size, DATATYPE_FLT64, context);
       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
diff --git a/libcdi/tables/gen_tableheaderfile.in b/libcdi/tables/gen_tableheaderfile.in
new file mode 100755
index 0000000..0a393a2
--- /dev/null
+++ b/libcdi/tables/gen_tableheaderfile.in
@@ -0,0 +1,108 @@
+#!/bin/ksh
+#
+# gen_tables create the headerfile table.h
+# with all default tables from default_tables
+#
+set -e
+DEFTABLES=@abs_top_srcdir@/tables/default_tables
+OFILE=@abs_top_srcdir@/src/table.h
+PTFILES=""
+#
+#########################################
+#
+exec 3<"$DEFTABLES"
+#
+item=0
+while read -u3 PTFILE[item] ; do
+#
+
+if [ -z ${PTFILE[item]} ] ; then break ; fi
+#
+PTFILE[item]="@abs_srcdir@/${PTFILE[item]}"
+#
+let item=item+1
+#
+done
+unset PTFILE[item]
+#
+#########################################
+#
+rm -f $OFILE
+#
+cat >> $OFILE <<EOF
+#ifndef _TABLE_H
+#define _TABLE_H
+
+EOF
+#
+for TFILE in "${PTFILE[@]}"; do
+    echo "process: $TFILE"
+    rm -f ptfile
+    ../app/createtable "$TFILE" - >>"$OFILE"
+done
+#
+cat >> $OFILE <<EOF
+
+static void
+tableDefault(void)
+{
+  int tableID, instID, modelID;
+
+EOF
+#
+settabvar() {
+  val=`grep $2 $1 | cut -f 2 -d "="`
+  echo $val
+}
+#
+item=0
+for TFILE in "${PTFILE[@]}" ; do
+TFBASENAME="${TFILE##*/}"
+echo "process: $TFILE"
+#
+TABLE_ID=`settabvar ${TFILE}  "TABLE_ID"`
+TABLE_NA=`settabvar ${TFILE}  "TABLE_NA"`
+TABLE_MO=`settabvar ${TFILE}  "TABLE_MO"`
+TABLE_IN=`settabvar ${TFILE}  "TABLE_IN"`
+TABLE_CE=`settabvar ${TFILE}  "TABLE_CE"`
+TABLE_SU=`settabvar ${TFILE}  "TABLE_SU"`
+#
+if [ -z $TABLE_ID ] ; then TABLE_ID=0; fi
+if [ -z $TABLE_NA ] ; then TABLE_NA=$TFBASENAME; fi
+#if [ -z $TABLE_MO ] ; then TABLE_MO=NULL; fi
+if [ -z $TABLE_CE ] ; then TABLE_CE=0; fi
+if [ -z $TABLE_SU ] ; then TABLE_SU=0; fi
+#
+echo "ID = $TABLE_ID name=$TABLE_NA model=$TABLE_MO inistitut=$TABLE_IN center=$TABLE_CE subcenter=$TABLE_SU"
+TABLENAME=`echo ${TFBASENAME} | sed -e "s/\./_/g" `
+#
+cat >> $OFILE <<EOF
+
+  /*
+   *  define table : ${TFBASENAME}
+   */
+
+  instID  = institutInq(${TABLE_CE}, ${TABLE_SU}, "${TABLE_IN}", NULL);
+  if ( instID == -1 )
+    instID  = institutDef(${TABLE_CE}, ${TABLE_SU}, "${TABLE_IN}", NULL);
+
+  modelID = modelInq(instID, 0, "${TABLE_MO}");
+  if ( modelID == -1 )
+    modelID = modelDef(instID, 0, "${TABLE_MO}");
+
+  tableID = tableDef(modelID, ${TABLE_ID}, "${TABLE_NA}");
+
+  tableLink(tableID, ${TABLENAME}, sizeof(${TABLENAME}) / sizeof(PAR));
+EOF
+#
+done
+#
+cat >> $OFILE <<EOF
+}
+
+#endif  /* _TABLE_H */
+EOF
+#
+rm -f ptfile
+#
+exit
diff --git a/libcdi/tests/Makefile.am b/libcdi/tests/Makefile.am
index 0922b40..d1bbe97 100644
--- a/libcdi/tests/Makefile.am
+++ b/libcdi/tests/Makefile.am
@@ -7,7 +7,8 @@ TESTS = cksum_verify \
 	test_chunk_cksum \
 	pio_write_run pio_cksum_mpinonb pio_cksum_fpguard \
 	pio_cksum_asynch pio_cksum_writer pio_cksum_cdf \
-	test_resource_copy pio_write_deco2d_run
+	test_resource_copy pio_write_deco2d_run \
+	test_f2003
 check_PROGRAMS = cksum_verify test_grib cksum_write cksum_read pio_write \
 	test_resource_copy cksum_write_chunk pio_write_deco2d
 
diff --git a/libcdi/tests/Makefile.in b/libcdi/tests/Makefile.in
index 2a0b675..9950792 100644
--- a/libcdi/tests/Makefile.in
+++ b/libcdi/tests/Makefile.in
@@ -82,7 +82,7 @@ TESTS = cksum_verify$(EXEEXT) test_cksum_grib test_cksum_nc \
 	test_cksum_nc4 test_cksum_ieg test_chunk_cksum pio_write_run \
 	pio_cksum_mpinonb pio_cksum_fpguard pio_cksum_asynch \
 	pio_cksum_writer pio_cksum_cdf test_resource_copy$(EXEEXT) \
-	pio_write_deco2d_run $(am__append_1)
+	pio_write_deco2d_run test_f2003 $(am__append_1)
 check_PROGRAMS = cksum_verify$(EXEEXT) test_grib$(EXEEXT) \
 	cksum_write$(EXEEXT) cksum_read$(EXEEXT) pio_write$(EXEEXT) \
 	test_resource_copy$(EXEEXT) cksum_write_chunk$(EXEEXT) \
@@ -96,7 +96,8 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(srcdir)/test_cksum_nc2.in $(srcdir)/test_cksum_nc4.in \
 	$(srcdir)/test_cksum_extra.in $(srcdir)/test_cksum_service.in \
 	$(srcdir)/test_cksum_ieg.in $(srcdir)/test_chunk_cksum.in \
-	$(srcdir)/pio_write_run.in $(srcdir)/pio_write_deco2d_run.in \
+	$(srcdir)/test_f2003.in $(srcdir)/pio_write_run.in \
+	$(srcdir)/pio_write_deco2d_run.in \
 	$(srcdir)/pio_cksum_mpinonb.in $(srcdir)/pio_cksum_fpguard.in \
 	$(srcdir)/pio_cksum_asynch.in $(srcdir)/pio_cksum_writer.in \
 	$(srcdir)/pio_cksum_cdf.in \
@@ -105,6 +106,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_assert_lang_is_fortran_variant.m4 \
+	$(top_srcdir)/m4/acx_check_strptr_convert.m4 \
 	$(top_srcdir)/m4/acx_lang_other_suffix_conftest.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
@@ -121,7 +123,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/src/config.h
 CONFIG_CLEAN_FILES = test_cksum_grib test_cksum_nc test_cksum_nc2 \
 	test_cksum_nc4 test_cksum_extra test_cksum_service \
-	test_cksum_ieg test_chunk_cksum pio_write_run \
+	test_cksum_ieg test_chunk_cksum test_f2003 pio_write_run \
 	pio_write_deco2d_run pio_cksum_mpinonb pio_cksum_fpguard \
 	pio_cksum_asynch pio_cksum_writer pio_cksum_cdf \
 	test_resource_copy_mpi_run
@@ -541,6 +543,8 @@ test_cksum_ieg: $(top_builddir)/config.status $(srcdir)/test_cksum_ieg.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 test_chunk_cksum: $(top_builddir)/config.status $(srcdir)/test_chunk_cksum.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+test_f2003: $(top_builddir)/config.status $(srcdir)/test_f2003.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 pio_write_run: $(top_builddir)/config.status $(srcdir)/pio_write_run.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 pio_write_deco2d_run: $(top_builddir)/config.status $(srcdir)/pio_write_deco2d_run.in
diff --git a/libcdi/tests/cksum_read.c b/libcdi/tests/cksum_read.c
index 6dff4b9..b39fc01 100644
--- a/libcdi/tests/cksum_read.c
+++ b/libcdi/tests/cksum_read.c
@@ -1,5 +1,5 @@
-#ifndef HAVE_CONFIG_H
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
 #endif
 
 #include <assert.h>
@@ -17,16 +17,16 @@ read_table(const char *table_fname, size_t *table_len)
   struct cksum_table *table = NULL;
   FILE *tablefp;
   size_t table_size = 0, table_used = 0;
-  unsigned long cksum_temp;
+  uint32_t cksum_temp;
   int code;
 
   if (!(tablefp = fopen(table_fname, "r")))
     {
       perror("failed to open table file");
-      *table_len = -1;
+      *table_len = (size_t)-1;
       return NULL;
     }
-  while (fscanf(tablefp, "%08lx %d\n", &cksum_temp, &code) == 2)
+  while (fscanf(tablefp, "%08"PRIx32" %d\n", &cksum_temp, &code) == 2)
     {
       ENSURE_ARRAY_SIZE(table, table_size, table_used + 1);
       table[table_used].code = code;
diff --git a/libcdi/tests/cksum_write.c b/libcdi/tests/cksum_write.c
index ba060da..98acb19 100644
--- a/libcdi/tests/cksum_write.c
+++ b/libcdi/tests/cksum_write.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -59,6 +63,16 @@ fname_create(const char *prefix, const char *suffix)
   return fname;
 }
 
+static inline void
+check_positive(int v, const char *msg)
+{
+  if (v < 1)
+    {
+      fprintf(stderr, "error: number of %s must be positive!\n", msg);
+      exit(EXIT_FAILURE);
+    }
+}
+
 #ifdef TEST_CHUNK_WRITE
 static void
 get_chunk(double *chunkBuf, double *var, int varShape[3],
@@ -155,6 +169,7 @@ main(int argc, char *argv[])
 #endif
       case 'm':
         nlon = parse_intarg("error parsing number of longitudes");
+        check_positive(nlon, "longitudes");
 #ifdef TEST_CHUNK_WRITE
         if (nlon < 2)
           {
@@ -165,13 +180,16 @@ main(int argc, char *argv[])
 #endif
         break;
       case 'n':
-        nlat = parse_intarg("error parsing number of latitudes");
+        check_positive(nlat = parse_intarg("error parsing number of latitudes"),
+                       "latitudes");
         break;
       case 'o':
-        nlev = parse_intarg("error parsing number of levels");
+        check_positive(nlev = parse_intarg("error parsing number of levels"),
+                       "levels");
         break;
       case 't':
-        nts = parse_intarg("error parsing number of timesteps");
+        check_positive(nts = parse_intarg("error parsing number of timesteps"),
+                       "timesteps");
         break;
       default: /* '?' */
         fprintf(stderr, "Usage: %s [-m nlon] [-n nlat] [-o nlev] [-t nts]\n", argv[0]);
@@ -179,18 +197,18 @@ main(int argc, char *argv[])
       }
   }
 
-  lons = malloc(nlon * sizeof (lons[0]));
+  lons = malloc((size_t)nlon * sizeof (lons[0]));
   for (i = 0; i < nlon; ++i)
     lons[i] = ((double)(i * 360))/nlon;
-  lats = malloc(nlat * sizeof (lats[0]));
+  lats = malloc((size_t)nlat * sizeof (lats[0]));
   for (i = 0; i < nlat; ++i)
     lats[i] = ((double)(i * 180))/nlat - 90.0;
-  levs = malloc(nlev * sizeof (levs[0]));
+  levs = malloc((size_t)nlev * sizeof (levs[0]));
   for (i = 0; i < nlev; ++i)
     levs[i] = 101300 - floor(3940.3 * (exp(2.3579 * (double)(i)/(nlev - 1)) - 1.0));
 
-  varSize[0] = nlon * nlat;
-  varSize[1] = nlon * nlat * nlev;
+  varSize[0] = (size_t)nlon * (size_t)nlat;
+  varSize[1] = (size_t)nlon * (size_t)nlat * (size_t)nlev;
 
   // Create a regular lon/lat grid
   gridID = gridCreate(grid, nlon*nlat);
@@ -253,7 +271,7 @@ main(int argc, char *argv[])
                 datatype);
         exit(EXIT_FAILURE);
       }
-    mscale = INT64_C(1) << mant_bits;
+    mscale = (double)(INT64_C(1) << mant_bits);
     mrscale = 1.0/mscale;
   }
 
@@ -314,7 +332,8 @@ main(int argc, char *argv[])
         // Write var1 and var2
 #ifdef TEST_CHUNK_WRITE
         {
-          size_t maxChunkSize = (nlon + 1)/2 * nlat * nlev;
+          size_t maxChunkSize
+            = ((size_t)nlon + 1)/2 * (size_t)nlat * (size_t)nlev;
           double *chunkBuf = malloc(maxChunkSize * sizeof (double));
           int varShape[2][3] = { { nlon, nlat, 1 }, { nlon, nlat, nlev } },
             chunk[3][2] = { { 0, nlon/2 - 1 }, { 0, nlat - 1 }, { 0, 0 } };
@@ -361,7 +380,9 @@ main(int argc, char *argv[])
         {
           uint32_t cksum;
           int code;
-          cksum = memcrc_finish(&checksum_state[i], (off_t)varSize[i] * sizeof (var[i][0]) * nts);
+          cksum = memcrc_finish(&checksum_state[i],
+                                (off_t)(varSize[i] * sizeof (var[i][0])
+                                        * (size_t)nts));
           code = vlistInqVarCode(vlistID, varID[i]);
           if (fprintf(tablefp, "%08lx %d\n", (unsigned long)cksum, code) < 0)
             {
diff --git a/libcdi/tests/deco2d_model.c b/libcdi/tests/deco2d_model.c
index 6ffbf3d..7e84bf7 100644
--- a/libcdi/tests/deco2d_model.c
+++ b/libcdi/tests/deco2d_model.c
@@ -56,11 +56,13 @@ modelRegionCompute(double region[], int nlev, int nlat, int nlon,
     for (unsigned j = 0; j < n; ++j)
       for (unsigned i = 0; i < m; ++i)
         region[k * kstride + j * jstride + i]
-          = sign_flat(round((cos(2.0 * M_PI * (lons[(i + is + tsID)%nlon]
-                                               - lons[0])
+          = sign_flat(round((cos(2.0 * M_PI
+                                 * (lons[(i + is + (unsigned)tsID)
+                                         %(unsigned)nlon] - lons[0])
                                  / (lons[nlon-1] - lons[0]))
-                             * sin(2.0 * M_PI * (lats[(j + js + k + ks)%nlat]
-                                                 - lats[0])
+                             * sin(2.0 * M_PI
+                                   * (lats[(j + js + k + ks)%(unsigned)nlat]
+                                      - lats[0])
                                    / (lats[nlat-1] - lats[0]))
                              ) * mscale)) * mrscale;
 }
@@ -138,26 +140,26 @@ modelRun(struct model_config setup, MPI_Comm comm)
   gridID = gridCreate ( GRID_LONLAT, nlon*nlat );
   gridDefXsize ( gridID, nlon );
   gridDefYsize ( gridID, nlat );
-  lons = xmalloc(nlon * sizeof (lons[0]));
+  lons = xmalloc((size_t)nlon * sizeof (lons[0]));
   for (i = 0; i < nlon; ++i)
     lons[i] = ((double)(i * 360))/nlon;
-  lats = xmalloc(nlat * sizeof (lats[0]));
+  lats = xmalloc((size_t)nlat * sizeof (lats[0]));
   for (i = 0; i < nlat; ++i)
     lats[i] = ((double)(i * 180))/nlat - 90.0;
   gridDefXvals ( gridID, lons );
   gridDefYvals ( gridID, lats );
 
-  levs = xmalloc(setup.max_nlev * sizeof (levs[0]));
+  levs = xmalloc((size_t)setup.max_nlev * sizeof (levs[0]));
   for (i = 0; i < setup.max_nlev; ++i)
     levs[i] = 101300.0
       - 3940.3 * (exp(1.3579 * (double)(i)/(setup.max_nlev - 1)) - 1.0);
 
   vlistID = vlistCreate ();
 
-  varDesc = xmalloc(nVars * sizeof (varDesc[0]));
+  varDesc = xmalloc((size_t)nVars * sizeof (varDesc[0]));
   for (int varIdx = 0; varIdx < nVars; varIdx++ )
     {
-      int varLevs = random()%4;
+      int varLevs = (int)random()%4;
       switch (varLevs)
         {
         case 1:
@@ -182,9 +184,10 @@ modelRun(struct model_config setup, MPI_Comm comm)
         = zaxisCreate(ZAXIS_PRESSURE, varDesc[varIdx].nlev);
       zaxisDefLevels(varDesc[varIdx].zaxisID, levs);
       zaxisIDset:
-      varDesc[varIdx].id = vlistDefVar(vlistID, gridID, varDesc[varIdx].zaxisID,
-                                       TIME_VARIABLE);
-      varDesc[varIdx].size = nlon * nlat * varDesc[varIdx].nlev;
+      varDesc[varIdx].id
+        = vlistDefVar(vlistID, gridID, varDesc[varIdx].zaxisID, TIME_VARIABLE);
+      varDesc[varIdx].size
+        = (size_t)nlon * (size_t)nlat * (size_t)varDesc[varIdx].nlev;
 #ifdef USE_MPI
       {
         int start[2], chunkSize[3], varSize[2] = { nlon, nlat };
@@ -378,8 +381,9 @@ modelRun(struct model_config setup, MPI_Comm comm)
                 uint32_t cksum;
                 int code;
                 cksum = memcrc_finish(&varDesc[i].checksum_state,
-                                      (off_t)varDesc[i].size
-                                      * sizeof (var[0]) * setup.nts);
+                                      (off_t)(varDesc[i].size
+                                              * sizeof (var[0])
+                                              * (size_t)setup.nts));
                 code = vlistInqVarCode(vlistID, varDesc[i].id);
                 if (fprintf(tablefp, "%08lx %d\n", (unsigned long)cksum,
                             code) < 0)
diff --git a/libcdi/tests/ensure_array_size.c b/libcdi/tests/ensure_array_size.c
index 2eb1b5b..f7e59aa 100644
--- a/libcdi/tests/ensure_array_size.c
+++ b/libcdi/tests/ensure_array_size.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include "ensure_array_size.h"
diff --git a/libcdi/tests/simple_model.c b/libcdi/tests/simple_model.c
index ccaed23..854b816 100644
--- a/libcdi/tests/simple_model.c
+++ b/libcdi/tests/simple_model.c
@@ -45,9 +45,9 @@ modelRegionCompute(double region[], size_t offset, size_t len,
   for (local_pos = 0; local_pos < len; ++local_pos)
     {
       size_t global_pos = offset + local_pos;
-      int k = global_pos / (nlon * nlat);
-      int j = (global_pos % (nlon * nlat))/ nlon;
-      int i = global_pos % nlon;
+      int k = (int)(global_pos / (size_t)(nlon * nlat));
+      int j = (int)(global_pos % (size_t)(nlon * nlat) / (size_t)nlon);
+      int i = (int)(global_pos % (size_t)nlon);
       region[local_pos]
         = sign_flat(round((cos(2.0 * M_PI * (lons[(i + tsID)%nlon] - lons[0])
                                / (lons[nlon-1] - lons[0]))
@@ -105,26 +105,26 @@ modelRun(struct model_config setup, MPI_Comm comm)
   gridID = gridCreate ( GRID_LONLAT, nlon*nlat );
   gridDefXsize ( gridID, nlon );
   gridDefYsize ( gridID, nlat );
-  lons = xmalloc(nlon * sizeof (lons[0]));
+  lons = xmalloc((size_t)nlon * sizeof (lons[0]));
   for (i = 0; i < nlon; ++i)
     lons[i] = ((double)(i * 360))/nlon;
-  lats = xmalloc(nlat * sizeof (lats[0]));
+  lats = xmalloc((size_t)nlat * sizeof (lats[0]));
   for (i = 0; i < nlat; ++i)
     lats[i] = ((double)(i * 180))/nlat - 90.0;
   gridDefXvals ( gridID, lons );
   gridDefYvals ( gridID, lats );
 
-  levs = xmalloc(setup.max_nlev * sizeof (levs[0]));
+  levs = xmalloc((size_t)setup.max_nlev * sizeof (levs[0]));
   for (i = 0; i < setup.max_nlev; ++i)
     levs[i] = 101300.0
       - 3940.3 * (exp(1.3579 * (double)(i)/(setup.max_nlev - 1)) - 1.0);
 
   vlistID = vlistCreate ();
 
-  varDesc = xmalloc(nVars * sizeof (varDesc[0]));
+  varDesc = xmalloc((size_t)nVars * sizeof (varDesc[0]));
   for (int varIdx = 0; varIdx < nVars; varIdx++ )
     {
-      int varLevs = random()%4;
+      int varLevs = (int)random()%4;
       switch (varLevs)
         {
         case 1:
@@ -149,9 +149,10 @@ modelRun(struct model_config setup, MPI_Comm comm)
         = zaxisCreate(ZAXIS_PRESSURE, varDesc[varIdx].nlev);
       zaxisDefLevels(varDesc[varIdx].zaxisID, levs);
       zaxisIDset:
-      varDesc[varIdx].id = vlistDefVar(vlistID, gridID, varDesc[varIdx].zaxisID,
-                                       TIME_VARIABLE);
-      varDesc[varIdx].size = nlon * nlat * varDesc[varIdx].nlev;
+      varDesc[varIdx].id
+        = vlistDefVar(vlistID, gridID, varDesc[varIdx].zaxisID, TIME_VARIABLE);
+      varDesc[varIdx].size
+        = (size_t)nlon * (size_t)nlat * (size_t)varDesc[varIdx].nlev;
 #ifdef USE_MPI
       {
         struct PPM_extent range
@@ -213,15 +214,15 @@ modelRun(struct model_config setup, MPI_Comm comm)
               int start = varDesc[varID].start;
               int chunk = varDesc[varID].chunkSize;
 #else
-              int chunk = varDesc[varID].size;
+              int chunk = (int)varDesc[varID].size;
               int start = 0;
 #endif
               if (varslice_size < chunk)
                 {
-                  varslice = xrealloc(varslice, chunk * sizeof (var[0]));
-                  varslice_size = chunk;
+                  varslice = xrealloc(varslice, (size_t)chunk * sizeof (var[0]));
+                  varslice_size = (size_t)chunk;
                 }
-              modelRegionCompute(varslice, start, chunk,
+              modelRegionCompute(varslice, (size_t)start, (size_t)chunk,
                                  varDesc[varID].nlev, nlat, nlon,
                                  tsID, lons, lats,
                                  mscale, mrscale);
@@ -276,8 +277,9 @@ modelRun(struct model_config setup, MPI_Comm comm)
                 uint32_t cksum;
                 int code;
                 cksum = memcrc_finish(&varDesc[i].checksum_state,
-                                      (off_t)varDesc[i].size
-                                      * sizeof (var[0]) * setup.nts);
+                                      (off_t)(varDesc[i].size
+                                              * sizeof (var[0])
+                                              * (size_t)setup.nts));
                 code = vlistInqVarCode(vlistID, varDesc[i].id);
                 if (fprintf(tablefp, "%08lx %d\n", (unsigned long)cksum,
                             code) < 0)
diff --git a/libcdi/tests/simple_model_helper.c b/libcdi/tests/simple_model_helper.c
index 9e92d1b..9947774 100644
--- a/libcdi/tests/simple_model_helper.c
+++ b/libcdi/tests/simple_model_helper.c
@@ -40,7 +40,7 @@ var_scale(int datatype, double *mscale, double *mrscale)
               datatype);
       exit(EXIT_FAILURE);
     }
-  *mscale = INT64_C(1) << mant_bits;
+  *mscale = (double)(INT64_C(1) << mant_bits);
   *mrscale = 1.0 / *mscale;
 }
 
diff --git a/libcdi/tests/stream_cksum.c b/libcdi/tests/stream_cksum.c
index 0ee33d5..005a97c 100644
--- a/libcdi/tests/stream_cksum.c
+++ b/libcdi/tests/stream_cksum.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include <stdio.h>
 
 #include "cdi.h"
@@ -45,8 +49,8 @@ cksum_stream(const char *fname, size_t *table_len)
         nvars = -1;
         break;
       }
-    checksum_state = xcalloc(nvars, sizeof (checksum_state[0]));
-    varSize = xmalloc(nvars * sizeof (varSize[0]));
+    checksum_state = xcalloc((size_t)nvars, sizeof (checksum_state[0]));
+    varSize = xmalloc((size_t)nvars * sizeof (varSize[0]));
 
     for (i = 0; i < nvars; ++i)
       {
@@ -86,8 +90,8 @@ cksum_stream(const char *fname, size_t *table_len)
           break;
         }
       if (varSize[i].y == 0) varSize[i].y = 1;
-      varSize[i].chars = (size_t)varSize[i].x * varSize[i].y * varSize[i].z
-        * sizeof (buf[0]);
+      varSize[i].chars = (size_t)varSize[i].x * (size_t)varSize[i].y
+        * (size_t)varSize[i].z * sizeof (buf[0]);
       if (var_size_max_chars < varSize[i].chars)
         var_size_max_chars = varSize[i].chars;
     }
@@ -118,7 +122,7 @@ cksum_stream(const char *fname, size_t *table_len)
         ++tsID;
       }
 
-    file_vars = xmalloc(nvars * sizeof (file_vars[0]));
+    file_vars = xmalloc((size_t)nvars * sizeof (file_vars[0]));
     for (i = 0; i < nvars; ++i)
       {
         file_vars[i].code = vlistInqVarCode(vlistID, i);
@@ -134,7 +138,7 @@ cksum_stream(const char *fname, size_t *table_len)
   free(checksum_state);
   free(varSize);
   free(buf);
-  *table_len = nvars;
+  *table_len = (size_t)nvars;
 
   return file_vars;
 }
diff --git a/libcdi/tests/test_f2003.in b/libcdi/tests/test_f2003.in
new file mode 100644
index 0000000..cbca2d7
--- /dev/null
+++ b/libcdi/tests/test_f2003.in
@@ -0,0 +1,69 @@
+#! @SHELL@
+
+set -e
+format=nc
+if [ @ENABLE_NETCDF@ = yes -a @ENABLE_F2003_ISOC@ = yes ]; then
+  exec >test_f2003_$format.log 2>&1
+  @abs_top_builddir@/examples/cdi_write_f2003
+  @abs_top_builddir@/examples/cdi_read_f2003 \
+    >cdi_read_f2003.$$.stdout \
+    2>cdi_read_f2003.$$.stderr
+  echo "$0"
+  exec 5<cdi_read_f2003.$$.stdout 6<cdi_read_f2003.$$.stderr 7<"$0"
+  while read pattern <&7 ; do
+    [ "$pattern" != "#PATTERNS" ] || break
+  done
+  saved_IFS=$IFS
+  IFS=''
+  while read line <&6 ; do
+    read pattern <&7
+    pattern=`echo "$pattern" | sed -e 's/^#//'`
+    echo "$line" | grep "$pattern"
+  done
+  while read line <&5 ; do
+    read pattern <&7
+    pattern=`echo "$pattern" | sed -e 's/^#//'`
+    echo "$line" | grep "$pattern"
+  done
+  read pattern <&7
+  [ "$pattern" = '#END PATTERNS' ]
+  exec 5<&- 6<&-
+  \rm cdi_read_f2003.$$.stdout cdi_read_f2003.$$.stderr
+  \rm test_f2003_$format.log
+else
+  # skip tests for unsupported formats
+  exit 77
+fi
+
+#PATTERNS
+#^cdi version: @VERSION@ of [A-Z][a-z][a-z]  *[0-9][0-9]*  *[0-9][0-9]*  *[0-9][0-9]\\{0,1\\}:[0-9][0-9]\\{0,1\\}:[0-9][0-9]\\{0,1\\}$
+#^Parameter:  *1  *-1  *varname1  *\\|$
+#^Parameter:  *2  *-2  *varname2  *\\|$
+#^Timestep:  *1  *19850101  *120000$
+#^  *var=  *1  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *2:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *3:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *4:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *5:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^Timestep:  *2  *19850102  *120000$
+#^  *var=  *1  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *2:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *3:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *4:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *5:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^Timestep:  *3  *19850103  *120000$
+#^  *var=  *1  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *1:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *2:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *3:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *4:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#^  *var=  *2  *level=  *5:  *[0-9]*.[0-9]*  *[0-9]*.[0-9]*
+#END PATTERNS
+
+#
+# Local Variables:
+# mode: sh
+# End:
+#
diff --git a/libcdi/tests/test_grib.c b/libcdi/tests/test_grib.c
index bd5e112..30c8256 100644
--- a/libcdi/tests/test_grib.c
+++ b/libcdi/tests/test_grib.c
@@ -1,36 +1,39 @@
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "cdi.h"
+#include "dmemory.h"
 
 int main(int argc, char *argv[])
 {
   char fname[] = "test.grb";
   int filetype = FILETYPE_GRB;
-  int nlat = 18, nlon = 2*nlat;
+  enum {
+    nlat = 18,
+    nlon = 2*nlat,
+  };
   double *data = NULL;
-  double missval;
   int nlevel;
   int varID;
-  int datasize = 0;
   int streamID1, streamID2;
-  int gridID, zaxisID, code, vdate, vtime;
+  int gridID, zaxisID;
   int nrecs, nvars;
-  int gridtype, gridsize = 0;
   int tsID;
-  int timeID = 0;
-  int level, levelID;
-  int offset;
+  int levelID;
   int vlistID, taxisID;
   int nmiss;
 
 
-  datasize = nlon * nlat;
-  data = (double *) malloc(datasize*sizeof(double));
-  memset(data, 0, datasize*sizeof(double));
+  size_t datasize = (size_t)nlon * (size_t)nlat;
+  data = (double *)xmalloc(datasize * sizeof (double));
+  memset(data, 0, datasize * sizeof (double));
 
-  gridID = gridCreate(GRID_GAUSSIAN, datasize);
+  gridID = gridCreate(GRID_GAUSSIAN, (int)datasize);
   gridDefXsize(gridID, nlon);
   gridDefYsize(gridID, nlat);
 
@@ -76,14 +79,14 @@ int main(int argc, char *argv[])
 
   for ( varID = 0; varID < nvars; varID++ )
     {
-      gridID   = vlistInqVarGrid(vlistID, varID);
-      zaxisID  = vlistInqVarZaxis(vlistID, varID);
-      gridsize = gridInqSize(gridID);
-      nlevel   = zaxisInqSize(zaxisID);
+      int gridID      = vlistInqVarGrid(vlistID, varID);
+      int zaxisID     = vlistInqVarZaxis(vlistID, varID);
+      size_t gridsize = (size_t)gridInqSize(gridID);
+      size_t nlevel   = (size_t)zaxisInqSize(zaxisID);
       if ( gridsize*nlevel > datasize ) datasize = gridsize*nlevel;
     }
 
-  data = (double *) malloc(datasize*sizeof(double));
+  data = (double *)xrealloc(data, datasize*sizeof(double));
   memset(data, 0, datasize*sizeof(double));
 
   taxisID = vlistInqTaxis(vlistID);
@@ -91,8 +94,8 @@ int main(int argc, char *argv[])
   tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
     {
-      vdate = taxisInqVdate(taxisID);
-      vtime = taxisInqVtime(taxisID);
+      /* int vdate =  */taxisInqVdate(taxisID);
+      /* int vtime =  */taxisInqVtime(taxisID);
 
       streamDefTimestep(streamID2, tsID);
 
@@ -100,18 +103,18 @@ int main(int argc, char *argv[])
 	{
 	  streamReadVar(streamID1, varID, data, &nmiss);
 
-	  code     = vlistInqVarCode(vlistID, varID);
+	  /* int code = */vlistInqVarCode(vlistID, varID);
 	  gridID   = vlistInqVarGrid(vlistID, varID);
 	  zaxisID  = vlistInqVarZaxis(vlistID, varID);
-	  gridtype = gridInqType(gridID);
-	  gridsize = gridInqSize(gridID);
+	  /* int gridtype = */gridInqType(gridID);
+	  /* int gridsize = */gridInqSize(gridID);
 	  nlevel   = zaxisInqSize(zaxisID);
-	  missval  = vlistInqVarMissval(vlistID, varID);
+	  /* double missval = */vlistInqVarMissval(vlistID, varID);
 
 	  for ( levelID = 0; levelID < nlevel; levelID++ )
 	    {
-	      level  = (int) zaxisInqLevel(zaxisID, levelID);
-	      offset = gridsize*levelID;
+	      /* int level  = (int) */ zaxisInqLevel(zaxisID, levelID);
+	      /* int offset = gridsize*levelID; */
 	    }
 
 	  streamWriteVar(streamID2, varID, data, nmiss);
diff --git a/libcdi/tests/test_resource_copy.c b/libcdi/tests/test_resource_copy.c
index 59e5ec4..c15e738 100644
--- a/libcdi/tests/test_resource_copy.c
+++ b/libcdi/tests/test_resource_copy.c
@@ -157,6 +157,11 @@ int defineVlist ( int gridID, int zaxisID, int taxisID )
   vlistDefVarName(vlistID, varID2, "varname2");
   vlistDefAttTxt(vlistID, varID2, "txt demo", 6, "banana");
   vlistDefTaxis(vlistID, taxisID);
+  int vlistID2 = vlistCreate();
+  vlistDefVar(vlistID2, gridID, zaxisID, TIME_VARIABLE);
+  vlistCopy(vlistID2, vlistID);
+  vlistDestroy(vlistID);
+  vlistID = vlistID2;
   return vlistID;
 }
 
@@ -202,13 +207,13 @@ int modelRun(MPI_Comm comm)
   defineStream ( streamID, vlistID );
 
   reshPackBufferCreate ( &sendBuffer, &bufferSize, &comm );
-  recvBuffer = xmalloc(bufferSize);
+  recvBuffer = xmalloc((size_t)bufferSize);
 #ifdef MPI_MARSHALLING
   xmpi(MPI_Sendrecv(sendBuffer, bufferSize, MPI_PACKED, 0, 0,
                     recvBuffer, bufferSize, MPI_PACKED, 0, 0,
                     MPI_COMM_SELF, MPI_STATUS_IGNORE));
 #else
-  memcpy(recvBuffer, sendBuffer, bufferSize);
+  memcpy(recvBuffer, sendBuffer, (size_t)bufferSize);
 #endif
   namespaceSetActive(destNamespace);
   reshUnpackResources(recvBuffer, bufferSize, &comm);
diff --git a/m4/._ax_pthread.m4 b/m4/._ax_pthread.m4
new file mode 100644
index 0000000..224412c
Binary files /dev/null and b/m4/._ax_pthread.m4 differ
diff --git a/m4/acx_options.m4 b/m4/acx_options.m4
index c12dd1a..37f61fa 100644
--- a/m4/acx_options.m4
+++ b/m4/acx_options.m4
@@ -319,10 +319,10 @@ AC_SUBST([ENABLE_IEG],[$enable_ieg])
 #  Compile with fftw support
 AC_MSG_CHECKING([for FFTW3 support])
 AC_ARG_WITH([fftw3],
-    [AS_HELP_STRING([--without-fftw3],
-      [disable support for fftw3])],
+    [AS_HELP_STRING([--with-fftw3],
+      [enable support for fftw3])],
     [],
-    [with_fftw3=yes])
+    [with_fftw3=no])
 
   AS_IF([test "x$with_fftw3" != xno],
       [AC_CHECK_HEADERS([fftw3.h])
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
index 4ecd9c6..d383ad5 100644
--- a/m4/ax_pthread.m4
+++ b/m4/ax_pthread.m4
@@ -33,6 +33,10 @@
 #   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
 #   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
 #
+#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+#   PTHREAD_CFLAGS.
+#
 #   ACTION-IF-FOUND is a list of shell commands to run if a threads library
 #   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
 #   is not found. If ACTION-IF-FOUND is not specified, the default action
@@ -45,9 +49,12 @@
 #   Alejandro Forero Cuervo to the autoconf macro repository. We are also
 #   grateful for the helpful feedback of numerous users.
 #
+#   Updated for Autoconf 2.68 by Daniel Richard G.
+#
 # LICENSE
 #
 #   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2011 Daniel Richard G. <skunk at iSKUNK.ORG>
 #
 #   This program is free software: you can redistribute it and/or modify it
 #   under the terms of the GNU General Public License as published by the
@@ -75,13 +82,12 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 11
+#serial 21
 
 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
 AC_DEFUN([AX_PTHREAD], [
 AC_REQUIRE([AC_CANONICAL_HOST])
-AC_LANG_SAVE
-AC_LANG_C
+AC_LANG_PUSH([C])
 ax_pthread_ok=no
 
 # We used to check for pthread.h first, but this fails if pthread.h
@@ -97,8 +103,8 @@ if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
         save_LIBS="$LIBS"
         LIBS="$PTHREAD_LIBS $LIBS"
         AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
-        AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
-        AC_MSG_RESULT($ax_pthread_ok)
+        AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
+        AC_MSG_RESULT([$ax_pthread_ok])
         if test x"$ax_pthread_ok" = xno; then
                 PTHREAD_LIBS=""
                 PTHREAD_CFLAGS=""
@@ -139,8 +145,8 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
 # --thread-safe: KAI C++
 # pthread-config: use pthread-config program (for GNU Pth library)
 
-case "${host_cpu}-${host_os}" in
-        *solaris*)
+case ${host_os} in
+        solaris*)
 
         # On Solaris (at least, for some versions), libc contains stubbed
         # (non-functional) versions of the pthreads routines, so link-based
@@ -153,11 +159,25 @@ case "${host_cpu}-${host_os}" in
         ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
         ;;
 
-	*-darwin*)
-	ax_pthread_flags="-pthread $ax_pthread_flags"
-	;;
+        darwin*)
+        ax_pthread_flags="-pthread $ax_pthread_flags"
+        ;;
 esac
 
+# Clang doesn't consider unrecognized options an error unless we specify
+# -Werror. We throw in some extra Clang-specific options to ensure that
+# this doesn't happen for GCC, which also accepts -Werror.
+
+AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
+save_CFLAGS="$CFLAGS"
+ax_pthread_extra_flags="-Werror"
+CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
+                  [AC_MSG_RESULT([yes])],
+                  [ax_pthread_extra_flags=
+                   AC_MSG_RESULT([no])])
+CFLAGS="$save_CFLAGS"
+
 if test x"$ax_pthread_ok" = xno; then
 for flag in $ax_pthread_flags; do
 
@@ -171,12 +191,12 @@ for flag in $ax_pthread_flags; do
                 PTHREAD_CFLAGS="$flag"
                 ;;
 
-		pthread-config)
-		AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
-		if test x"$ax_pthread_config" = xno; then continue; fi
-		PTHREAD_CFLAGS="`pthread-config --cflags`"
-		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-		;;
+                pthread-config)
+                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+                if test x"$ax_pthread_config" = xno; then continue; fi
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
 
                 *)
                 AC_MSG_CHECKING([for the pthreads library -l$flag])
@@ -187,7 +207,7 @@ for flag in $ax_pthread_flags; do
         save_LIBS="$LIBS"
         save_CFLAGS="$CFLAGS"
         LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
 
         # Check for various functions.  We must include pthread.h,
         # since some functions may be macros.  (On the Sequent, we
@@ -198,21 +218,22 @@ for flag in $ax_pthread_flags; do
         # pthread_cleanup_push because it is one of the few pthread
         # functions on Solaris that doesn't have a non-functional libc stub.
         # We try pthread_create on general principles.
-        AC_TRY_LINK([#include <pthread.h>
-		     static void routine(void* a) {a=0;}
-		     static void* start_routine(void* a) {return a;}],
-                    [pthread_t th; pthread_attr_t attr;
-                     pthread_create(&th,0,start_routine,0);
-                     pthread_join(th, 0);
-                     pthread_attr_init(&attr);
-                     pthread_cleanup_push(routine, 0);
-                     pthread_cleanup_pop(0); ],
-                    [ax_pthread_ok=yes])
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+                [ax_pthread_ok=yes],
+                [])
 
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        AC_MSG_RESULT($ax_pthread_ok)
+        AC_MSG_RESULT([$ax_pthread_ok])
         if test "x$ax_pthread_ok" = xyes; then
                 break;
         fi
@@ -230,54 +251,82 @@ if test "x$ax_pthread_ok" = xyes; then
         CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
 
         # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-	AC_MSG_CHECKING([for joinable pthread attribute])
-	attr_name=unknown
-	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
-                        [attr_name=$attr; break])
-	done
-        AC_MSG_RESULT($attr_name)
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        attr_name=unknown
+        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+            AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                           [int attr = $attr; return attr /* ; */])],
+                [attr_name=$attr; break],
+                [])
+        done
+        AC_MSG_RESULT([$attr_name])
         if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
-            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+            AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
                                [Define to necessary symbol if this constant
                                 uses a non-standard name on your system.])
         fi
 
         AC_MSG_CHECKING([if more special flags are required for pthreads])
         flag=no
-        case "${host_cpu}-${host_os}" in
-            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        case ${host_os} in
+            aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+            osf* | hpux*) flag="-D_REENTRANT";;
+            solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                # TODO: What about Clang on Solaris?
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
-        AC_MSG_RESULT(${flag})
+        AC_MSG_RESULT([$flag])
         if test "x$flag" != xno; then
             PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
         fi
 
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            [ax_cv_PTHREAD_PRIO_INHERIT], [
+                AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+                                                [[int i = PTHREAD_PRIO_INHERIT;]])],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+            [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
+
         LIBS="$save_LIBS"
         CFLAGS="$save_CFLAGS"
 
-        # More AIX lossage: must compile with xlc_r or cc_r
-	if test x"$GCC" != xyes -a \( x"$CC" = xxlc -o x"$CC" = cc \) ; then
-          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
-        else
-          PTHREAD_CC=$CC
-	fi
-else
-        PTHREAD_CC="$CC"
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != xyes; then
+            case $host_os in
+                aix*)
+                AS_CASE(["x/$CC"],
+                  [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+                  [#handle absolute path differently from PATH based program lookup
+                   AS_CASE(["x$CC"],
+                     [x/*],
+                     [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+                     [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+                ;;
+            esac
+        fi
 fi
 
-AC_SUBST(PTHREAD_LIBS)
-AC_SUBST(PTHREAD_CFLAGS)
-AC_SUBST(PTHREAD_CC)
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
 
 # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
 if test x"$ax_pthread_ok" = xyes; then
-        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
         :
 else
         ax_pthread_ok=no
         $2
 fi
-AC_LANG_RESTORE
+AC_LANG_POP
 ])dnl AX_PTHREAD
diff --git a/src/Cat.c b/src/Cat.c
index 02b7c8f..56a4e1a 100644
--- a/src/Cat.c
+++ b/src/Cat.c
@@ -40,18 +40,24 @@ void *Cat(void *argument)
   int gridsize;
   int nmiss;
   int ntsteps, nvars;
+  int timer_cat;
+  double tw0 = 0, tw = 0;
   double *array = NULL;
 
   cdoInitialize(argument);
 
   if ( UNCHANGED_RECORD ) lcopy = TRUE;
 
+  timer_cat = timer_new("cat");
+  if ( cdoTimer ) timer_start(timer_cat);
+
   streamCnt = cdoStreamCnt();
   nfiles = streamCnt - 1;
 
   for ( indf = 0; indf < nfiles; indf++ )
     {
       if ( cdoVerbose ) cdoPrint("Process file: %s", cdoStreamName(indf)->args);
+      if ( cdoTimer ) tw0 = timer_val(timer_cat);
 
       streamID1 = streamOpenRead(cdoStreamName(indf));
 
@@ -60,7 +66,10 @@ void *Cat(void *argument)
 
       if ( indf == 0 )
 	{
-	  if ( fileExists(cdoStreamName(nfiles)->args) )
+	  int file_exists = fileExists(cdoStreamName(nfiles)->args);
+	  if ( cdoOverwriteMode ) file_exists = 0;
+
+	  if ( file_exists )
 	    {
 	      streamID2 = streamOpenAppend(cdoStreamName(nfiles));
 
@@ -114,9 +123,17 @@ void *Cat(void *argument)
 	  vlistCompare(vlistID1, vlistID2, CMP_ALL);
 	}
 
+      int ntsteps = vlistNtsteps(vlistID1);
+
       tsID1 = 0;
       while ( (nrecs = streamInqTimestep(streamID1, tsID1)) )
 	{
+	  {
+	    double fstatus = indf+1.;
+	    if ( ntsteps > 1 ) fstatus = indf+(tsID1+1.)/ntsteps;
+	    if ( !cdoVerbose ) progressStatus(0, 1, fstatus/nfiles);
+	  }
+
 	  taxisCopyTimestep(taxisID2, taxisID1);
 
 	  streamDefTimestep(streamID2, tsID2);
@@ -136,14 +153,20 @@ void *Cat(void *argument)
 		  streamWriteRecord(streamID2, array, nmiss);
 		}
 	    }
+
 	  tsID1++;
 	  tsID2++;
 	}
       streamClose(streamID1);
+
+      if ( cdoTimer ) tw = timer_val(timer_cat) - tw0;
+      if ( cdoTimer ) cdoPrint("Processed file: %s   %.2f seconds", cdoStreamName(indf)->args, tw);
     }
 
   streamClose(streamID2);
  
+  if ( cdoTimer ) timer_stop(timer_cat);
+
   if ( array ) free(array);
 
   cdoFinish();
diff --git a/src/Gather.c b/src/Collgrid.c
similarity index 61%
rename from src/Gather.c
rename to src/Collgrid.c
index 293b93e..a904873 100644
--- a/src/Gather.c
+++ b/src/Collgrid.c
@@ -42,8 +42,8 @@ static
 int cmpx(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const xyinfo_t *xy1 = s1;
-  const xyinfo_t *xy2 = s2;
+  const xyinfo_t *xy1 = (const xyinfo_t *) s1;
+  const xyinfo_t *xy2 = (const xyinfo_t *) s2;
 
   if      ( xy1->x < xy2->x ) cmp = -1;
   else if ( xy1->x > xy2->x ) cmp =  1;
@@ -55,8 +55,8 @@ static
 int cmpxy_lt(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const xyinfo_t *xy1 = s1;
-  const xyinfo_t *xy2 = s2;
+  const xyinfo_t *xy1 = (const xyinfo_t *) s1;
+  const xyinfo_t *xy2 = (const xyinfo_t *) s2;
 
   if      ( xy1->y < xy2->y || (!(fabs(xy1->y - xy2->y) > 0) && xy1->x < xy2->x) ) cmp = -1;
   else if ( xy1->y > xy2->y || (!(fabs(xy1->y - xy2->y) > 0) && xy1->x > xy2->x) ) cmp =  1;
@@ -68,8 +68,8 @@ static
 int cmpxy_gt(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const xyinfo_t *xy1 = s1;
-  const xyinfo_t *xy2 = s2;
+  const xyinfo_t *xy1 = (const xyinfo_t *) s1;
+  const xyinfo_t *xy2 = (const xyinfo_t *) s2;
 
   if      ( xy1->y > xy2->y || (!(fabs(xy1->y - xy2->y) > 0) && xy1->x < xy2->x) ) cmp = -1;
   else if ( xy1->y < xy2->y || (!(fabs(xy1->y - xy2->y) > 0) && xy1->x > xy2->x) ) cmp =  1;
@@ -137,17 +137,17 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid)
 	  if ( yvals[fileID][0] > yvals[fileID][ysize[fileID]-1] ) lsouthnorth = FALSE;
 	}
     }
-  
+  /*
   if ( cdoVerbose )
     for ( fileID = 0; fileID < nfiles; fileID++ )
       printf("1 %d %g %g \n",  xyinfo[fileID].id, xyinfo[fileID].x, xyinfo[fileID].y);
-  
+  */
   qsort(xyinfo, nfiles, sizeof(xyinfo_t), cmpx);  	      
-  
+  /*
   if ( cdoVerbose )
     for ( fileID = 0; fileID < nfiles; fileID++ )
       printf("2 %d %g %g \n",  xyinfo[fileID].id, xyinfo[fileID].x, xyinfo[fileID].y);
-  
+  */
   if ( lsouthnorth )
     qsort(xyinfo, nfiles, sizeof(xyinfo_t), cmpxy_lt);  
   else
@@ -165,7 +165,8 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid)
     }
   ny = nfiles/nx;
   if ( cdoVerbose ) cdoPrint("nx %d  ny %d", nx, ny);
-
+  if ( nx*ny != nfiles ) cdoAbort("Number of input files (%d) seems to be incomplete!", nfiles);
+ 
   xsize2 = 0;
   for ( i = 0; i < nx; ++i ) xsize2 += xsize[xyinfo[i].id];
   ysize2 = 0;
@@ -229,23 +230,21 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid)
   free(xvals2);
   free(yvals2);
 
-  {
-    char string[1024];
-    string[0] = 0;
-    gridID = vlistGrid(ef[0].vlistID, igrid);
-    gridInqXname(gridID, string);
-    gridDefXname(gridID2, string);
-    gridInqYname(gridID, string);
-    gridDefYname(gridID2, string);
-    gridInqXlongname(gridID, string);
-    gridDefXlongname(gridID2, string);
-    gridInqYlongname(gridID, string);
-    gridDefYlongname(gridID2, string);
-    gridInqXunits(gridID, string);
-    gridDefXunits(gridID2, string);
-    gridInqYunits(gridID, string);
-    gridDefYunits(gridID2, string);
-  }
+  char string[1024];
+  string[0] = 0;
+  gridID = vlistGrid(ef[0].vlistID, igrid);
+  gridInqXname(gridID, string);
+  gridDefXname(gridID2, string);
+  gridInqYname(gridID, string);
+  gridDefYname(gridID2, string);
+  gridInqXlongname(gridID, string);
+  gridDefXlongname(gridID2, string);
+  gridInqYlongname(gridID, string);
+  gridDefYlongname(gridID2, string);
+  gridInqXunits(gridID, string);
+  gridDefXunits(gridID2, string);
+  gridInqYunits(gridID, string);
+  gridDefYunits(gridID2, string);
 
   for ( fileID = 0; fileID < nfiles; fileID++ )
     {
@@ -260,71 +259,99 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid)
 }
 
 
-void *Gather(void *argument)
+void *Collgrid(void *argument)
 {
-  int i;
-  int nvars;
-  int cmpfunc;
   int varID, recID;
-  int gridsize = 0;
-  int gridsizemax = 0;
-  int gridsize2;
-  int *gridIDs = NULL;
-  int *vars = NULL;
   int nrecs, nrecs0;
-  int ngrids;
   int levelID;
-  int tsID;
-  int streamID = 0, streamID2;
-  int vlistID, vlistID1, vlistID2;
   int nmiss;
   int taxisID1, taxisID2;
-  int **gridindex;
   double missval;
-  double *array2 = NULL;
-  int fileID, nfiles;
-  const char *ofilename;
-  ens_file_t *ef = NULL;
+  int fileID;
 
   cdoInitialize(argument);
     
-  nfiles = cdoStreamCnt() - 1;
-
-  ofilename = cdoStreamName(nfiles)->args;
+  int nfiles = cdoStreamCnt() - 1;
+  const char *ofilename = cdoStreamName(nfiles)->args;
 
   if ( !cdoSilentMode && !cdoOverwriteMode )
     if ( fileExists(ofilename) )
       if ( !userFileOverwrite(ofilename) )
 	cdoAbort("Outputfile %s already exists!", ofilename);
 
-  ef = (ens_file_t*) malloc(nfiles*sizeof(ens_file_t));
+  ens_file_t *ef = (ens_file_t*) malloc(nfiles*sizeof(ens_file_t));
 
   for ( fileID = 0; fileID < nfiles; fileID++ )
     {
-      streamID = streamOpenRead(cdoStreamName(fileID));
+      ef[fileID].streamID = streamOpenRead(cdoStreamName(fileID));
+      ef[fileID].vlistID  = streamInqVlist(ef[fileID].streamID);
+    }
 
-      vlistID = streamInqVlist(streamID);
+  int vlistID1 = ef[0].vlistID;
+  vlistClearFlag(vlistID1);
 
-      ef[fileID].streamID = streamID;
-      ef[fileID].vlistID  = vlistID;
-    }
+  /* check that the contents is always the same */
+  for ( fileID = 1; fileID < nfiles; fileID++ )
+    vlistCompare(vlistID1, ef[fileID].vlistID, CMP_NAME | CMP_NLEVEL);
 
-  nvars = vlistNvars(ef[0].vlistID);
-  vars  = (int*) malloc(nvars*sizeof(int));
+  int nvars = vlistNvars(vlistID1);
+  int *vars  = (int*) malloc(nvars*sizeof(int));
   for ( varID = 0; varID < nvars; varID++ ) vars[varID] = FALSE;
+  int *vars1  = (int*) malloc(nvars*sizeof(int));
+  for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = FALSE;
 
-  /* check that the contents is always the same */
-  if ( nvars == 1 ) 
-    cmpfunc = CMP_NAME | CMP_NLEVEL;
+  int nsel = operatorArgc();
+  if ( nsel == 0 )
+    {
+      for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = TRUE;
+    }
   else
-    cmpfunc = CMP_NAME | CMP_NLEVEL;
+    {
+      char **argnames = operatorArgv();
 
-  for ( fileID = 1; fileID < nfiles; fileID++ )
-    vlistCompare(ef[0].vlistID, ef[fileID].vlistID, cmpfunc);
+      if ( cdoVerbose )
+	for ( int i = 0; i < nsel; i++ )
+	  fprintf(stderr, "name %d = %s\n", i+1, argnames[i]);
 
-  vlistID1 = ef[0].vlistID;
-  gridsizemax = vlistGridsizeMax(vlistID1);
-  for ( fileID = 1; fileID < nfiles; fileID++ )
+      int *selfound = (int*) malloc(nsel*sizeof(int));
+      for ( int i = 0; i < nsel; i++ ) selfound[i] = FALSE;
+
+      char varname[CDI_MAX_NAME];
+      for ( varID = 0; varID < nvars; varID++ )
+	{
+	  vlistInqVarName(vlistID1, varID, varname);
+
+	  for ( int isel = 0; isel < nsel; isel++ )
+	    {
+	      if ( strcmp(argnames[isel], varname) == 0 )
+		{
+		  selfound[isel] = TRUE;
+		  vars1[varID] = TRUE;
+		}
+	    }
+	}
+
+      for ( int isel = 0; isel < nsel; isel++ )
+	if ( selfound[isel] == FALSE )
+	  cdoAbort("Variable name %s not found!", argnames[isel]);
+
+      free(selfound);
+    }
+
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      if ( vars1[varID] == TRUE )
+	{
+	  int zaxisID  = vlistInqVarZaxis(vlistID1, varID);
+	  int nlevs    = zaxisInqSize(zaxisID);
+	  for ( int levID = 0; levID < nlevs; levID++ )
+	    vlistDefFlag(vlistID1, varID, levID, TRUE);
+	}
+    }
+
+  int gridsize;
+  int gridsizemax = 0;
+  for ( fileID = 0; fileID < nfiles; fileID++ )
     {
       gridsize = vlistGridsizeMax(ef[fileID].vlistID);
       if ( gridsize > gridsizemax ) gridsizemax = gridsize;
@@ -334,31 +361,54 @@ void *Gather(void *argument)
   for ( fileID = 0; fileID < nfiles; fileID++ )
     ef[fileID].array = (double*) malloc(gridsizemax*sizeof(double));
 
-  ngrids = vlistNgrids(ef[0].vlistID);
-  gridIDs = (int*) malloc(ngrids*sizeof(int));
-  gridindex = (int **) malloc(nfiles*sizeof(int *));
+
+  int vlistID2 = vlistCreate();
+  vlistCopyFlag(vlistID2, vlistID1);
+  /*
+  if ( cdoVerbose )
+    {
+      vlistPrint(vlistID1);
+      vlistPrint(vlistID2);
+    }
+  */
+  //int vlistID2 = vlistDuplicate(vlistID1);
+  int nvars2 = vlistNvars(vlistID2);
+  // int *vars  = (int*) malloc(nvars*sizeof(int));
+  //for ( varID = 0; varID < nvars; varID++ ) vars[varID] = FALSE;
+
+  int ngrids1 = vlistNgrids(vlistID1);
+  int ngrids2 = vlistNgrids(vlistID2);
+
+  int *gridIDs = (int*) malloc(ngrids2*sizeof(int));
+  int **gridindex = (int **) malloc(nfiles*sizeof(int *));
   for ( fileID = 0; fileID < nfiles; fileID++ )
     gridindex[fileID] = (int*) malloc(gridsizemax*sizeof(int));
 
   int ginit = FALSE;
-  for ( i = 0; i < ngrids; ++i )
+  for ( int i2 = 0; i2 < ngrids2; ++i2 )
     {
+      int i1;
+      for ( i1 = 0; i1 < ngrids1; ++i1 )
+	if ( vlistGrid(vlistID1, i1) == vlistGrid(vlistID2, i2) ) break;
+
+      //   printf("i1 %d i2 %d\n", i1, i2);
+
       if ( ginit == FALSE )
 	{
-	  gridIDs[i] = genGrid(nfiles, ef, gridindex, i);
-	  if ( gridIDs[i] != -1 ) ginit = TRUE;
+	  gridIDs[i2] = genGrid(nfiles, ef, gridindex, i1);
+	  if ( gridIDs[i2] != -1 ) ginit = TRUE;
 	}
       else
-	gridIDs[i] = genGrid(nfiles, ef, NULL, i);
+	gridIDs[i2] = genGrid(nfiles, ef, NULL, i1);
     }
 
-  vlistID2 = vlistDuplicate(vlistID1);
+
   taxisID1 = vlistInqTaxis(vlistID1);
   taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  gridsize2 = 0;
-  for ( i = 0; i < ngrids; ++i )
+  int gridsize2 = 0;
+  for ( int i = 0; i < ngrids2; ++i )
     {
       if ( gridIDs[i] != -1 ) 
 	{
@@ -368,35 +418,34 @@ void *Gather(void *argument)
 	}
     }
 
-  for ( varID = 0; varID < nvars; varID++ )
+  for ( varID = 0; varID < nvars2; varID++ )
     {
-      int gridID = vlistInqVarGrid(ef[0].vlistID, varID);
+      int gridID = vlistInqVarGrid(vlistID2, varID);
 
-      for ( i = 0; i < ngrids; ++i )
+      for ( int i = 0; i < ngrids2; ++i )
 	{
 	  if ( gridIDs[i] != -1 ) 
 	    {
-	      if ( gridID == vlistGrid(ef[0].vlistID, i) )
-	      vars[varID] = TRUE;
+	      if ( gridID == vlistGrid(vlistID2, i) )
+		vars[varID] = TRUE;
 	      break;
 	    }
 	}
     }
 
-  streamID2 = streamOpenWrite(cdoStreamName(nfiles), cdoFiletype());
+  int streamID2 = streamOpenWrite(cdoStreamName(nfiles), cdoFiletype());
       
   streamDefVlist(streamID2, vlistID2);
 	  
-  array2 = (double*) malloc(gridsize2*sizeof(double));
+  double *array2 = (double*) malloc(gridsize2*sizeof(double));
 
-  tsID = 0;
+  int tsID = 0;
   do
     {
       nrecs0 = streamInqTimestep(ef[0].streamID, tsID);
       for ( fileID = 1; fileID < nfiles; fileID++ )
 	{
-	  streamID = ef[fileID].streamID;
-	  nrecs = streamInqTimestep(streamID, tsID);
+	  nrecs = streamInqTimestep(ef[fileID].streamID, tsID);
 	  if ( nrecs != nrecs0 )
 	    cdoAbort("Number of records at time step %d of %s and %s differ!", tsID+1, cdoStreamName(0)->args, cdoStreamName(fileID)->args);
 	}
@@ -407,42 +456,52 @@ void *Gather(void *argument)
       
       for ( recID = 0; recID < nrecs0; recID++ )
 	{
-	  streamID = ef[0].streamID;
-	  streamInqRecord(streamID, &varID, &levelID);
-
-	  missval = vlistInqVarMissval(vlistID1, varID);
-	  for ( i = 0; i < gridsize2; i++ ) array2[i] = missval;
+	  streamInqRecord(ef[0].streamID, &varID, &levelID);
+	  if ( cdoVerbose && tsID == 0 ) printf(" tsID, recID, varID, levelID %d %d %d %d\n", tsID, recID, varID, levelID);
 
-#if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(fileID, streamID, nmiss, i)
-#endif
 	  for ( fileID = 0; fileID < nfiles; fileID++ )
 	    {
 	      int varIDx, levelIDx;
-	      streamID = ef[fileID].streamID;
-	      if ( fileID > 0 ) streamInqRecord(streamID, &varIDx, &levelIDx);
-	      streamReadRecord(streamID, ef[fileID].array, &nmiss);
+	      if ( fileID > 0 ) streamInqRecord(ef[fileID].streamID, &varIDx, &levelIDx);
+	    }
+
+	  if ( vlistInqFlag(vlistID1, varID, levelID) == TRUE )
+	    {
+	      int varID2   = vlistFindVar(vlistID2, varID);
+	      int levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+	      if ( cdoVerbose && tsID == 0 ) printf("varID %d %d levelID %d %d\n", varID, varID2, levelID, levelID2);
+
+	      missval = vlistInqVarMissval(vlistID2, varID2);
+	      for ( int i = 0; i < gridsize2; i++ ) array2[i] = missval;
 
-	      if ( vars[varID] )
+#if defined(_OPENMP)
+#pragma omp parallel for default(shared) private(fileID, nmiss)
+#endif
+	      for ( fileID = 0; fileID < nfiles; fileID++ )
 		{
-		  gridsize = gridInqSize(vlistInqVarGrid(ef[fileID].vlistID, varID));
-		  for ( i = 0; i < gridsize; ++i )
-		    array2[gridindex[fileID][i]] = ef[fileID].array[i];
+		  streamReadRecord(ef[fileID].streamID, ef[fileID].array, &nmiss);
+
+		  if ( vars[varID2] )
+		    {
+		      gridsize = gridInqSize(vlistInqVarGrid(ef[fileID].vlistID, varID));
+		      for ( int i = 0; i < gridsize; ++i )
+			array2[gridindex[fileID][i]] = ef[fileID].array[i];
+		    }
 		}
-	    }
 
-	  streamDefRecord(streamID2, varID, levelID);
+	      streamDefRecord(streamID2, varID2, levelID2);
 
-	  if ( vars[varID] )
-	    {
-	      nmiss = 0;
-	      for ( i = 0; i < gridsize2; i++ )
-		if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
-	      
-	      streamWriteRecord(streamID2, array2, nmiss);
+	      if ( vars[varID2] )
+		{
+		  nmiss = 0;
+		  for ( int i = 0; i < gridsize2; i++ )
+		    if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
+
+		  streamWriteRecord(streamID2, array2, nmiss);
+		}
+	      else
+		streamWriteRecord(streamID2, ef[0].array, 0);
 	    }
-	  else
-	    streamWriteRecord(streamID2, ef[0].array, 0);
 	}
 
       tsID++;
@@ -450,10 +509,7 @@ void *Gather(void *argument)
   while ( nrecs0 > 0 );
 
   for ( fileID = 0; fileID < nfiles; fileID++ )
-    {
-      streamID = ef[fileID].streamID;
-      streamClose(streamID);
-    }
+    streamClose(ef[fileID].streamID);
 
   streamClose(streamID2);
 
@@ -465,6 +521,7 @@ void *Gather(void *argument)
 
   free(gridIDs);
   if ( vars   ) free(vars);
+  if ( vars1  ) free(vars1);
 
   cdoFinish();
 
diff --git a/src/Consecstat.c b/src/Consecstat.c
index 091a12e..e55486c 100644
--- a/src/Consecstat.c
+++ b/src/Consecstat.c
@@ -126,7 +126,6 @@ void *Consecstat(void *argument)
   int ostreamID, otaxisID, ovlistID, otsID;
   int vdate = 0, vtime = 0;
   int histvdate = 0, histvtime = 0;
-  int i;
   int recID, nrecs;
   int varID, nvars;
   int levelID, nlevels; 
@@ -221,7 +220,7 @@ void *Consecstat(void *argument)
           }
 #if defined(_OPENMP)
 #pragma omp parallel for default(shared) schedule(static)
-          for ( i = 0; i < gridInqSize(vars[varID][levelID].grid); i++ )
+          for ( int i = 0; i < gridInqSize(vars[varID][levelID].grid); i++ )
             hist[varID][levelID].ptr[i] = vars[varID][levelID].ptr[i];
 #else
           memcpy(hist[varID][levelID].ptr,
diff --git a/src/Detrend.c b/src/Detrend.c
index da66f25..a57fb37 100644
--- a/src/Detrend.c
+++ b/src/Detrend.c
@@ -21,9 +21,6 @@
       Detrend    detrend         Detrend
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
 
 #include <cdi.h>
 #include "cdo.h"
@@ -94,7 +91,6 @@ void taxisDefDTinfo(int taxisID, dtinfo_t dtinfo)
 
 void *Detrend(void *argument)
 {
-  int ompthID;
   int gridsize;
   int nrecs;
   int gridID, varID, levelID, recID;
@@ -178,15 +174,12 @@ void *Detrend(void *argument)
       for ( levelID = 0; levelID < nlevel; levelID++ )
 	{
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, ompthID, tsID)
+#pragma omp parallel for default(shared) private(i, tsID)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
-#if defined(_OPENMP)
-              ompthID = omp_get_thread_num();
-#else
-              ompthID = 0;
-#endif
+              int ompthID = cdo_omp_get_thread_num();
+
 	      for ( tsID = 0; tsID < nts; tsID++ )
 		ompmem[ompthID].array1[tsID] = vars[tsID][varID][levelID].ptr[i];
 
diff --git a/src/Scatter.c b/src/Distgrid.c
similarity index 99%
rename from src/Scatter.c
rename to src/Distgrid.c
index f349597..d0af9c4 100644
--- a/src/Scatter.c
+++ b/src/Distgrid.c
@@ -117,7 +117,7 @@ typedef struct
 } sgrid_t;
 
 
-void *Scatter(void *argument)
+void *Distgrid(void *argument)
 {
   int nchars;
   int streamID1;
diff --git a/src/Ensstat.c b/src/Ensstat.c
index 86d85b1..6cc8374 100644
--- a/src/Ensstat.c
+++ b/src/Ensstat.c
@@ -30,9 +30,6 @@
       Ensstat    enspctl         Ensemble percentiles
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
 
 #include <cdi.h>
 #include "cdo.h"
@@ -56,7 +53,6 @@ void *Ensstat(void *argument)
   int vlistID, vlistID1, vlistID2;
   int nmiss;
   int taxisID1, taxisID2;
-  int ompthID;
   double missval;
   double *array2 = NULL;
   field_t *field;
@@ -195,15 +191,12 @@ void *Ensstat(void *argument)
 
 	  nmiss = 0;
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, ompthID, fileID)
+#pragma omp parallel for default(shared) private(i, fileID)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
-#if defined(_OPENMP)
-	      ompthID = omp_get_thread_num();
-#else
-	      ompthID = 0;
-#endif
+	      int ompthID = cdo_omp_get_thread_num();
+
 	      field[ompthID].missval = missval;
 	      field[ompthID].nmiss = 0;
 	      for ( fileID = 0; fileID < nfiles; fileID++ )
@@ -221,7 +214,7 @@ void *Ensstat(void *argument)
 	      if ( DBL_IS_EQUAL(array2[i], field[ompthID].missval) )
 		{
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
 		  nmiss++;
 		}
diff --git a/src/Ensstat3.c b/src/Ensstat3.c
index 916bee4..4c2c7e2 100644
--- a/src/Ensstat3.c
+++ b/src/Ensstat3.c
@@ -22,9 +22,6 @@
    Ensstat3       ensroccurve      Ensamble Receiver Operating Characteristics
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
 
 #include <cdi.h>
 #include "cdo.h"
@@ -68,7 +65,6 @@ void *Ensstat3(void *argument)
   int vlistID, vlistID1, vlistID2;
   int taxisID1, taxisID2;
   int zaxisID2;
-  int ompthID;
   int *varID2;
   int time_mode;
   int **array2 = NULL;
@@ -128,13 +124,8 @@ void *Ensstat3(void *argument)
   /* ("first touch strategy")                            */
   /* --> #pragma omp parallel for ...                    */
   /* *************************************************** */
-#if defined(_OPENMP)
-  field = (field_t*) malloc(omp_get_max_threads()*sizeof(field_t));
-  for ( i = 0; i < omp_get_max_threads(); i++ )
-#else
-  field = (field_t*) malloc(1*sizeof(field_t));
-  for ( i = 0; i < 1; i++ )
-#endif
+  field = (field_t*) malloc(ompNumThreads*sizeof(field_t));
+  for ( i = 0; i < ompNumThreads; i++ )
     {
       field_init(&field[i]);
       field[i].size   = nfiles;
@@ -300,15 +291,12 @@ void *Ensstat3(void *argument)
 	      array2[binID][0] = 0;
 
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, binID, ompthID, fileID)
+#pragma omp parallel for default(shared) private(i, binID, fileID)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
-#if defined(_OPENMP)
-	      ompthID = omp_get_thread_num();
-#else
-	      ompthID = 0;
-#endif
+	      int ompthID = cdo_omp_get_thread_num();
+
 	      field[ompthID].missval = missval;
 	      field[ompthID].nmiss = 0;
 	      have_miss = 0;
diff --git a/src/Ensval.c b/src/Ensval.c
index 0e86324..41d6a24 100644
--- a/src/Ensval.c
+++ b/src/Ensval.c
@@ -437,7 +437,7 @@ void *Ensval(void *argument)
 	      osum += brs_o[k];
 	    }
 	    
-	    if ( abs(osum-1) > 1e-06 || abs(gsum-1) > 1e-06 )  {
+	    if ( fabs(osum-1) > 1.e-06 || fabs(gsum-1) > 1.e-06 )  {
 	      cdoAbort("Internal error - normalization constraint of problem not fulfilled");
 	      cdoAbort("This is likely due to missing values");
 	    }
diff --git a/src/Eof3d.c b/src/Eof3d.c
index d534104..3639e6a 100644
--- a/src/Eof3d.c
+++ b/src/Eof3d.c
@@ -472,22 +472,25 @@ void *EOF3d(void * argument)
 	    // sum +=  weight[pack[i]%gridsize] *
 	    sum += eigenvec[pack[i]] * eigenvec[pack[i]];
 
-	  if ( sum > 0 ) {
-	    sum = sqrt(sum);
+	  if ( sum > 0 )
+	    {
+	      sum = sqrt(sum);
 #if defined(_OPENMP)
 #pragma omp parallel for private(i) default(none) \
   shared(sum,npack,eigenvec,pack)
 #endif
-	    for( i = 0; i < npack; i++ )
-	      eigenvec[pack[i]] /= sum;
-	  }
+	      for( i = 0; i < npack; i++ )
+		eigenvec[pack[i]] /= sum;
+	    }
 	  else
+	    {
 #if defined(_OPENMP)
 #pragma omp parallel for private(i) default(none) \
   shared(eigenvec,pack,missval,npack)
 #endif
-	    for( i = 0; i < npack; i++ )
-	      eigenvec[pack[i]] = missval;
+	      for( i = 0; i < npack; i++ )
+		eigenvec[pack[i]] = missval;
+	    }
 	}     /* for ( eofID = 0; eofID < n_eig; eofID++ )     */
 
       if ( cdoTimer ) timer_stop(timer_post);
diff --git a/src/Filedes.c b/src/Filedes.c
index 4cc74b0..abfe1b3 100644
--- a/src/Filedes.c
+++ b/src/Filedes.c
@@ -83,7 +83,7 @@ void printAtts(FILE *fp, int vlistID, int varID)
 static
 void partab(FILE *fp, int vlistID, int option)
 {
-  int varID, code, tabnum, tableID, datatype = -1;
+  int varID, datatype = -1;
   int param;
   char pstr[32];
   char paramstr[32];
@@ -137,9 +137,6 @@ void partab(FILE *fp, int vlistID, int option)
       varlongname[0] = 0;
       varunits[0]    = 0;
       param    = vlistInqVarParam(vlistID, varID);
-      // code     = vlistInqVarCode(vlistID, varID);
-      // tableID  = vlistInqVarTable(vlistID, varID);
-      // tabnum   = tableInqNum(tableID);
       missval  = vlistInqVarMissval(vlistID, varID);
       vlistInqVarName(vlistID, varID, varname);
       /* printf("1>%s<\n", varname); */
@@ -317,6 +314,7 @@ void *Filedes(void *argument)
 		{
 		  if ( operatorID == VCT )
 		    {
+		      fprintf(stdout, "#   k         vct_a(k) [Pa]             vct_b(k) []\n");
 		      for ( i = 0; i < vctsize/2; i++ )
 			fprintf(stdout, "%5d %25.17f %25.17f\n", i, vct[i], vct[vctsize/2+i]);
 		    }
diff --git a/src/Filter.c b/src/Filter.c
index 96b8f54..6a84930 100644
--- a/src/Filter.c
+++ b/src/Filter.c
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
@@ -56,8 +57,6 @@ void create_fmasc(int nts, double fdata, double fmin, double fmax, int *fmasc)
   imin = dimin<0 ? 0 : (int)floor(dimin);  
   imax = ceil(dimax)>nts/2 ? nts/2 : (int) ceil(dimax);  
 
-  //  printf("%d %d %g %g %g %g %g\n", imin, imax, dimin, dimax, fdata, fmin, fmax);
-  
   fmasc[imin] = 1;
   for ( i = imin+1; i <= imax; i++ )  
     fmasc[i] = fmasc[nts-i] = 1; 
@@ -74,8 +73,8 @@ void filter_fftw(int nts, const int *fmasc, fftw_complex *fft_out, fftw_plan *p_
   for ( i = 0; i < nts; i++ )
     if ( ! fmasc[i] )
       {
-	fft_out[i][0] = 0;
-	fft_out[i][1] = 0;
+        fft_out[i][0] = 0;
+        fft_out[i][1] = 0;
       }
   
   fftw_execute(*p_S2T);
@@ -142,17 +141,23 @@ void *Filter(void *argument)
   dtinfo_t *dtinfo = NULL;
   int incperiod0, incunit0, incunit, calendar;
   int year0, month0, day0;
-  double *array1 = NULL, *array2 = NULL;
   double fdata = 0;
   field_t ***vars = NULL;
   double fmin = 0, fmax = 0;
   int *fmasc;
   int use_fftw = FALSE;
+  typedef struct
+  {
+    double *array1;
+    double *array2;
 #if defined(HAVE_LIBFFTW3) 
-  fftw_plan p_T2S, p_S2T;
-  fftw_complex *out_fft = NULL;
-  fftw_complex *in_fft = NULL;
+    fftw_complex *in_fft;
+    fftw_complex *out_fft;
+    fftw_plan p_T2S;
+    fftw_plan p_S2T;
 #endif
+  } memory_t;
+  memory_t *ompmem = NULL;
   
   cdoInitialize(argument);
 
@@ -194,7 +199,7 @@ void *Filter(void *argument)
       if ( tsID >= nalloc )
         {
           nalloc += NALLOC_INC;
-	  dtinfo = (dtinfo_t*) realloc(dtinfo, nalloc*sizeof(dtinfo_t));
+          dtinfo = (dtinfo_t*) realloc(dtinfo, nalloc*sizeof(dtinfo_t));
           vars   = (field_t ***) realloc(vars, nalloc*sizeof(field_t **));
         }
                        
@@ -216,13 +221,13 @@ void *Filter(void *argument)
       /* get and check time increment */                   
       if ( tsID > 0 )
         {    
-	  juldate_t juldate0, juldate;
-	  double jdelta;
-	  int incperiod = 0;
-	  int year, month, day;
+          juldate_t juldate0, juldate;
+          double jdelta;
+          int incperiod = 0;
+          int year, month, day;
 
           cdiDecodeDate(dtinfo[tsID].v.date,   &year,  &month,  &day);
-	  cdiDecodeDate(dtinfo[tsID-1].v.date, &year0, &month0, &day0);               
+          cdiDecodeDate(dtinfo[tsID-1].v.date, &year0, &month0, &day0);               
 
           juldate0 = juldate_encode(calendar, dtinfo[tsID-1].v.date, dtinfo[tsID-1].v.time);        
           juldate  = juldate_encode(calendar, dtinfo[tsID].v.date, dtinfo[tsID].v.time);         
@@ -230,8 +235,6 @@ void *Filter(void *argument)
           
           if ( tsID == 1 ) 
             {           
-              /*printf("%4i %4.4i-%2.2i-%2.2i\n", tsID, year, month, day);
-              printf("    %4.4i-%2.2i-%2.2i\n",     year0,month0,day0);*/
               getTimeInc(jdelta, dtinfo[tsID-1].v.date, dtinfo[tsID].v.date, &incperiod0, &incunit0);
               incperiod = incperiod0; 
               if ( incperiod == 0 ) cdoAbort("Time step must be different from zero!");
@@ -242,16 +245,16 @@ void *Filter(void *argument)
           else 
             getTimeInc(jdelta, dtinfo[tsID-1].v.date, dtinfo[tsID].v.date, &incperiod, &incunit);        
 
-	  if ( incunit0 < 4 && month == 2 && day == 29 && 
-	       ( day0 != day || month0 != month || year0 != year ) )
-	    {
-	      cdoWarning("Filtering of multi-year times series only works properly with 365-day-calendar.");
-	      cdoWarning("  Please delete the day %i-02-29 (cdo del29feb)", year);
-	    }
+          if ( incunit0 < 4 && month == 2 && day == 29 && 
+               ( day0 != day || month0 != month || year0 != year ) )
+            {
+              cdoWarning("Filtering of multi-year times series only works properly with 365-day-calendar.");
+              cdoWarning("  Please delete the day %i-02-29 (cdo del29feb)", year);
+            }
 
           if ( ! ( incperiod == incperiod0 && incunit == incunit0 ) )
             cdoWarning("Time increment in step %i (%d%s) differs from step 1 (%d%s)!",
-		       tsID, incperiod, tunits[incunit], incperiod0, tunits[incunit0]);        
+                       tsID, incperiod, tunits[incunit], incperiod0, tunits[incunit0]);        
         }
       tsID++;
     }
@@ -259,54 +262,61 @@ void *Filter(void *argument)
   nts = tsID;
   if ( nts <= 1 ) cdoAbort("Number of time steps <= 1!");
 
+  if ( use_fftw )
+    {
+#if defined(HAVE_LIBFFTW3) 
+      ompmem = (memory_t*) malloc(ompNumThreads*sizeof(memory_t));
+      for ( i = 0; i < ompNumThreads; i++ )
+	{
+	  ompmem[i].in_fft  = (fftw_complex*) malloc(nts*sizeof(fftw_complex));
+	  ompmem[i].out_fft = (fftw_complex*) malloc(nts*sizeof(fftw_complex));
+	  ompmem[i].p_T2S = fftw_plan_dft_1d(nts, ompmem[i].in_fft, ompmem[i].out_fft,  1, FFTW_ESTIMATE);
+	  ompmem[i].p_S2T = fftw_plan_dft_1d(nts, ompmem[i].out_fft, ompmem[i].in_fft, -1, FFTW_ESTIMATE);
+	}
+#endif
+    }
+  else
+    {
+      ompmem = (memory_t*) malloc(ompNumThreads*sizeof(memory_t));
+      for ( i = 0; i < ompNumThreads; i++ )
+	{
+	  ompmem[i].array1 = (double*) malloc(nts*sizeof(double));
+	  ompmem[i].array2 = (double*) malloc(nts*sizeof(double));
+	}
+    }
+
   fmasc  = (int*) calloc(nts, sizeof(int));
 
   switch(operfunc)
     {
     case BANDPASS: 
       {
-	operatorInputArg("lower and upper bound of frequency band");
-	operatorCheckArgc(2);
-	fmin = atof(operatorArgv()[0]);
-	fmax = atof(operatorArgv()[1]);
-	break;
+        operatorInputArg("lower and upper bound of frequency band");
+        operatorCheckArgc(2);
+        fmin = atof(operatorArgv()[0]);
+        fmax = atof(operatorArgv()[1]);
+        break;
       }
     case HIGHPASS:
       {              
-	operatorInputArg("lower bound of frequency pass");
-	operatorCheckArgc(1);
-	fmin = atof(operatorArgv()[0]);
-	fmax = fdata;
-	break;
+        operatorInputArg("lower bound of frequency pass");
+        operatorCheckArgc(1);
+        fmin = atof(operatorArgv()[0]);
+        fmax = fdata;
+        break;
       }
     case LOWPASS: 
-      {
-	operatorInputArg("upper bound of frequency pass");
-	operatorCheckArgc(1);
-	fmin = 0;
-	fmax = atof(operatorArgv()[0]);
-	break;
+      { 
+        operatorInputArg("upper bound of frequency pass");
+        operatorCheckArgc(1);
+        fmin = 0;
+        fmax = atof(operatorArgv()[0]);
+        break;
       }
     }
   
   create_fmasc(nts, fdata, fmin, fmax, fmasc);
 
-  if ( use_fftw )
-    {
-#if defined(HAVE_LIBFFTW3) 
-      in_fft  = (fftw_complex*) malloc(nts*sizeof(fftw_complex));
-      out_fft = (fftw_complex*) malloc(nts*sizeof(fftw_complex));
-
-      p_T2S = fftw_plan_dft_1d(nts, in_fft, out_fft,  1, FFTW_ESTIMATE);
-      p_S2T = fftw_plan_dft_1d(nts, out_fft, in_fft, -1, FFTW_ESTIMATE);
-#endif
-    }
-  else
-    {
-      array1 = (double*) malloc(nts*sizeof(double));
-      array2 = (double*) malloc(nts*sizeof(double));
-    }
-
   for ( varID = 0; varID < nvars; varID++ )
     {
       gridID   = vlistInqVarGrid(vlistID1, varID);
@@ -315,46 +325,74 @@ void *Filter(void *argument)
       
       for ( levelID = 0; levelID < nlevel; levelID++ )
         {
-	  if ( use_fftw )
-	    {
+          if ( use_fftw )
+            {
+#if defined(HAVE_LIBFFTW3) 
+#if defined(_OPENMP)
+#pragma omp parallel for default(shared) private(i, tsID)
+#endif
+              for ( i = 0; i < gridsize; i++ )
+                {
+            	  int ompthID = cdo_omp_get_thread_num();
+
+                  for ( tsID = 0; tsID < nts; tsID++ )                              
+                    {
+                      ompmem[ompthID].in_fft[tsID][0] = vars[tsID][varID][levelID].ptr[i];
+                      ompmem[ompthID].in_fft[tsID][1] = 0;
+                    }
+
+                  filter_fftw(nts, fmasc, ompmem[ompthID].out_fft, &ompmem[ompthID].p_T2S, &ompmem[ompthID].p_S2T);
+                  
+                  for ( tsID = 0; tsID < nts; tsID++ )
+                    {
+                      vars[tsID][varID][levelID].ptr[i] = ompmem[ompthID].in_fft[tsID][0] / nts;  
+                    }
+                }
+#endif
+            }
+          else
+            {
+#if defined(_OPENMP)
+#pragma omp parallel for default(shared) private(i, tsID)
+#endif
+              for ( i = 0; i < gridsize; i++ )  
+                {
+            	  int ompthID = cdo_omp_get_thread_num();
+
+                  for ( tsID = 0; tsID < nts; tsID++ )
+                    ompmem[ompthID].array1[tsID] = vars[tsID][varID][levelID].ptr[i];
+
+                  memset(ompmem[ompthID].array2, 0, nts*sizeof(double));
+
+                  filter_intrinsic(nts, fmasc, ompmem[ompthID].array1, ompmem[ompthID].array2);
+
+                  for ( tsID = 0; tsID < nts; tsID++ )
+                    vars[tsID][varID][levelID].ptr[i] = ompmem[ompthID].array1[tsID];
+                }
+            }
+        }
+    }
+
+  if ( use_fftw )
+    {
 #if defined(HAVE_LIBFFTW3) 
-	      for ( i = 0; i < gridsize; i++ )
-		{
-		  for ( tsID = 0; tsID < nts; tsID++ )                              
-		    {
-		      in_fft[tsID][0] = vars[tsID][varID][levelID].ptr[i];
-		      in_fft[tsID][1] = 0;
-		    }
-
-		  filter_fftw(nts, fmasc, out_fft, &p_T2S, &p_S2T);
-		  
-		  for ( tsID = 0; tsID < nts; tsID++ )
-		    {
-		      vars[tsID][varID][levelID].ptr[i] = in_fft[tsID][0] / nts;  
-		    }
-		}
+      for ( i = 0; i < ompNumThreads; i++ )
+	{
+	  free(ompmem[i].in_fft);
+	  free(ompmem[i].out_fft);
+	}
+      free(ompmem);
 #endif
-	    }
-	  else
-	    {
-	      for ( i = 0; i < gridsize; i++ )  
-		{
-		  for ( tsID = 0; tsID < nts; tsID++ )
-		    array1[tsID] = vars[tsID][varID][levelID].ptr[i];
-
-		  memset(array2, 0, nts*sizeof(double));
-
-		  filter_intrinsic(nts, fmasc, array1, array2);
-
-		  for ( tsID = 0; tsID < nts; tsID++ )
-		    vars[tsID][varID][levelID].ptr[i] = array1[tsID];  
-		}
-	    }
+    }
+  else
+    {
+      for ( i = 0; i < ompNumThreads; i++ )
+	{
+	  free(ompmem[i].array1);
+	  free(ompmem[i].array2);
 	}
+      free(ompmem);
     }
-  
-  if ( array1 ) free(array1);
-  if ( array2 ) free(array2);
 
   streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
   
@@ -373,11 +411,11 @@ void *Filter(void *argument)
               if ( vars[tsID][varID][levelID].ptr )
                 {
                   nmiss = vars[tsID][varID][levelID].nmiss;
-		  streamDefRecord(streamID2, varID, levelID);
+                  streamDefRecord(streamID2, varID, levelID);
                   streamWriteRecord(streamID2, vars[tsID][varID][levelID].ptr, nmiss);
 
                   free(vars[tsID][varID][levelID].ptr);
-		  vars[tsID][varID][levelID].ptr = NULL;
+                  vars[tsID][varID][levelID].ptr = NULL;
                 }
             }
         }
@@ -385,16 +423,11 @@ void *Filter(void *argument)
       field_free(vars[tsID], vlistID1);
     }
 
-  streamClose(streamID2);
-  streamClose(streamID1);
-
   if ( vars   ) free(vars);
   if ( dtinfo ) free(dtinfo);
 
-#if defined(HAVE_LIBFFTW3)
-  if ( in_fft  ) free(in_fft);
-  if ( out_fft ) free(out_fft);
-#endif
+  streamClose(streamID2);
+  streamClose(streamID1);
 
   cdoFinish();
   
diff --git a/src/Fldstat2.c b/src/Fldstat2.c
index 7861716..ccaabe5 100644
--- a/src/Fldstat2.c
+++ b/src/Fldstat2.c
@@ -103,18 +103,18 @@ void *Fldstat2(void *argument)
   int gridID, lastgridID = -1;
   int gridID3;
   int wstatus = FALSE;
-  int code = 0, oldcode = 0;
   int index, ngrids;
   int recID, nrecs, nrecs2;
   int tsID, varID, levelID;
   long gridsize;
   int needWeights = TRUE;
   int nmiss1, nmiss2, nmiss3;
+  int taxisID1, taxisID3;
   double missval1, missval2;
   double slon, slat;
   double sglval;
   double *array1, *array2, *weight;
-  int taxisID1, taxisID3;
+  char varname[CDI_MAX_NAME];
 
   cdoInitialize(argument);
 
@@ -191,9 +191,11 @@ void *Fldstat2(void *argument)
 	      lastgridID = gridID;
 	      wstatus = gridWeights(gridID, weight);
 	    }
-	  code = vlistInqVarCode(vlistID1, varID);
-	  if ( wstatus != 0 && tsID == 0 && code != oldcode )
-	    cdoWarning("Using constant grid cell area weights for code %d!", oldcode=code);
+	  if ( wstatus != 0 && tsID == 0 && levelID == 0 )
+	    {
+	      vlistInqVarName(vlistID1, varID, varname);
+	      cdoWarning("Using constant grid cell area weights for variable %s!", varname);
+	    }
 
 	  missval1 = vlistInqVarMissval(vlistID1, varID);
 	  missval2 = vlistInqVarMissval(vlistID2, varID);
diff --git a/src/Fourier.c b/src/Fourier.c
index e8b814a..7ef2d4a 100644
--- a/src/Fourier.c
+++ b/src/Fourier.c
@@ -15,9 +15,6 @@
   GNU General Public License for more details.
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
 
 #include <cdi.h>
 #include "cdo.h"
@@ -31,7 +28,6 @@
 
 void *Fourier(void *argument)
 {
-  int ompthID;
   int bit, sign;
   int gridsize;
   int nrecs;
@@ -131,16 +127,13 @@ void *Fourier(void *argument)
       for ( levelID = 0; levelID < nlevel; levelID++ )
 	{
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, ompthID, tsID)
+#pragma omp parallel for default(shared) private(i, tsID)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
 	      int lmiss = 0;
-#if defined(_OPENMP)
-              ompthID = omp_get_thread_num();
-#else
-              ompthID = 0;
-#endif
+              int ompthID = cdo_omp_get_thread_num();
+
 	      for ( tsID = 0; tsID < nts; tsID++ )
 		{
 		  ompmem[ompthID].real[tsID] = vars[tsID][varID][levelID].ptr[2*i];
diff --git a/src/Gradsdes.c b/src/Gradsdes.c
index c31eddb..24cf8cf 100644
--- a/src/Gradsdes.c
+++ b/src/Gradsdes.c
@@ -75,7 +75,7 @@ struct gaindx {
   float *fltpnt;    /* Pointer to float index values  */
 };
 struct gaindxb {
-  int    bignum;    /* Number of off_t values */	       
+  int    bignum;    /* Number of off_t values */
   off_t *bigpnt;    /* Pointer to off_t values */
 };
 
@@ -110,32 +110,32 @@ char *ch1,*ch2,*ch3,*ch4,cc1,cc2;
 static
 float ibm2flt(unsigned char *ibm) {
 
-	int positive, power;
-	unsigned int abspower;
-	long int mant;
-	double value, exp;
-
-	positive = (ibm[0] & 0x80) == 0;
-	mant = (ibm[1] << 16) + (ibm[2] << 8) + ibm[3];
-	power = (int) (ibm[0] & 0x7f) - 64;
-	abspower = power > 0 ? power : -power;
-
-
-	/* calc exp */
-	exp = 16.0;
-	value = 1.0;
-	while (abspower) {
-		if (abspower & 1) {
-			value *= exp;
-		}
-		exp = exp * exp;
-		abspower >>= 1;
-	}
-
-	if (power < 0) value = 1.0 / value;
-	value = value * mant / 16777216.0;
-	if (positive == 0) value = -value;
-	return (float)value;
+  int positive, power;
+  unsigned int abspower;
+  long int mant;
+  double value, exp;
+
+  positive = (ibm[0] & 0x80) == 0;
+  mant = (ibm[1] << 16) + (ibm[2] << 8) + ibm[3];
+  power = (int) (ibm[0] & 0x7f) - 64;
+  abspower = power > 0 ? power : -power;
+
+
+  /* calc exp */
+  exp = 16.0;
+  value = 1.0;
+  while (abspower) {
+    if (abspower & 1) {
+      value *= exp;
+    }
+    exp = exp * exp;
+    abspower >>= 1;
+  }
+
+  if (power < 0) value = 1.0 / value;
+  value = value * mant / 16777216.0;
+  if (positive == 0) value = -value;
+  return (float)value;
 }
 
 /*
@@ -148,66 +148,66 @@ float ibm2flt(unsigned char *ibm) {
 static
 int flt2ibm(float x, unsigned char *ibm) {
 
-	int sign, exp, i;
-	double mant;
-
-	if ( !(fabs((double)x) > 0) ) {
-		ibm[0] = ibm[1] = ibm[2] = ibm[3] = 0;
-		return 0;
-	}
-
-	/* sign bit */
-	if (x < 0.0) {
-		sign = 128;
-		x = -x;
-	}
-	else sign = 0;
-
-	mant = frexp((double) x, &exp);
-
-	/* round up by adding 2**-24 */
-	/* mant = mant + 1.0/16777216.0; */
-
-	if (mant >= 1.0) {
-		mant = 0.5;
-		exp++;
-	}
-	while (exp & 3) {
-		mant *= 0.5;
-		exp++;
-	}
-	
-	exp = exp/4 + 64;
-
-	if (exp < 0) {
-		fprintf(stderr,"underflow in flt2ibm\n");
-		ibm[0] = ibm[1] = ibm[2] = ibm[3] = 0;
-		return 0;
-	}
-	if (exp > 127) {
-		fprintf(stderr,"overflow in flt2ibm\n");
-		ibm[0] = sign | 127;
-		ibm[1] = ibm[2] = ibm[3] = 255;
-		return -1;
-	}
-
-	/* normal number */
-
-	ibm[0] = sign | exp;
-
-	mant = mant * 256.0;
-	i = (int) floor(mant);
-	mant = mant - i;
-	ibm[1] = i;
-
-	mant = mant * 256.0;
-	i = (int) floor(mant);
-	mant = mant - i;
-	ibm[2] = i;
-
-	ibm[3] = (int) floor(mant*256.0);
-
-	return 0;
+  int sign, exp, i;
+  double mant;
+
+  if ( !(fabs((double)x) > 0) ) {
+    ibm[0] = ibm[1] = ibm[2] = ibm[3] = 0;
+    return 0;
+  }
+
+  /* sign bit */
+  if (x < 0.0) {
+    sign = 128;
+    x = -x;
+  }
+  else sign = 0;
+
+  mant = frexp((double) x, &exp);
+
+  /* round up by adding 2**-24 */
+  /* mant = mant + 1.0/16777216.0; */
+
+  if (mant >= 1.0) {
+    mant = 0.5;
+    exp++;
+  }
+  while (exp & 3) {
+    mant *= 0.5;
+    exp++;
+  }
+
+  exp = exp/4 + 64;
+
+  if (exp < 0) {
+    fprintf(stderr,"underflow in flt2ibm\n");
+    ibm[0] = ibm[1] = ibm[2] = ibm[3] = 0;
+    return 0;
+  }
+  if (exp > 127) {
+    fprintf(stderr,"overflow in flt2ibm\n");
+    ibm[0] = sign | 127;
+    ibm[1] = ibm[2] = ibm[3] = 255;
+    return -1;
+  }
+
+  /* normal number */
+
+  ibm[0] = sign | exp;
+
+  mant = mant * 256.0;
+  i = (int) floor(mant);
+  mant = mant - i;
+  ibm[1] = i;
+
+  mant = mant * 256.0;
+  i = (int) floor(mant);
+  mant = mant - i;
+  ibm[2] = i;
+
+  ibm[3] = (int) floor(mant*256.0);
+
+  return 0;
 }
 
 #define  GET_UINT4(a,b,c,d) ((int) ((a << 24) + (b << 16) + (c << 8) + (d)))
@@ -260,7 +260,7 @@ void dumpmap()
 
       nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
       indx.hinum = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
-      
+
       nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
       indx.hfnum = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
 
@@ -273,38 +273,38 @@ void dumpmap()
       nbytes = fread(mrec, sizeof(unsigned char), 7, mapfp);
 
       if ( indx.hinum > 0 )
-	{
-	  indx.hipnt = (int*) malloc(sizeof(int)*indx.hinum);
-	  for ( i = 0; i < indx.hinum; i++ )
-	    {
-	      nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
-	      indx.hipnt[i] = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
-	    }
-	}
+        {
+          indx.hipnt = (int*) malloc(sizeof(int)*indx.hinum);
+          for ( i = 0; i < indx.hinum; i++ )
+            {
+              nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
+              indx.hipnt[i] = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
+            }
+        }
       if ( indx.hfnum > 0 )
-	{
-	  indx.hfpnt = (float*) malloc(sizeof(float)*indx.hfnum);
-	  nbytes = fread (indx.hfpnt,sizeof(float),indx.hfnum,mapfp);
-	}
+        {
+          indx.hfpnt = (float*) malloc(sizeof(float)*indx.hfnum);
+          nbytes = fread (indx.hfpnt,sizeof(float),indx.hfnum,mapfp);
+        }
       if ( indx.intnum > 0 )
-	{
-	  indx.intpnt = (int*) malloc(sizeof(int)*indx.intnum);
-	  for ( i = 0; i < indx.intnum; i++ )
-	    {
-	      nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
-	      indx.intpnt[i] = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
-	      if ( indx.intpnt[i] < 0 ) indx.intpnt[i] = 0x7fffffff - indx.intpnt[i] + 1;
-	    }
-	}
+        {
+          indx.intpnt = (int*) malloc(sizeof(int)*indx.intnum);
+          for ( i = 0; i < indx.intnum; i++ )
+            {
+              nbytes = fread(mrec, sizeof(unsigned char), 4, mapfp);
+              indx.intpnt[i] = GET_UINT4(mrec[0],mrec[1],mrec[2],mrec[3]);
+              if ( indx.intpnt[i] < 0 ) indx.intpnt[i] = 0x7fffffff - indx.intpnt[i] + 1;
+            }
+        }
       if ( indx.fltnum > 0 )
-	{
-	  indx.fltpnt = (float*) malloc(sizeof(float)*indx.fltnum);
-	  for ( i = 0; i < indx.fltnum; i++ )
-	    {
-	      nbytes = fread(urec, sizeof(unsigned char), 4, mapfp);
-	      indx.fltpnt[i] = ibm2flt(urec);
-	    }
-	}
+        {
+          indx.fltpnt = (float*) malloc(sizeof(float)*indx.fltnum);
+          for ( i = 0; i < indx.fltnum; i++ )
+            {
+              nbytes = fread(urec, sizeof(unsigned char), 4, mapfp);
+              indx.fltpnt[i] = ibm2flt(urec);
+            }
+        }
     }
   else
     {
@@ -314,43 +314,43 @@ void dumpmap()
       if ( indx.type>>24 > 0 ) swpflg = 1;
       if ( swpflg ) printf("swap endian!\n");
       if ( swpflg ) gabswp((float *)&indx.type, 5);
-      
+
       if ( indx.hinum > 0 )
-	{
-	  indx.hipnt = (int*) malloc(sizeof(int)*indx.hinum);
-	  nbytes = fread (indx.hipnt, sizeof(int), indx.hinum, mapfp);
-	  if ( swpflg ) gabswp((float *)(indx.hipnt),indx.hinum);
-	}
+        {
+          indx.hipnt = (int*) malloc(sizeof(int)*indx.hinum);
+          nbytes = fread (indx.hipnt, sizeof(int), indx.hinum, mapfp);
+          if ( swpflg ) gabswp((float *)(indx.hipnt),indx.hinum);
+        }
       if ( indx.hfnum > 0 )
-	{
-	  indx.hfpnt = (float*) malloc(sizeof(float)*indx.hfnum);
-	  nbytes = fread (indx.hfpnt,sizeof(float),indx.hfnum,mapfp);
-	  if ( swpflg ) gabswp(indx.hfpnt,indx.hfnum);
-	}
+        {
+          indx.hfpnt = (float*) malloc(sizeof(float)*indx.hfnum);
+          nbytes = fread (indx.hfpnt,sizeof(float),indx.hfnum,mapfp);
+          if ( swpflg ) gabswp(indx.hfpnt,indx.hfnum);
+        }
 
       if ( indx.intnum > 0 )
-	{
-	  indx.intpnt = (int*) malloc(sizeof(int)*indx.intnum);
-	  nbytes = fread (indx.intpnt,sizeof(int),indx.intnum,mapfp);
-	  if ( swpflg ) gabswp((float *)(indx.intpnt),indx.intnum);
-	}
+        {
+          indx.intpnt = (int*) malloc(sizeof(int)*indx.intnum);
+          nbytes = fread (indx.intpnt,sizeof(int),indx.intnum,mapfp);
+          if ( swpflg ) gabswp((float *)(indx.intpnt),indx.intnum);
+        }
       if ( indx.fltnum > 0 )
-	{
-	  indx.fltpnt = (float*) malloc(sizeof(float)*indx.fltnum);
-	  nbytes = fread (indx.fltpnt,sizeof(float),indx.fltnum,mapfp);
-	  if ( swpflg ) gabswp(indx.fltpnt,indx.fltnum);
-	}
+        {
+          indx.fltpnt = (float*) malloc(sizeof(float)*indx.fltnum);
+          nbytes = fread (indx.fltpnt,sizeof(float),indx.fltnum,mapfp);
+          if ( swpflg ) gabswp(indx.fltpnt,indx.fltnum);
+        }
 
       if ( indx.hipnt[0] == 4 )
-	{
-	  indxb.bignum = indx.hipnt[4];
-	  if ( indxb.bignum > 0 )
-	    {
-	      indxb.bigpnt = (off_t*) malloc(sizeof(off_t)*indxb.bignum);
-	      nbytes = fread (indxb.bigpnt,sizeof(off_t),indxb.bignum,mapfp);
-	      if ( swpflg ) gabswp(indxb.bigpnt,indxb.bignum);
-	    }
-	}
+        {
+          indxb.bignum = indx.hipnt[4];
+          if ( indxb.bignum > 0 )
+            {
+              indxb.bigpnt = (off_t*) malloc(sizeof(off_t)*indxb.bignum);
+              nbytes = fread (indxb.bigpnt,sizeof(off_t),indxb.bignum,mapfp);
+              if ( swpflg ) gabswp(indxb.bigpnt,indxb.bignum);
+            }
+        }
     }
 
   fclose(mapfp);
@@ -358,12 +358,12 @@ void dumpmap()
   printf("hinum: %d\n", indx.hinum);
   for ( i = 0; i < indx.hinum; i++ )
     printf("%3d %5d\n", i+1, indx.hipnt[i]);
-  
+
   printf("\n");
   printf("hfnum: %d\n", indx.hfnum);
   for ( i = 0; i < indx.hfnum; i++ )
     printf("%3d %g\n", i+1, indx.hfpnt[i]);
-  
+
   printf("\n");
 
   nrecords = indx.hipnt[1]*indx.hipnt[2];
@@ -372,33 +372,33 @@ void dumpmap()
     {
       printf("num: %d\n", indx.intnum);
       for ( i = 0; i < indx.intnum/3; i++ )
-	printf("%3d %8d %6d %4d %8g %10g %8g\n", i+1,
-	       indx.intpnt[i*3], indx.intpnt[i*3+1], indx.intpnt[i*3+2],
-	       indx.fltpnt[i*3], indx.fltpnt[i*3+1], indx.fltpnt[i*3+2]);
+        printf("%3d %8d %6d %4d %8g %10g %8g\n", i+1,
+               indx.intpnt[i*3], indx.intpnt[i*3+1], indx.intpnt[i*3+2],
+               indx.fltpnt[i*3], indx.fltpnt[i*3+1], indx.fltpnt[i*3+2]);
     }
   else if ( indx.intnum == nrecords && indx.fltnum == nrecords*3 && indxb.bignum == nrecords*2 )
     {
       printf("nrecords: %d\n", nrecords);
       for ( i = 0; i < nrecords; i++ )
-	printf("%3d %8zd %6zd %4d %8g %10g %8g\n", i+1,
-	       (size_t)indxb.bigpnt[i*2], (size_t)indxb.bigpnt[i*2+1], indx.intpnt[i],
-	       indx.fltpnt[i*3], indx.fltpnt[i*3+1], indx.fltpnt[i*3+2]);
+        printf("%3d %8zd %6zd %4d %8g %10g %8g\n", i+1,
+               (size_t)indxb.bigpnt[i*2], (size_t)indxb.bigpnt[i*2+1], indx.intpnt[i],
+               indx.fltpnt[i*3], indx.fltpnt[i*3+1], indx.fltpnt[i*3+2]);
     }
   else
     {
       printf("intnum: %d\n", indx.intnum);
       for ( i = 0; i < indx.intnum; i++ )
-	printf("%3d %d\n", i+1, indx.intpnt[i]);
+        printf("%3d %d\n", i+1, indx.intpnt[i]);
 
       printf("\n");
       printf("fltnum: %d\n", indx.fltnum);
       for ( i = 0; i < indx.fltnum; i++ )
-	printf("%3d %g\n", i+1, indx.fltpnt[i]);
+        printf("%3d %g\n", i+1, indx.fltpnt[i]);
 
       printf("\n");
       printf("bignum: %d\n", indxb.bignum);
       for ( i = 0; i < indxb.bignum; i++ )
-	printf("%3d %zd\n", i+1, (size_t)indxb.bigpnt[i]);
+        printf("%3d %zd\n", i+1, (size_t)indxb.bigpnt[i]);
     }
 }
 
@@ -430,9 +430,9 @@ void ctl_xydef(FILE *gdp, int gridID, int *yrev)
       double inc[] = { 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01, 0.005, 0.002, 0.001 };
 
       gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-		 &projflag, &scanflag);
-      fprintf(gdp, "PDEF %d %d LCCR %g %g 1 1 %g %g %g %g %g\n", 
-	      xsize, ysize, originLat, originLon, lat1, lat2, lonParY, xincm, yincm);
+                 &projflag, &scanflag);
+      fprintf(gdp, "PDEF %d %d LCCR %g %g 1 1 %g %g %g %g %g\n",
+              xsize, ysize, originLat, originLon, lat1, lat2, lonParY, xincm, yincm);
 
       gridID = gridToCurvilinear(gridID, 0);
       xvals = (double*) malloc(xsize*ysize*sizeof(double));
@@ -440,13 +440,13 @@ void ctl_xydef(FILE *gdp, int gridID, int *yrev)
       gridInqXvals(gridID, xvals);
       gridInqYvals(gridID, yvals);
       for ( i = 0; i < xsize*ysize; ++i )
-	{
-	  if ( xvals[i] > 180  ) xvals[i] -= 360;
-	  if ( xvals[i] < xmin ) xmin = xvals[i];
-	  if ( xvals[i] > xmax ) xmax = xvals[i];
-	  if ( yvals[i] < ymin ) ymin = yvals[i];
-	  if ( yvals[i] > ymax ) ymax = yvals[i];
-	}
+        {
+          if ( xvals[i] > 180  ) xvals[i] -= 360;
+          if ( xvals[i] < xmin ) xmin = xvals[i];
+          if ( xvals[i] > xmax ) xmax = xvals[i];
+          if ( yvals[i] < ymin ) ymin = yvals[i];
+          if ( yvals[i] > ymax ) ymax = yvals[i];
+        }
       free(xvals);
       free(yvals);
 
@@ -457,13 +457,13 @@ void ctl_xydef(FILE *gdp, int gridID, int *yrev)
 
       ni = sizeof(inc)/sizeof(inc[0]);
       for ( i = 0; i < ni; i++ )
-	{
-	  xinc = yinc = inc[i];
-	  nx = 1 + (int) (xrange / xinc);
-	  ny = 1 + (int) (yrange / yinc);
+        {
+          xinc = yinc = inc[i];
+          nx = 1 + (int) (xrange / xinc);
+          ny = 1 + (int) (yrange / yinc);
 
-	  if ( nx > 1.5*xsize && ny > 1.5*ysize ) break;
-	}
+          if ( nx > 1.5*xsize && ny > 1.5*ysize ) break;
+        }
 
       fprintf(gdp, "XDEF %d LINEAR %f %f\n", nx, xfirst, xinc);
       fprintf(gdp, "YDEF %d LINEAR %f %f\n", ny, yfirst, yinc);
@@ -476,31 +476,31 @@ void ctl_xydef(FILE *gdp, int gridID, int *yrev)
       xfirst = gridInqXval(gridID, 0);
       xinc   = gridInqXinc(gridID);
       if ( IS_EQUAL(xinc, 0) && gridInqXvals(gridID, NULL) )
-	{
-	  xvals = (double*) malloc(xsize*sizeof(double));
-	  gridInqXvals(gridID, xvals);
-	  fprintf(gdp ,"XDEF %d LEVELS ", xsize);
-	  j = 0;
-	  for ( i = 0; i < xsize; i++ )
-	    {
-	      fprintf(gdp, "%7.3f ", xvals[i]); 
-	      j++;
-	      if ( j == 6 )
-		{
-		  fprintf(gdp, "\n");
-		  j = 0;
-		  if ( i != xsize-1 ) fprintf(gdp, "               ");
-		}
-	    }
-	  if ( j ) fprintf(gdp, "\n");
-	  
-	  free(xvals);
-	}
+        {
+          xvals = (double*) malloc(xsize*sizeof(double));
+          gridInqXvals(gridID, xvals);
+          fprintf(gdp ,"XDEF %d LEVELS ", xsize);
+          j = 0;
+          for ( i = 0; i < xsize; i++ )
+            {
+              fprintf(gdp, "%7.3f ", xvals[i]);
+              j++;
+              if ( j == 6 )
+                {
+                  fprintf(gdp, "\n");
+                  j = 0;
+                  if ( i != xsize-1 ) fprintf(gdp, "               ");
+                }
+            }
+          if ( j ) fprintf(gdp, "\n");
+
+          free(xvals);
+        }
       else
-	{
-	  if ( IS_EQUAL(xinc, 0) ) xinc = 360.0/xsize;
-	  fprintf(gdp, "XDEF %d LINEAR %f %f\n", xsize, xfirst, xinc);	  
-	}
+        {
+          if ( IS_EQUAL(xinc, 0) ) xinc = 360.0/xsize;
+          fprintf(gdp, "XDEF %d LINEAR %f %f\n", xsize, xfirst, xinc);
+        }
     }
 
   /* YDEF */
@@ -512,56 +512,56 @@ void ctl_xydef(FILE *gdp, int gridID, int *yrev)
       if ( gridtype == GRID_GAUSSIAN ) yinc = 0;
 
       if ( IS_EQUAL(yinc, 0) && gridInqYvals(gridID, NULL) )
-	{
-	  yvals = (double*) malloc(ysize*sizeof(double));
-	  gridInqYvals(gridID, yvals);
-	  fprintf(gdp ,"YDEF %d LEVELS ", ysize);
-	  j = 0;
-	  if ( yvals[0] > yvals[ysize-1] )
-	    {
-	      *yrev = TRUE;
-	      for ( i = ysize-1; i >= 0; i-- )
-		{
-		  fprintf(gdp, "%7.3f ", yvals[i]); 
-		  j++;
-		  if ( j == 6 )
-		    {
-		      fprintf(gdp, "\n");
-		      j = 0;
-		      if ( i != 0 ) fprintf(gdp, "               ");
-		    }
-		}
-	    }
-	  else
-	    {
-	      for ( i = 0; i < ysize; i++ )
-		{
-		  fprintf(gdp, "%7.3f ", yvals[i]); 
-		  j++;
-		  if ( j == 6 )
-		    {
-		      fprintf(gdp, "\n");
-		      j = 0;
-		      if ( i != ysize-1 ) fprintf(gdp, "               ");
-		    }
-		}
-	    }
-
-	  if ( j ) fprintf(gdp, "\n");
-
-	  free(yvals);
-	}
+        {
+          yvals = (double*) malloc(ysize*sizeof(double));
+          gridInqYvals(gridID, yvals);
+          fprintf(gdp ,"YDEF %d LEVELS ", ysize);
+          j = 0;
+          if ( yvals[0] > yvals[ysize-1] )
+            {
+              *yrev = TRUE;
+              for ( i = ysize-1; i >= 0; i-- )
+                {
+                  fprintf(gdp, "%7.3f ", yvals[i]);
+                  j++;
+                  if ( j == 6 )
+                    {
+                      fprintf(gdp, "\n");
+                      j = 0;
+                      if ( i != 0 ) fprintf(gdp, "               ");
+                    }
+                }
+            }
+          else
+            {
+              for ( i = 0; i < ysize; i++ )
+                {
+                  fprintf(gdp, "%7.3f ", yvals[i]);
+                  j++;
+                  if ( j == 6 )
+                    {
+                      fprintf(gdp, "\n");
+                      j = 0;
+                      if ( i != ysize-1 ) fprintf(gdp, "               ");
+                    }
+                }
+            }
+
+          if ( j ) fprintf(gdp, "\n");
+
+          free(yvals);
+        }
       else
-	{
-	  if ( IS_EQUAL(yinc, 0) ) yinc = 180.0/ysize;
-	  if ( yinc < 0)
-	    {
-	      *yrev = TRUE;
-	      fprintf(gdp, "YDEF %d LINEAR %f %f\n", ysize, yfirst + yinc * (ysize-1 ), -yinc);
-	    }
-	  else
-	    fprintf(gdp, "YDEF %d LINEAR %f %f\n", ysize, yfirst, yinc);
-	}
+        {
+          if ( IS_EQUAL(yinc, 0) ) yinc = 180.0/ysize;
+          if ( yinc < 0)
+            {
+              *yrev = TRUE;
+              fprintf(gdp, "YDEF %d LINEAR %f %f\n", ysize, yfirst + yinc * (ysize-1 ), -yinc);
+            }
+          else
+            fprintf(gdp, "YDEF %d LINEAR %f %f\n", ysize, yfirst, yinc);
+        }
     }
 }
 
@@ -583,10 +583,10 @@ void ctl_zdef(FILE *gdp, int vlistID, int *zrev)
       zaxisID = vlistZaxis(vlistID, index);
       nlev    = zaxisInqSize(zaxisID);
       if ( nlev > nlevmax )
-	{
-	  nlevmax = nlev;
-	  zaxisIDmax = zaxisID;
-	}
+        {
+          nlevmax = nlev;
+          zaxisIDmax = zaxisID;
+        }
     }
 
   levels = (double*) malloc(nlevmax*sizeof(double));
@@ -596,20 +596,20 @@ void ctl_zdef(FILE *gdp, int vlistID, int *zrev)
   if ( nlevmax > 1 )
     {
       if ( levels[0] < levels[1] && zaxisInqType(zaxisIDmax) != ZAXIS_HYBRID )
-	*zrev = TRUE;
+        *zrev = TRUE;
 
       levinc = levels[1] - levels[0];
 
       if ( IS_EQUAL(levinc, 1) ) *zrev = FALSE;
 
       for ( i = 1; i < nlevmax; i++ )
-	{
-	  if ( IS_NOT_EQUAL(levinc, (levels[i] - levels[i-1])) )
-	    {
-	      levinc = 0;
-	      break;
-	    }
-	}
+        {
+          if ( IS_NOT_EQUAL(levinc, (levels[i] - levels[i-1])) )
+            {
+              levinc = 0;
+              break;
+            }
+        }
     }
 
   if ( IS_NOT_EQUAL(levinc, 0) )
@@ -620,36 +620,36 @@ void ctl_zdef(FILE *gdp, int vlistID, int *zrev)
       j  = 0;
       /* zrev not needed !!!
       if ( *zrev )
-	{
-	  for ( i = nlevmax-1; i >=0 ; i-- )
-	    {
-	      if ( lplev ) fprintf(gdp, "%g ", levels[i]/100);
-	      else         fprintf(gdp, "%d ", (int) levels[i]);
-	      j++;
-	      if ( j == 10 )
-		{
-		  fprintf(gdp, "\n");
-		  j = 0;
-		  if ( i != 0 ) fprintf(gdp, "               ");
-		}
-	    }
-	}
+        {
+          for ( i = nlevmax-1; i >=0 ; i-- )
+            {
+              if ( lplev ) fprintf(gdp, "%g ", levels[i]/100);
+              else         fprintf(gdp, "%d ", (int) levels[i]);
+              j++;
+              if ( j == 10 )
+                {
+                  fprintf(gdp, "\n");
+                  j = 0;
+                  if ( i != 0 ) fprintf(gdp, "               ");
+                }
+            }
+        }
       else
       */
-	{
-	  for ( i = 0; i < nlevmax ; i++ )
-	    {
-	      if ( lplev ) fprintf(gdp, "%g ", levels[i]/100);
-	      else         fprintf(gdp, "%g ", levels[i]);
-	      j++;
-	      if ( j == 10 )
-		{
-		  fprintf(gdp, "\n");
-		  j = 0;
-		  if ( i != (nlevmax-1) ) fprintf(gdp, "               ");
-		}
-	    }
-	}
+        {
+          for ( i = 0; i < nlevmax ; i++ )
+            {
+              if ( lplev ) fprintf(gdp, "%g ", levels[i]/100);
+              else         fprintf(gdp, "%g ", levels[i]);
+              j++;
+              if ( j == 10 )
+                {
+                  fprintf(gdp, "\n");
+                  j = 0;
+                  if ( i != (nlevmax-1) ) fprintf(gdp, "               ");
+                }
+            }
+        }
       if ( j ) fprintf(gdp, "\n");
     }
 
@@ -657,7 +657,7 @@ void ctl_zdef(FILE *gdp, int vlistID, int *zrev)
 }
 
 static
-void ctl_options(FILE *gdp, int yrev, int zrev, int sequential, int bigendian, int littleendian, int flt64)
+void ctl_options(FILE *gdp, int yrev, int zrev, int sequential, int bigendian, int littleendian, int flt64, int cal365day)
 {
   /* if ( filetype == FILETYPE_GRB ) zrev = FALSE; */
 
@@ -670,6 +670,7 @@ void ctl_options(FILE *gdp, int yrev, int zrev, int sequential, int bigendian, i
       if ( bigendian )    fprintf(gdp, " big_endian");
       if ( littleendian ) fprintf(gdp, " little_endian");
       if ( flt64 )        fprintf(gdp, " flt64");
+      if ( cal365day )    fprintf(gdp, " 365_day_calendar");
       fprintf(gdp, "\n");
     }
 }
@@ -700,87 +701,87 @@ void ctl_vars(FILE *gdp, int filetype, int vlistID, int nvarsout, int *vars)
   for ( varID = 0; varID < nvars; varID++ )
     {
       if ( vars[varID] == TRUE )
-	{
-	  zaxisID = vlistInqVarZaxis(vlistID, varID);
-	  ltype   = zaxisInqLtype(zaxisID);
-	  nlev    = zaxisInqSize(zaxisID);
-	  vlistInqVarName(vlistID, varID, varname);
-
-	  len = (int) strlen(varname);
-	  for ( i = 0; i < len; i++ )
-	    if ( varname[i] == '-' ) break;
-
-	  if ( i < len )
-	    for ( j = i; j < len; j++ )
-	      varname[j] = varname[j+1];
-
-	  vlistInqVarLongname(vlistID, varID, varlongname);
-	  vlistInqVarUnits(vlistID, varID, varunits);
-	  fprintf(gdp, "%-15s", varname);
-      
-	  if ( nlev == 1 ) nlev = 0;
-
-	  fprintf(gdp, "  %3d", nlev);
-
-	  if ( filetype == FILETYPE_GRB )
-	    {
-	      code = vlistInqVarCode(vlistID, varID);
-	      /*	      
-	      if      ( ltype == ZAXIS_SURFACE )  ltype = 1;
-	      else if ( ltype == ZAXIS_PRESSURE ) ltype = 99;
-	      else if ( nlev == 1 )  ltype = 1;
-	      else ltype = 99;
-	      */
-	      fprintf(gdp, "  %d,%d", code, ltype);
-	    }
-	  else if ( filetype == FILETYPE_NC )
-	    {
-	      int xyz = vlistInqVarXYZ(vlistID, varID);
-
-	      fprintf(gdp, "  ");
-	      if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
-		fprintf(gdp, "t,");
-	      if ( xyz == 321 )
-		{
-		  if ( nlev > 0 ) fprintf(gdp, "z,");
-		  fprintf(gdp, "y,x");
-		}
-	      else if ( xyz == 312 )
-		{
-		  if ( nlev > 0 ) fprintf(gdp, "z,");
-		  fprintf(gdp, "x,y");
-		}
-	      else if ( xyz == 231 )
-		{
-		  fprintf(gdp, "y,");
-		  if ( nlev > 0 ) fprintf(gdp, "z,");
-		  fprintf(gdp, "x");
-		}
-	      else if ( xyz == 132 )
-		{
-		  fprintf(gdp, "x,");
-		  if ( nlev > 0 ) fprintf(gdp, "z,");
-		  fprintf(gdp, "y");
-		}
-	      else
-		{
-		  if ( nlev > 0 ) fprintf(gdp, "z,");
-		  fprintf(gdp, "y,x");
-		}
-	    }
-	  else
-	    fprintf(gdp, "  99");
-
-	  if ( varlongname[0] == 0 )
-	    fprintf(gdp, "  %s", varname);
-	  else
-	    fprintf(gdp, "  %s", varlongname);
-
-	  if ( varunits[0] != 0 )
-	    fprintf(gdp, "  [%s]", varunits);
-	
-	  fprintf(gdp, "\n");      
-	}
+        {
+          zaxisID = vlistInqVarZaxis(vlistID, varID);
+          ltype   = zaxisInqLtype(zaxisID);
+          nlev    = zaxisInqSize(zaxisID);
+          vlistInqVarName(vlistID, varID, varname);
+
+          len = (int) strlen(varname);
+          for ( i = 0; i < len; i++ )
+            if ( varname[i] == '-' ) break;
+
+          if ( i < len )
+            for ( j = i; j < len; j++ )
+              varname[j] = varname[j+1];
+
+          vlistInqVarLongname(vlistID, varID, varlongname);
+          vlistInqVarUnits(vlistID, varID, varunits);
+          fprintf(gdp, "%-15s", varname);
+
+          if ( nlev == 1 ) nlev = 0;
+
+          fprintf(gdp, "  %3d", nlev);
+
+          if ( filetype == FILETYPE_GRB )
+            {
+              code = vlistInqVarCode(vlistID, varID);
+              /*
+              if      ( ltype == ZAXIS_SURFACE )  ltype = 1;
+              else if ( ltype == ZAXIS_PRESSURE ) ltype = 99;
+              else if ( nlev == 1 )  ltype = 1;
+              else ltype = 99;
+              */
+              fprintf(gdp, "  %d,%d", code, ltype);
+            }
+          else if ( filetype == FILETYPE_NC )
+            {
+              int xyz = vlistInqVarXYZ(vlistID, varID);
+
+              fprintf(gdp, "  ");
+              if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+                fprintf(gdp, "t,");
+              if ( xyz == 321 )
+                {
+                  if ( nlev > 0 ) fprintf(gdp, "z,");
+                  fprintf(gdp, "y,x");
+                }
+              else if ( xyz == 312 )
+                {
+                  if ( nlev > 0 ) fprintf(gdp, "z,");
+                  fprintf(gdp, "x,y");
+                }
+              else if ( xyz == 231 )
+                {
+                  fprintf(gdp, "y,");
+                  if ( nlev > 0 ) fprintf(gdp, "z,");
+                  fprintf(gdp, "x");
+                }
+              else if ( xyz == 132 )
+                {
+                  fprintf(gdp, "x,");
+                  if ( nlev > 0 ) fprintf(gdp, "z,");
+                  fprintf(gdp, "y");
+                }
+              else
+                {
+                  if ( nlev > 0 ) fprintf(gdp, "z,");
+                  fprintf(gdp, "y,x");
+                }
+            }
+          else
+            fprintf(gdp, "  99");
+
+          if ( varlongname[0] == 0 )
+            fprintf(gdp, "  %s", varname);
+          else
+            fprintf(gdp, "  %s", varlongname);
+
+          if ( varunits[0] != 0 )
+            fprintf(gdp, "  [%s]", varunits);
+
+          fprintf(gdp, "\n");
+        }
     }
 
   fprintf(gdp, "ENDVARS\n");
@@ -834,71 +835,71 @@ void write_map_grib1(const char *ctlfile, int map_version, int nrecords, int *in
       float fdum;
       unsigned char *map;
       unsigned char ibmfloat[4];
-      
+
       /* calculate the size of the ver==1 index file */
-      
+
       nb = 2 + (indx.hinum*4) +  /* version in byte 2, then 4 ints with number of each data type */
-	indx.hinum*sizeof(int) +
-	indx.hfnum*sizeof(int) +
-	indx.intnum*sizeof(int) +
-	indx.fltnum*sizeof(float);
-      
+        indx.hinum*sizeof(int) +
+        indx.hfnum*sizeof(int) +
+        indx.intnum*sizeof(int) +
+        indx.fltnum*sizeof(float);
+
       /* add additional info */
-      
+
       nb += 7;      /* base time (+ sec)  for compatibility with earlier version 2 maps */
       nb += 8*4;    /* grvals for time <-> grid conversion */
-      
+
       map = (unsigned char*) malloc(nb);
-      
+
       bcnt = 0;
       Put1Byte(map, bcnt, 0);
       Put1Byte(map, bcnt, map_version);
-      
+
       Put4Byte(map, bcnt, indx.hinum);
       Put4Byte(map, bcnt, indx.hfnum);
       Put4Byte(map, bcnt, indx.intnum);
       Put4Byte(map, bcnt, indx.fltnum);
-      
+
       Put2Byte(map, bcnt, 0);   /* initial year   */
-      Put1Byte(map, bcnt, 0);   /* initial month  */ 
+      Put1Byte(map, bcnt, 0);   /* initial month  */
       Put1Byte(map, bcnt, 0);   /* initial day    */
       Put1Byte(map, bcnt, 0);   /* initial hour   */
       Put1Byte(map, bcnt, 0);   /* initial minute */
       Put1Byte(map, bcnt, 0);   /* initial second */
-      
+
       if( indx.hinum )
-	for ( i = 0; i < indx.hinum; i++ )
-	  Put4Byte(map, bcnt, hinum[i]);
-      
+        for ( i = 0; i < indx.hinum; i++ )
+          Put4Byte(map, bcnt, hinum[i]);
+
       if( indx.hfnum ) {
-	/* blank for now */
+        /* blank for now */
       }
-      
+
       for ( i = 0; i < nrecords; i++ )
-	{
-	  PutInt(map, bcnt, (int) bignum[i*2]);
-	  PutInt(map, bcnt, (int) bignum[i*2+1]);
-	  PutInt(map, bcnt, intnum[i]);
-	}
+        {
+          PutInt(map, bcnt, (int) bignum[i*2]);
+          PutInt(map, bcnt, (int) bignum[i*2+1]);
+          PutInt(map, bcnt, intnum[i]);
+        }
 
       for ( i = 0; i < indx.fltnum; i++)
-	{
-	  fdum= fltnum[i];
-	  rc = flt2ibm(fdum, ibmfloat); 
-	  if ( rc < 0 ) cdoAbort("overflow in IBM float conversion");
-	  for ( j = 0; j < 4; j++ ) map[bcnt++] = ibmfloat[j];
-	}
-      
-      /* write out the factors for converting from grid to absolute time */ 
-      
+        {
+          fdum= fltnum[i];
+          rc = flt2ibm(fdum, ibmfloat);
+          if ( rc < 0 ) cdoAbort("overflow in IBM float conversion");
+          for ( j = 0; j < 4; j++ ) map[bcnt++] = ibmfloat[j];
+        }
+
+      /* write out the factors for converting from grid to absolute time */
+
       for ( i = 0; i < 8; i++)
-	{
-	  fdum = 0;
-	  rc = flt2ibm(fdum, ibmfloat); 
-	  if ( rc < 0 ) cdoAbort("overflow in IBM float conversion");
-	  for ( j = 0; j < 4; j++ ) map[bcnt++] = ibmfloat[j];
-	}
-      
+        {
+          fdum = 0;
+          rc = flt2ibm(fdum, ibmfloat);
+          if ( rc < 0 ) cdoAbort("overflow in IBM float conversion");
+          for ( j = 0; j < 4; j++ ) map[bcnt++] = ibmfloat[j];
+        }
+
       fwrite(map, 1, bcnt, mapfp);
 
       free(map);
@@ -908,31 +909,99 @@ void write_map_grib1(const char *ctlfile, int map_version, int nrecords, int *in
       fwrite(&indx, sizeof(struct gaindx), 1, mapfp);
       if ( indx.hinum > 0 )  fwrite(hinum, sizeof(int), indx.hinum, mapfp);
       if ( map_version == 1 )
-	{
-	  int *intnumbuf;
-	  intnumbuf = (int*) malloc(indx.intnum*sizeof(int));
-	  for ( i = 0; i < nrecords; i++ )
-	    {
-	      intnumbuf[i*3+0] = (int) bignum[i*2];
-	      intnumbuf[i*3+1] = (int) bignum[i*2+1];
-	      intnumbuf[i*3+2] = intnum[i];
-	    }
-	  if ( indx.intnum > 0 ) fwrite(intnumbuf, sizeof(int), indx.intnum, mapfp);
-	  free(intnumbuf);
-	  if ( indx.fltnum > 0 ) fwrite(fltnum, sizeof(float), indx.fltnum, mapfp);
-	}
+        {
+          int *intnumbuf;
+          intnumbuf = (int*) malloc(indx.intnum*sizeof(int));
+          for ( i = 0; i < nrecords; i++ )
+            {
+              intnumbuf[i*3+0] = (int) bignum[i*2];
+              intnumbuf[i*3+1] = (int) bignum[i*2+1];
+              intnumbuf[i*3+2] = intnum[i];
+            }
+          if ( indx.intnum > 0 ) fwrite(intnumbuf, sizeof(int), indx.intnum, mapfp);
+          free(intnumbuf);
+          if ( indx.fltnum > 0 ) fwrite(fltnum, sizeof(float), indx.fltnum, mapfp);
+        }
       else
-	{
-	  if ( indx.intnum  > 0 ) fwrite(intnum, sizeof(int), indx.intnum, mapfp);
-	  if ( indx.fltnum  > 0 ) fwrite(fltnum, sizeof(float), indx.fltnum, mapfp);
-	  if ( indxb.bignum > 0 ) fwrite(bignum, sizeof(off_t), indxb.bignum, mapfp);
-	}
+        {
+          if ( indx.intnum  > 0 ) fwrite(intnum, sizeof(int), indx.intnum, mapfp);
+          if ( indx.fltnum  > 0 ) fwrite(fltnum, sizeof(float), indx.fltnum, mapfp);
+          if ( indxb.bignum > 0 ) fwrite(bignum, sizeof(off_t), indxb.bignum, mapfp);
+        }
     }
-  
+
   fclose(mapfp);
 }
 
 
+/*
+ * Remove file extension:
+ * -------------------------------------------------
+ * Remove file extension if it is the expected one
+ * Do nothing otherwise
+ */
+static
+void rm_ext(char *file, const char *ext)
+{
+  // length of filename
+  int namelen = (int) strlen(file);
+  // length of the original file extension
+  int extlen =  (int) strlen(ext);
+
+  // delete original extension if it is the expected one
+  if ( strcmp(&file[namelen-extlen], ext) == 0 )
+      file[namelen-extlen] = 0;
+}
+
+
+/* 
+ * Return the filetype extension
+ * for a given filetype (int)
+ * TODO this general function should be somewhere else
+ */
+static
+const char *filetypeext(int filetype)
+{
+  switch ( filetype )
+    {
+    case FILETYPE_GRB:
+    case FILETYPE_GRB2: return (".grb");   break;
+    case FILETYPE_NC:
+    case FILETYPE_NC2:
+    case FILETYPE_NC4:
+    case FILETYPE_NC4C: return (".nc");    break;
+    case FILETYPE_SRV:  return (".srv");   break;
+    case FILETYPE_EXT:  return (".ext");   break;
+    case FILETYPE_IEG:  return (".ieg");   break;
+    default:            return ("");
+    }
+}
+
+
+/*
+ * Replace or just add file extension:
+ * -------------------------------------------------
+ * Replace file extension with new one
+ * or just add the new file extension 
+ * if the original extension is not the expected one
+ */
+static
+void repl_filetypeext(char *file, const char *oldext, const char *newext)
+{
+  // delete original extension if it is the expected one
+  rm_ext(file, oldext);
+
+  // add new file extension
+  strcat(file, newext);
+}
+
+
+static
+void write_map_grib2(const char *ctlfile, int map_version, int nrecords, int *intnum, float *fltnum, off_t *bignum)
+{
+    // to be implemented
+}
+
 void *Gradsdes(void *argument)
 {
   int GRADSDES, DUMPMAP;
@@ -951,6 +1020,7 @@ void *Gradsdes(void *argument)
   int vdate, vtime;
   const char *datfile;
   char ctlfile[1024], *pctlfile;
+  char idxfile[1024], *pidxfile;
   int len;
   char varname[CDI_MAX_NAME];
   FILE *gdp;
@@ -962,6 +1032,7 @@ void *Gradsdes(void *argument)
   int nrecords = 0;
   int bigendian = FALSE, littleendian = FALSE;
   int flt64 = 0;
+  int cal365day = 0;
   int sequential = FALSE;
   char Time[30], Incr[10] = {"1mn"}, *IncrKey[] = {"mn","hr","dy","mo","yr"};
   int isd, imn, ihh, iyy, imm, idd;
@@ -984,7 +1055,7 @@ void *Gradsdes(void *argument)
   off_t *bignum = NULL;
   double *array = NULL;
   const char *cmons[]={"jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
-      
+
   cdoInitialize(argument);
 
   GRADSDES  = cdoOperatorAdd("gradsdes",  0, 0, NULL);
@@ -1008,7 +1079,7 @@ void *Gradsdes(void *argument)
     {
       map_version = atoi(operatorArgv()[0]);
       if ( map_version != 1 && map_version != 2 && map_version != 4 )
-	cdoAbort("map_version=%d unsupported!", map_version);
+        cdoAbort("map_version=%d unsupported!", map_version);
     }
   else
     {
@@ -1019,8 +1090,8 @@ void *Gradsdes(void *argument)
 
   if ( map_version == 4 && sizeof(off_t) != 8 )
     cdoAbort("GrADS GRIB map version %d requires size of off_t to be 8! The size of off_t is %ld.",
-	     map_version, sizeof(off_t));
- 
+             map_version, sizeof(off_t));
+
 
   streamID = streamOpenRead(cdoStreamName(0));
 
@@ -1041,12 +1112,13 @@ void *Gradsdes(void *argument)
        filetype != FILETYPE_GRB )
     {
       if ( filetype == FILETYPE_NC )
-	//	cdoAbort("Unsupported file format: netCDF");
-	;
+        //        cdoAbort("Unsupported file format: netCDF");
+        ;
       else if ( filetype == FILETYPE_GRB2 )
-	cdoAbort("Unsupported file format: GRIB2");
+        //cdoAbort("Unsupported file format: GRIB2");
+        ;
       else
-	cdoAbort("Unsupported file format!");
+        cdoAbort("Unsupported file format!");
     }
 
   /* find the first lonlat or Gaussian grid */
@@ -1055,8 +1127,8 @@ void *Gradsdes(void *argument)
       gridID = vlistGrid(vlistID, index);
       gridtype = gridInqType(gridID);
       if ( gridtype == GRID_LONLAT   ||
-	   gridtype == GRID_GAUSSIAN ||
-	   gridtype == GRID_LCC  ) break;
+           gridtype == GRID_GAUSSIAN ||
+           gridtype == GRID_LCC  ) break;
     }
 
   if ( index == ngrids )
@@ -1070,33 +1142,33 @@ void *Gradsdes(void *argument)
   for ( varID = 0; varID < nvars; varID++ )
     {
       if ( vlistInqVarGrid(vlistID, varID) == gridID )
-	{
-	  if ( filetype == FILETYPE_SRV ||
-	       filetype == FILETYPE_EXT ||
-	       filetype == FILETYPE_IEG )
-	    {
-	      prec = vlistInqVarDatatype(vlistID, varID);
-	      if ( prec == DATATYPE_FLT64 ) flt64 = 1;
-	    }
-	  vars[varID] = TRUE;
-	  recoffset[varID] = nrecsout;
-	  nvarsout++;
-	  nrecsout += zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
-	  if ( ntsteps != 1 && ntsteps != 0 && vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT )
-	    cdoAbort("Unsupported GrADS record structure! Variable %d has only 1 time step.",
-		     vlistInqVarCode(vlistID, varID));
-	}
+        {
+          if ( filetype == FILETYPE_SRV ||
+               filetype == FILETYPE_EXT ||
+               filetype == FILETYPE_IEG )
+            {
+              prec = vlistInqVarDatatype(vlistID, varID);
+              if ( prec == DATATYPE_FLT64 ) flt64 = 1;
+            }
+          vars[varID] = TRUE;
+          recoffset[varID] = nrecsout;
+          nvarsout++;
+          nrecsout += zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
+          if ( ntsteps != 1 && ntsteps != 0 && vlistInqVarTsteptype(vlistID, varID) == TSTEP_CONSTANT )
+            cdoAbort("Unsupported GrADS record structure! Variable %d has only 1 time step.",
+                     vlistInqVarCode(vlistID, varID));
+        }
       else
-	{
-	  vlistInqVarName(vlistID, varID, varname);
-	  cdoPrint("Unsupported grid type >%s<, skipped variable %s!",
-		   gridNamePtr(gridInqType(vlistInqVarGrid(vlistID, varID))), varname);
-	  vars[varID] = FALSE;
-	}
+        {
+          vlistInqVarName(vlistID, varID, varname);
+          cdoPrint("Unsupported grid type >%s<, skipped variable %s!",
+                   gridNamePtr(gridInqType(vlistInqVarGrid(vlistID, varID))), varname);
+          vars[varID] = FALSE;
+        }
     }
 
   if ( filetype != FILETYPE_GRB && nvars != nvarsout )
-    cdoAbort("Too many different grids!");    
+    cdoAbort("Too many different grids!");
 
   if ( filetype == FILETYPE_SRV )
     {
@@ -1125,33 +1197,21 @@ void *Gradsdes(void *argument)
       if ( byteorder == CDI_LITTLEENDIAN ) littleendian = TRUE;
     }
 
+  /* ctl file name */
   strcpy(ctlfile, cdoStreamName(0)->args);
-  len = (int) strlen(ctlfile);
-  if ( len > 4 )
-    {
-      if ( filetype == FILETYPE_SRV )
-	if ( strcmp(&ctlfile[len-4], ".srv") == 0 ) ctlfile[len-4] = 0;
-      if ( filetype == FILETYPE_EXT )
-	if ( strcmp(&ctlfile[len-4], ".ext") == 0 ) ctlfile[len-4] = 0;
-      if ( filetype == FILETYPE_IEG )
-	if ( strcmp(&ctlfile[len-4], ".ieg") == 0 ) ctlfile[len-4] = 0;
-      if ( filetype == FILETYPE_GRB )
-	if ( strcmp(&ctlfile[len-4], ".grb") == 0 ) ctlfile[len-4] = 0;
-      if ( filetype == FILETYPE_NC )
-	if ( strcmp(&ctlfile[len-3], ".nc") == 0 ) ctlfile[len-3] = 0;
-    }
+  repl_filetypeext(ctlfile, filetypeext(filetype), ".ctl");
 
-  strcat(ctlfile, ".ctl");
+  /* open ctl file*/
   gdp = fopen(ctlfile, "w");
   if ( gdp == NULL ) cdoAbort("Open failed on %s", ctlfile);
 
+  /* VERSION */
 #if defined(VERSION)
   fprintf(gdp, "* Generated by CDO version %s\n", VERSION);
   fprintf(gdp, "*\n");
 #endif
 
   /* DSET */
-
   datfile = cdoStreamName(0)->args;
   if ( datfile[0] == '/' )
     fprintf(gdp, "DSET  %s\n", datfile);
@@ -1159,28 +1219,52 @@ void *Gradsdes(void *argument)
     {
       datfile = strrchr(datfile, '/');
       if ( datfile == 0 ) datfile = cdoStreamName(0)->args;
-      else                datfile++;	  
+      else                datfile++;
       fprintf(gdp, "DSET  ^%s\n", datfile);
     }
 
-  /* DTYPE */
+  /*
+   * DTYPE Print file type
+   * INDEX Print filename of the control file .ctl
+   */
   if ( filetype == FILETYPE_GRB )
     {
       fprintf(gdp, "DTYPE  GRIB\n");
 
       pctlfile = ctlfile;
-      len = (int) strlen(pctlfile);
-      strcpy(&pctlfile[len-4], ".gmp");
-      
+      repl_filetypeext(pctlfile, ".ctl", ".gmp");
+
       if ( datfile[0] == '/' )
-	fprintf(gdp, "INDEX  %s\n", pctlfile);
+        fprintf(gdp, "INDEX  %s\n", pctlfile);
       else
-	{
-	  pctlfile = strrchr(pctlfile, '/');
-	  if ( pctlfile == 0 ) pctlfile = ctlfile;
-	  else                 pctlfile++;	  
-	  fprintf(gdp, "INDEX  ^%s\n", pctlfile);
-	}
+        {
+          pctlfile = strrchr(pctlfile, '/');
+          if ( pctlfile == 0 ) pctlfile = ctlfile;
+          else                 pctlfile++;
+          fprintf(gdp, "INDEX  ^%s\n", pctlfile);
+        }
+
+      gridsize = vlistGridsizeMax(vlistID);
+      array = (double*) malloc(gridsize*sizeof(double));
+    }
+  else if ( filetype ==  FILETYPE_GRB2 )
+    {
+      fprintf(gdp, "DTYPE  GRIB2\n");
+
+      strcpy(idxfile, ctlfile);
+      pidxfile = idxfile;
+      repl_filetypeext(pidxfile, ".ctl", ".idx");
+
+      if ( datfile[0] == '/' )
+        fprintf(gdp, "INDEX  %s\n", pidxfile);
+      else
+        {
+          pidxfile = strrchr(pidxfile, '/');
+          if ( pidxfile == 0 ) pidxfile = idxfile;
+          else                 pidxfile++;
+          fprintf(gdp, "INDEX  ^%s\n", pidxfile);
+        }
+
 
       gridsize = vlistGridsizeMax(vlistID);
       array = (double*) malloc(gridsize*sizeof(double));
@@ -1197,6 +1281,9 @@ void *Gradsdes(void *argument)
 
   taxisID = vlistInqTaxis(vlistID);
 
+  int calendar = taxisInqCalendar(taxisID);
+  if ( calendar == CALENDAR_365DAYS ) cal365day = 1;
+
   tsID = 0;
   while ( (nrecs = streamInqTimestep(streamID, tsID)) )
     {
@@ -1204,128 +1291,128 @@ void *Gradsdes(void *argument)
       vtime = taxisInqVtime(taxisID);
 
       if ( tsID == 0 )
-	{
-	  cdiDecodeDate(vdate, &iyys, &imms, &idds);
-	  cdiDecodeTime(vtime, &ihhs, &imns, &isds);
-     
-	  if ( imms < 1 || imms > 12 )  imms=1;
-
-	  ihh0 = ihhs;
-	  imn0 = imns;
-	  iyy0 = iyys;
-	  imm0 = imms;
-	  idd0 = idds;
-	}
+        {
+          cdiDecodeDate(vdate, &iyys, &imms, &idds);
+          cdiDecodeTime(vtime, &ihhs, &imns, &isds);
+
+          if ( imms < 1 || imms > 12 )  imms=1;
+
+          ihh0 = ihhs;
+          imn0 = imns;
+          iyy0 = iyys;
+          imm0 = imms;
+          idd0 = idds;
+        }
 
       if ( tsID == 1 )
-	{
-	  cdiDecodeDate(vdate, &iyy, &imm, &idd);
-	  cdiDecodeTime(vtime, &ihh, &imn, &isd);
-
-	  idmn = imn - imns;
-	  idhh = ihh - ihhs;
-	  iddd = idd - idds;
-	  idmm = imm - imms;
-	  idyy = iyy - iyys;
-
-	  if ( idmn != 0 )
-	    {
-	      dt = idmn + (idhh + (iddd + (idmm*30 + idyy*12)*30)*24)*60;
-	    }
-	  else if ( idhh != 0 )
-	    {
-	      dt = idhh + (iddd + (idmm + idyy*12)*30)*24;
-	      iik = 1;
-	    }
-	  else if ( iddd != 0 )
-	    {
-	      dt = iddd + (idmm + idyy*12)*30;
-	      iik = 2;
-	    }
-	  else if ( idmm != 0 )
-	    {
-	      dt = idmm + idyy*12;
-	      iik = 3;
-	    }
-	  else if ( idyy != 0 )
-	    {
-	      dt = idyy;
-	      iik = 4;
-	    }
-
-	  if ( dt <= 0 ) dt = 1;
-	}
+        {
+          cdiDecodeDate(vdate, &iyy, &imm, &idd);
+          cdiDecodeTime(vtime, &ihh, &imn, &isd);
+
+          idmn = imn - imns;
+          idhh = ihh - ihhs;
+          iddd = idd - idds;
+          idmm = imm - imms;
+          idyy = iyy - iyys;
+
+          if ( idmn != 0 )
+            {
+              dt = idmn + (idhh + (iddd + (idmm*30 + idyy*12)*30)*24)*60;
+            }
+          else if ( idhh != 0 )
+            {
+              dt = idhh + (iddd + (idmm + idyy*12)*30)*24;
+              iik = 1;
+            }
+          else if ( iddd != 0 )
+            {
+              dt = iddd + (idmm + idyy*12)*30;
+              iik = 2;
+            }
+          else if ( idmm != 0 )
+            {
+              dt = idmm + idyy*12;
+              iik = 3;
+            }
+          else if ( idyy != 0 )
+            {
+              dt = idyy;
+              iik = 4;
+            }
+
+          if ( dt <= 0 ) dt = 1;
+        }
 
       if ( tsID > 0 && tsID < 6 && iik != 3 && (monavg == TRUE || monavg == -1) )
-	{
-	  cdiDecodeDate(vdate, &iyy, &imm, &idd);
-	  cdiDecodeTime(vtime, &ihh, &imn, &isd);
-
-	  idmn = imn - imns;
-	  idhh = ihh - ihhs;
-	  iddd = idd - idds;
-	  idmm = imm - imms;
-	  idyy = iyy - iyys;
-
-	  if ( iddd < 0 ) iddd *= -1;
-	  if ( idyy > 0 ) idmm += idyy*12;
-
-	  if ( idmn == 0 && idhh == 0 && (iddd == 0 || idd > 27 ) &&
-	       idmm > 0 && (mdt == 0 || idmm == mdt) )
-	    {
-	      mdt = idmm;
-	      monavg = TRUE;
-	    }
-	  else
-	    {
-	      monavg = FALSE;
-	    }
-	  /*
-	  printf("monavg %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
-		 tsID, monavg, mdt, imm , imms, idmm, iyy, iyys, idyy, idd, idds, iddd);
-	  */
+        {
+          cdiDecodeDate(vdate, &iyy, &imm, &idd);
+          cdiDecodeTime(vtime, &ihh, &imn, &isd);
+
+          idmn = imn - imns;
+          idhh = ihh - ihhs;
+          iddd = idd - idds;
+          idmm = imm - imms;
+          idyy = iyy - iyys;
+
+          if ( iddd < 0 ) iddd *= -1;
+          if ( idyy > 0 ) idmm += idyy*12;
+
+          if ( idmn == 0 && idhh == 0 && (iddd == 0 || idd > 27 ) &&
+               idmm > 0 && (mdt == 0 || idmm == mdt) )
+            {
+              mdt = idmm;
+              monavg = TRUE;
+            }
+          else
+            {
+              monavg = FALSE;
+            }
+          /*
+          printf("monavg %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
+                 tsID, monavg, mdt, imm , imms, idmm, iyy, iyys, idyy, idd, idds, iddd);
+          */
           imns = imn;
           ihhs = ihh;
-	  idds = idd;
+          idds = idd;
           imms = imm;
           iyys = iyy;
-	}
+        }
 
       if ( filetype == FILETYPE_GRB )
-	{
-	  nrecords += nrecsout;
-	  if ( nrecords >= maxrecs )
-	    {
-	      maxrecs = nrecords;
-	      intnum = (int*) realloc(intnum, 1*maxrecs*sizeof(int));
-	      fltnum = (float*) realloc(fltnum, 3*maxrecs*sizeof(float));
-	      bignum = (off_t*) realloc(bignum, 2*maxrecs*sizeof(off_t));
-	    }
-
-	  for ( recID = 0; recID < nrecs; recID++ )
-	    {
-	      streamInqRecord(streamID, &varID, &levelID);
-	      if ( vars[varID] == TRUE )
-		{
-		  streamReadRecord(streamID, array, &nmiss);
-
-		  index = (tsID*nrecsout + recoffset[varID] + levelID);
-	      
-		  streamInqGinfo(streamID, &intnum[index], &fltnum[index*3], &bignum[index*2]);
-
-		  if ( map_version != 4 )
-		    {
-		      checksize = (long)bignum[index*2] + (long)gridsize*intnum[index]/8;
-		      if ( checksize < 0L || checksize > 2147483647L )
-			{
-			  nrecords -= nrecsout;
-			  cdoWarning("File size limit reached for GrADS GRIB map_version=%d! Only the first %d time steps (2GB) are processed.", map_version, tsID);
-			  goto LABEL_STOP;
-			}
-		    }
-		}
-	    }
-	}
+        {
+          nrecords += nrecsout;
+          if ( nrecords >= maxrecs )
+            {
+              maxrecs = nrecords;
+              intnum = (int*) realloc(intnum, 1*maxrecs*sizeof(int));
+              fltnum = (float*) realloc(fltnum, 3*maxrecs*sizeof(float));
+              bignum = (off_t*) realloc(bignum, 2*maxrecs*sizeof(off_t));
+            }
+
+          for ( recID = 0; recID < nrecs; recID++ )
+            {
+              streamInqRecord(streamID, &varID, &levelID);
+              if ( vars[varID] == TRUE )
+                {
+                  streamReadRecord(streamID, array, &nmiss);
+
+                  index = (tsID*nrecsout + recoffset[varID] + levelID);
+
+                  streamInqGRIBinfo(streamID, &intnum[index], &fltnum[index*3], &bignum[index*2]);
+
+                  if ( map_version != 4 )
+                    {
+                      checksize = (long)bignum[index*2] + (long)gridsize*intnum[index]/8;
+                      if ( checksize < 0L || checksize > 2147483647L )
+                        {
+                          nrecords -= nrecsout;
+                          cdoWarning("File size limit reached for GrADS GRIB map_version=%d! Only the first %d time steps (2GB) are processed.", map_version, tsID);
+                          goto LABEL_STOP;
+                        }
+                    }
+                }
+            }
+        }
 
       tsID++;
     }
@@ -1345,12 +1432,12 @@ void *Gradsdes(void *argument)
       dt = mdt;
       iik = 3;
       if ( idd0 > 28 )
-	{
-	  /* int iddx = idd0; */
-	  idd0 = 1;
-	  cdoPrint("Reset start date to %02d:%02dZ%02d%s%04d",
-		   ihh0, imn0, idd0, cmons[imm0-1], iyy0);
-	}
+        {
+          /* int iddx = idd0; */
+          idd0 = 1;
+          cdoPrint("Reset start date to %02d:%02dZ%02d%s%04d",
+                   ihh0, imn0, idd0, cmons[imm0-1], iyy0);
+        }
     }
 
   sprintf (Time, "%02d:%02dZ%02d%s%04d", ihh0, imn0, idd0, cmons[imm0-1], iyy0);
@@ -1372,7 +1459,7 @@ void *Gradsdes(void *argument)
     fprintf(gdp, "TITLE  %s  %dx%d grid\n", datfile, xsize, ysize);
 
   /* OPTIONS */
-  ctl_options(gdp, yrev, zrev, sequential, bigendian, littleendian, flt64);
+  ctl_options(gdp, yrev, zrev, sequential, bigendian, littleendian, flt64, cal365day);
 
   /* UNDEF */
   ctl_undef(gdp, vlistID);
@@ -1386,6 +1473,11 @@ void *Gradsdes(void *argument)
     {
       write_map_grib1(ctlfile, map_version, nrecords, intnum, fltnum, bignum);
     }
+  if ( filetype == FILETYPE_GRB2 )
+    {
+      cdoAbort("\nThe fileformat GRIB2 is not fully supported yet\nfor the gradsdes operator.\nThe .ctl file %s was generated.\nYou can add the necessary .idx file by running\n\tgribmap -i %s", ctlfile, ctlfile);
+      write_map_grib2(idxfile, map_version, nrecords, intnum, fltnum, bignum);
+    }
 
 
   streamClose(streamID);
diff --git a/src/Gridboxstat.c b/src/Gridboxstat.c
index aadbeb6..0c52ab3 100644
--- a/src/Gridboxstat.c
+++ b/src/Gridboxstat.c
@@ -27,9 +27,6 @@
       Gridboxstat    gridboxvar          Gridbox variance
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
 
 #include <cdi.h>
 #include "cdo.h"
@@ -533,7 +530,6 @@ void gridboxstat(field_t *field1, field_t *field2, int xinc, int yinc, int statf
   double missval;
   long ig, i, j, ii, jj, index;
   long gridsize;
-  long ompthID;
   field_t *field;
   int isize;
   int useWeight = FALSE;
@@ -570,22 +566,19 @@ void gridboxstat(field_t *field1, field_t *field2, int xinc, int yinc, int statf
   nlat2 = gridInqYsize(gridID2);
 
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(ig, ilat, ilon, j, jj, i, ii, index, isize, ompthID)
+#pragma omp parallel for default(shared) private(ig, ilat, ilon, j, jj, i, ii, index, isize)
 #endif
   for ( ig = 0; ig < nlat2*nlon2; ++ig )
     {
-#if defined(_OPENMP)
-      ompthID = omp_get_thread_num();
-#else
-      ompthID = 0;
-#endif
+      int ompthID = cdo_omp_get_thread_num();
+
       /*
       int lprogress = 1;
 #if defined(_OPENMP)
       if ( ompthID != 0 ) lprogress = 0;
 #endif
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/nlat2*nlon2);
@@ -639,16 +632,16 @@ void *Gridboxstat(void *argument)
   int vlistID1, vlistID2;
   int lastgrid = -1;
   int wstatus = FALSE;
-  int code = 0, oldcode = 0;
   int index, ngrids;
   int recID, nrecs;
   int tsID, varID, levelID;
   int needWeights = FALSE;
   int gridID1, gridID2;
   int gridsize1, gridsize2;
-  field_t field1, field2;
   int taxisID1, taxisID2;
   int xinc, yinc;
+  field_t field1, field2;
+  char varname[CDI_MAX_NAME];
 
   cdoInitialize(argument);
 
@@ -734,9 +727,11 @@ void *Gridboxstat(void *argument)
 	      lastgrid = field1.grid;
               wstatus = gridWeights(field1.grid, field1.weight);
             }
-          code = vlistInqVarCode(vlistID1, varID);
-          if ( wstatus != 0 && tsID == 0 && code != oldcode )
-            cdoWarning("Using constant grid cell area weights for code %d!", oldcode=code);
+          if ( wstatus != 0 && tsID == 0 && levelID == 0 )
+	    {
+	      vlistInqVarName(vlistID1, varID, varname);
+	      cdoWarning("Using constant grid cell area weights for variable %s!", varname);
+	    }
           
           gridboxstat(&field1, &field2, xinc, yinc, operfunc);
           
diff --git a/src/Gridcell.c b/src/Gridcell.c
index bc2445b..883b5cd 100644
--- a/src/Gridcell.c
+++ b/src/Gridcell.c
@@ -51,7 +51,6 @@ void *Gridcell(void *argument)
   int need_radius;
   int tsID, varID, levelID, taxisID;
   long i, gridsize;
-  char *envstr;
   double *array = NULL;
   double  EarthRadius = 6371000; /* default radius of the earth in m */
   double PlanetRadius = EarthRadius;
@@ -70,20 +69,16 @@ void *Gridcell(void *argument)
 
   if ( need_radius )
     {
-      envstr = getenv("PLANET_RADIUS");
+      char *envstr = getenv("PLANET_RADIUS");
       if ( envstr )
 	{
-	  double fval;
-	  fval = atof(envstr);
-	  if ( fval > 0 )
-	    {
-	      PlanetRadius = fval;
-	      if ( cdoVerbose )
-		cdoPrint("Set PlanetRadius to %g", PlanetRadius);
-	    }
+	  double fval = atof(envstr);
+	  if ( fval > 0 ) PlanetRadius = fval;
 	}
     }
 
+  if ( cdoVerbose ) cdoPrint("PlanetRadius: %g", PlanetRadius);
+
   streamID1 = streamOpenRead(cdoStreamName(0));
 
   vlistID1 = streamInqVlist(streamID1);
diff --git a/src/Gridsearch.c b/src/Gridsearch.c
new file mode 100644
index 0000000..ab56a1d
--- /dev/null
+++ b/src/Gridsearch.c
@@ -0,0 +1,42 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2014 Uwe Schulzweida, Uwe.Schulzweida at zmaw.de
+  See COPYING file for copying and redistribution conditions.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+*/
+
+#include <cdi.h>
+#include "cdo.h"
+#include "cdo_int.h"
+#include "pstream.h"
+
+
+
+void *Gridsearch(void *argument)
+{
+  int gridID1, gridID2;
+
+  cdoInitialize(argument);
+
+  cdoOperatorAdd("testpointsearch",  0,   0, NULL);
+  cdoOperatorAdd("testcellsearch",   0,   0, NULL);
+
+  operatorInputArg("source and target grid description file or name");
+  operatorCheckArgc(2);
+  gridID1 = cdoDefineGrid(operatorArgv()[0]);
+  gridID2 = cdoDefineGrid(operatorArgv()[1]);
+
+  cdoFinish();
+
+  return (0);
+}
diff --git a/src/Intlevel3d.c b/src/Intlevel3d.c
index 46a59e1..8b0ff5f 100644
--- a/src/Intlevel3d.c
+++ b/src/Intlevel3d.c
@@ -228,18 +228,16 @@ void *Intlevel3d(void *argument)
 
   operatorID = cdoOperatorID();
 
-  if ( cdoVerbose ) 
-    cdoPrint("Called '%s'\n",__func__);
-
-  if ( operatorID == INTLEVELX3D ) expol = TRUE;
+  if      ( operatorID == INTLEVEL3D )  expol = FALSE;
+  else if ( operatorID == INTLEVELX3D ) expol = TRUE;
 
   operatorInputArg("icoordinate");
 
   /*  Read filename from Parameter */
-  operatorInputArg("grid description file or name, remap file (SCRIP netCDF)");
+  operatorInputArg("filename for vertical source coordinates variable");
   operatorCheckArgc(1);
   argument_t *fileargument = file_argument_new(operatorArgv()[0]);
-  streamID0 = streamOpenRead(fileargument);                /*  3d vertical input coordinate */
+  streamID0 = streamOpenRead(fileargument);                     /*  3d vertical input coordinate */
   file_argument_free(fileargument);
   streamID1 = streamOpenRead(cdoStreamName(0));                 /*  input data */
   streamID2 = streamOpenRead(cdoStreamName(1));                 /*  3d target vertical coordinate */
@@ -257,8 +255,8 @@ void *Intlevel3d(void *argument)
    */
   {
     nvars = vlistNvars(vlistID0);
-    if (nvars != 1) 
-      cdoAbort("Only one single variable is allowed!");
+    if (nvars != 1) cdoAbort("Only one single variable is allowed!");
+
     gridID     = vlistInqVarGrid(vlistID0, 0);
     zaxisID    = vlistInqVarZaxis(vlistID0, 0);
     gridsize   = gridInqSize(gridID);
@@ -275,10 +273,9 @@ void *Intlevel3d(void *argument)
     nlevi      = nlevel;   /* number of input levels for later use */
     gridsizei  = gridsize; /* horizontal gridsize of input z coordinate */
     nrecs      = streamInqTimestep(streamID0, 0);
-    if (cdoVerbose)
-      cdoPrint("%d records input 3d vertical height\n",nrecs);
-    {
-      for ( recID = 0; recID < nrecs; recID++ )
+    if (cdoVerbose) cdoPrint("%d records input 3d vertical height\n",nrecs);
+
+    for ( recID = 0; recID < nrecs; recID++ )
       {
         streamInqRecord(streamID0, &varID, &levelID);
         gridsize = gridInqSize(vlistInqVarGrid(vlistID0, varID));
@@ -286,7 +283,6 @@ void *Intlevel3d(void *argument)
         single1  = zlevels_in + offset;
         streamReadRecord(streamID0, single1, &zlevels_in_miss);
       }
-    }
   }
 
   /*
@@ -311,17 +307,16 @@ void *Intlevel3d(void *argument)
     nlevo       = nlevel;  /* number of output levels for later use */
     gridsizeo   = gridsize;/* horizontal gridsize of output z coordinate */
     nrecs       = streamInqTimestep(streamID2, 0);
-    if (cdoVerbose)
-      cdoPrint("%d records target 3d vertical height and gridsize %d\n",nrecs,gridsize);
+    if (cdoVerbose) cdoPrint("%d records target 3d vertical height and gridsize %d\n",nrecs,gridsize);
 
     for ( recID = 0; recID < nrecs; recID++ )
-    {
-      streamInqRecord(streamID2, &varID, &levelID);
-      gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
-      offset   = gridsize*levelID;
-      single1  = zlevels_out + offset;
-      streamReadRecord(streamID2, single1, &zlevels_out_miss);
-    }
+      {
+	streamInqRecord(streamID2, &varID, &levelID);
+	gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
+	offset   = gridsize*levelID;
+	single1  = zlevels_out + offset;
+	streamReadRecord(streamID2, single1, &zlevels_out_miss);
+      }
   }
 
   /* Missing values are not allowed for coordinate variables */
@@ -331,6 +326,7 @@ void *Intlevel3d(void *argument)
     {
       if ( cdoVerbose ) cdoPrint("Input vertical coordinate has no missing values.");
     }
+
   if ( 0 != zlevels_out_miss )
     cdoAbort("Output vertical coordinate variables are not allowd to contian missing values.");
   else
@@ -345,10 +341,10 @@ void *Intlevel3d(void *argument)
    */
   if ( gridsizei != gridsizeo )
     cdoAbort("Input and output vertical coordinate must have the same gridsize");
-   gridSize = gridsizeo;
 
-   /* input and output vertical coordinates must have exactly the same
-    * horizontal grid */
+  gridSize = gridsizeo;
+
+   /* input and output vertical coordinates must have exactly the same horizontal grid */
    if ( nlonIn != nlonOut || 
         nlatIn != nlatOut ||
         memcmp(lonIn,lonOut,nlonIn*sizeof(double)) ||
diff --git a/src/Makefile.am b/src/Makefile.am
index c0a88e1..c07c403 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,6 +15,7 @@ cdo_SOURCES += Adisit.c        \
                Change.c        \
                Change_e5slm.c  \
                Cloudlayer.c    \
+               Collgrid.c      \
                Command.c       \
                Comp.c          \
                Compc.c         \
@@ -28,6 +29,7 @@ cdo_SOURCES += Adisit.c        \
                Derivepar.c     \
                Detrend.c       \
                Diff.c          \
+               Distgrid.c      \
                Duplicate.c     \
                EOFs.c          \
 	       Eof3d.c         \
@@ -49,11 +51,11 @@ cdo_SOURCES += Adisit.c        \
                Fldstat.c       \
                Fldstat2.c      \
                Fourier.c       \
-               Gather.c        \
                Gengrid.c       \
                Gradsdes.c      \
                Gridboxstat.c   \
                Gridcell.c      \
+               Gridsearch.c    \
                Harmonic.c      \
                Hi.c            \
                Histogram.c     \
@@ -101,7 +103,6 @@ cdo_SOURCES += Adisit.c        \
                Rotuv.c         \
                Runpctl.c       \
                Runstat.c       \
-               Scatter.c       \
                Seascount.c     \
                Seaspctl.c      \
                Seasstat.c      \
@@ -258,6 +259,7 @@ cdo_SOURCES += Adisit.c        \
                percentiles.h   \
                pipe.c          \
                pipe.h          \
+               pragma_omp_atomic_update.h \
                printinfo.h     \
                process.c       \
                process.h       \
diff --git a/src/Makefile.in b/src/Makefile.in
index a3d039d..8d46b8f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -116,22 +116,22 @@ am__installdirs = "$(DESTDIR)$(bindir)"
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
 am__cdo_SOURCES_DIST = cdo.c Adisit.c Arith.c Arithc.c Arithdays.c \
 	Arithlat.c CDItest.c CDIread.c CDIwrite.c Cat.c Change.c \
-	Change_e5slm.c Cloudlayer.c Command.c Comp.c Compc.c \
-	Complextorect.c Cond.c Cond2.c Condc.c Consecstat.c Copy.c \
-	Deltime.c Derivepar.c Detrend.c Diff.c Duplicate.c EOFs.c \
-	Eof3d.c EcaIndices.c Echam5ini.c Enlarge.c Enlargegrid.c \
-	Ensstat.c Ensstat3.c Ensval.c Eofcoeff.c Eofcoeff3d.c Exprf.c \
-	FC.c Filedes.c Fillmiss.c Filter.c Fldrms.c Fldstat.c \
-	Fldstat2.c Fourier.c Gather.c Gengrid.c Gradsdes.c \
-	Gridboxstat.c Gridcell.c Harmonic.c Hi.c Histogram.c \
-	Importamsr.c Importbinary.c Importcmsaf.c Importobs.c Info.c \
-	Input.c Intgrid.c Intgridtraj.c Intlevel.c Intlevel3d.c \
-	Intntime.c Inttime.c Intyear.c Invert.c Invertlev.c \
-	Isosurface.c Kvl.c Log.c Maskbox.c Mastrfu.c Math.c Merge.c \
-	Mergegrid.c Mergetime.c Merstat.c Monarith.c Mrotuv.c \
-	Mrotuvb.c Ninfo.c Nmltest.c Output.c Outputgmt.c Pack.c \
-	Pinfo.c Pressure.c Regres.c Remap.c Remapeta.c Replace.c \
-	Replacevalues.c Rhopot.c Rotuv.c Runpctl.c Runstat.c Scatter.c \
+	Change_e5slm.c Cloudlayer.c Collgrid.c Command.c Comp.c \
+	Compc.c Complextorect.c Cond.c Cond2.c Condc.c Consecstat.c \
+	Copy.c Deltime.c Derivepar.c Detrend.c Diff.c Distgrid.c \
+	Duplicate.c EOFs.c Eof3d.c EcaIndices.c Echam5ini.c Enlarge.c \
+	Enlargegrid.c Ensstat.c Ensstat3.c Ensval.c Eofcoeff.c \
+	Eofcoeff3d.c Exprf.c FC.c Filedes.c Fillmiss.c Filter.c \
+	Fldrms.c Fldstat.c Fldstat2.c Fourier.c Gengrid.c Gradsdes.c \
+	Gridboxstat.c Gridcell.c Gridsearch.c Harmonic.c Hi.c \
+	Histogram.c Importamsr.c Importbinary.c Importcmsaf.c \
+	Importobs.c Info.c Input.c Intgrid.c Intgridtraj.c Intlevel.c \
+	Intlevel3d.c Intntime.c Inttime.c Intyear.c Invert.c \
+	Invertlev.c Isosurface.c Kvl.c Log.c Maskbox.c Mastrfu.c \
+	Math.c Merge.c Mergegrid.c Mergetime.c Merstat.c Monarith.c \
+	Mrotuv.c Mrotuvb.c Ninfo.c Nmltest.c Output.c Outputgmt.c \
+	Pack.c Pinfo.c Pressure.c Regres.c Remap.c Remapeta.c \
+	Replace.c Replacevalues.c Rhopot.c Rotuv.c Runpctl.c Runstat.c \
 	Seascount.c Seaspctl.c Seasstat.c Selbox.c Select.c \
 	Seloperator.c Selrec.c Seltime.c Selvar.c Set.c Setbox.c \
 	Setgatt.c Setgrid.c Sethalo.c Setmiss.c Setpartab.c \
@@ -159,10 +159,11 @@ am__cdo_SOURCES_DIST = cdo.c Adisit.c Arith.c Arithc.c Arithdays.c \
 	kvlist.c kvlist.h legendre.c list.c list.h merge_sort2.c \
 	merge_sort2.h modules.c modules.h namelist.c namelist.h \
 	normal.c nth_element.c nth_element.h operator_help.h par_io.c \
-	par_io.h percentiles.c percentiles.h pipe.c pipe.h printinfo.h \
-	process.c process.h pstream.c pstream.h pstream_int.h \
-	pthread_debug.c pthread_debug.h readline.c realtime.c remap.h \
-	remaplib.c remapsort.c remap_scrip_io.c remap_search_reg2d.c \
+	par_io.h percentiles.c percentiles.h pipe.c pipe.h \
+	pragma_omp_atomic_update.h printinfo.h process.c process.h \
+	pstream.c pstream.h pstream_int.h pthread_debug.c \
+	pthread_debug.h readline.c realtime.c remap.h remaplib.c \
+	remapsort.c remap_scrip_io.c remap_search_reg2d.c \
 	remap_search_latbins.c remap_store_link.c remap_store_link.h \
 	remap_conserv.c remap_conserv_scrip.c remap_distwgt_scrip.c \
 	remap_bicubic_scrip.c remap_bilinear_scrip.c stdnametable.c \
@@ -179,6 +180,7 @@ am__cdo_SOURCES_DIST = cdo.c Adisit.c Arith.c Arithc.c Arithdays.c \
 	results_template_parser.c magics_template_parser.h \
 	magics_template_parser.c StringUtilities.h StringUtilities.c \
 	CdoMagicsMapper.h CdoMagicsMapper.c
+am__dirstamp = $(am__leading_dot)dirstamp
 @ENABLE_MAGICS_TRUE at am__objects_1 = cdo-Magplot.$(OBJEXT) \
 @ENABLE_MAGICS_TRUE@	cdo-Magvector.$(OBJEXT) \
 @ENABLE_MAGICS_TRUE@	cdo-Maggraph.$(OBJEXT) \
@@ -193,13 +195,15 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-CDItest.$(OBJEXT) cdo-CDIread.$(OBJEXT) \
 	cdo-CDIwrite.$(OBJEXT) cdo-Cat.$(OBJEXT) cdo-Change.$(OBJEXT) \
 	cdo-Change_e5slm.$(OBJEXT) cdo-Cloudlayer.$(OBJEXT) \
-	cdo-Command.$(OBJEXT) cdo-Comp.$(OBJEXT) cdo-Compc.$(OBJEXT) \
+	cdo-Collgrid.$(OBJEXT) cdo-Command.$(OBJEXT) \
+	cdo-Comp.$(OBJEXT) cdo-Compc.$(OBJEXT) \
 	cdo-Complextorect.$(OBJEXT) cdo-Cond.$(OBJEXT) \
 	cdo-Cond2.$(OBJEXT) cdo-Condc.$(OBJEXT) \
 	cdo-Consecstat.$(OBJEXT) cdo-Copy.$(OBJEXT) \
 	cdo-Deltime.$(OBJEXT) cdo-Derivepar.$(OBJEXT) \
 	cdo-Detrend.$(OBJEXT) cdo-Diff.$(OBJEXT) \
-	cdo-Duplicate.$(OBJEXT) cdo-EOFs.$(OBJEXT) cdo-Eof3d.$(OBJEXT) \
+	cdo-Distgrid.$(OBJEXT) cdo-Duplicate.$(OBJEXT) \
+	cdo-EOFs.$(OBJEXT) cdo-Eof3d.$(OBJEXT) \
 	cdo-EcaIndices.$(OBJEXT) cdo-Echam5ini.$(OBJEXT) \
 	cdo-Enlarge.$(OBJEXT) cdo-Enlargegrid.$(OBJEXT) \
 	cdo-Ensstat.$(OBJEXT) cdo-Ensstat3.$(OBJEXT) \
@@ -208,9 +212,9 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-Filedes.$(OBJEXT) cdo-Fillmiss.$(OBJEXT) \
 	cdo-Filter.$(OBJEXT) cdo-Fldrms.$(OBJEXT) \
 	cdo-Fldstat.$(OBJEXT) cdo-Fldstat2.$(OBJEXT) \
-	cdo-Fourier.$(OBJEXT) cdo-Gather.$(OBJEXT) \
-	cdo-Gengrid.$(OBJEXT) cdo-Gradsdes.$(OBJEXT) \
-	cdo-Gridboxstat.$(OBJEXT) cdo-Gridcell.$(OBJEXT) \
+	cdo-Fourier.$(OBJEXT) cdo-Gengrid.$(OBJEXT) \
+	cdo-Gradsdes.$(OBJEXT) cdo-Gridboxstat.$(OBJEXT) \
+	cdo-Gridcell.$(OBJEXT) cdo-Gridsearch.$(OBJEXT) \
 	cdo-Harmonic.$(OBJEXT) cdo-Hi.$(OBJEXT) \
 	cdo-Histogram.$(OBJEXT) cdo-Importamsr.$(OBJEXT) \
 	cdo-Importbinary.$(OBJEXT) cdo-Importcmsaf.$(OBJEXT) \
@@ -231,18 +235,17 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-Remap.$(OBJEXT) cdo-Remapeta.$(OBJEXT) \
 	cdo-Replace.$(OBJEXT) cdo-Replacevalues.$(OBJEXT) \
 	cdo-Rhopot.$(OBJEXT) cdo-Rotuv.$(OBJEXT) cdo-Runpctl.$(OBJEXT) \
-	cdo-Runstat.$(OBJEXT) cdo-Scatter.$(OBJEXT) \
-	cdo-Seascount.$(OBJEXT) cdo-Seaspctl.$(OBJEXT) \
-	cdo-Seasstat.$(OBJEXT) cdo-Selbox.$(OBJEXT) \
-	cdo-Select.$(OBJEXT) cdo-Seloperator.$(OBJEXT) \
-	cdo-Selrec.$(OBJEXT) cdo-Seltime.$(OBJEXT) \
-	cdo-Selvar.$(OBJEXT) cdo-Set.$(OBJEXT) cdo-Setbox.$(OBJEXT) \
-	cdo-Setgatt.$(OBJEXT) cdo-Setgrid.$(OBJEXT) \
-	cdo-Sethalo.$(OBJEXT) cdo-Setmiss.$(OBJEXT) \
-	cdo-Setpartab.$(OBJEXT) cdo-Setrcaname.$(OBJEXT) \
-	cdo-Settime.$(OBJEXT) cdo-Setzaxis.$(OBJEXT) \
-	cdo-Showinfo.$(OBJEXT) cdo-Sinfo.$(OBJEXT) \
-	cdo-Smooth9.$(OBJEXT) cdo-Sort.$(OBJEXT) \
+	cdo-Runstat.$(OBJEXT) cdo-Seascount.$(OBJEXT) \
+	cdo-Seaspctl.$(OBJEXT) cdo-Seasstat.$(OBJEXT) \
+	cdo-Selbox.$(OBJEXT) cdo-Select.$(OBJEXT) \
+	cdo-Seloperator.$(OBJEXT) cdo-Selrec.$(OBJEXT) \
+	cdo-Seltime.$(OBJEXT) cdo-Selvar.$(OBJEXT) cdo-Set.$(OBJEXT) \
+	cdo-Setbox.$(OBJEXT) cdo-Setgatt.$(OBJEXT) \
+	cdo-Setgrid.$(OBJEXT) cdo-Sethalo.$(OBJEXT) \
+	cdo-Setmiss.$(OBJEXT) cdo-Setpartab.$(OBJEXT) \
+	cdo-Setrcaname.$(OBJEXT) cdo-Settime.$(OBJEXT) \
+	cdo-Setzaxis.$(OBJEXT) cdo-Showinfo.$(OBJEXT) \
+	cdo-Sinfo.$(OBJEXT) cdo-Smooth9.$(OBJEXT) cdo-Sort.$(OBJEXT) \
 	cdo-Sorttimestamp.$(OBJEXT) cdo-Specinfo.$(OBJEXT) \
 	cdo-Spectral.$(OBJEXT) cdo-Spectrum.$(OBJEXT) \
 	cdo-Split.$(OBJEXT) cdo-Splitrec.$(OBJEXT) \
@@ -305,10 +308,13 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-specspace.$(OBJEXT) cdo-statistic.$(OBJEXT) \
 	cdo-table.$(OBJEXT) cdo-text.$(OBJEXT) cdo-timer.$(OBJEXT) \
 	cdo-userlog.$(OBJEXT) cdo-util.$(OBJEXT) cdo-vinterp.$(OBJEXT) \
-	cdo-zaxis.$(OBJEXT) cdo-clipping.$(OBJEXT) cdo-area.$(OBJEXT) \
-	cdo-ensure_array_size.$(OBJEXT) cdo-geometry_tools.$(OBJEXT) \
-	cdo-grid_cell.$(OBJEXT) cdo-intersection.$(OBJEXT) \
-	cdo-utils.$(OBJEXT) $(am__objects_1)
+	cdo-zaxis.$(OBJEXT) clipping/cdo-clipping.$(OBJEXT) \
+	clipping/cdo-area.$(OBJEXT) \
+	clipping/cdo-ensure_array_size.$(OBJEXT) \
+	clipping/cdo-geometry_tools.$(OBJEXT) \
+	clipping/cdo-grid_cell.$(OBJEXT) \
+	clipping/cdo-intersection.$(OBJEXT) \
+	clipping/cdo-utils.$(OBJEXT) $(am__objects_1)
 cdo_OBJECTS = $(am_cdo_OBJECTS)
 cdo_DEPENDENCIES = $(top_builddir)/libcdi/src/libcdi.la
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -557,50 +563,51 @@ top_srcdir = @top_srcdir@
 #
 cdo_SOURCES = cdo.c Adisit.c Arith.c Arithc.c Arithdays.c Arithlat.c \
 	CDItest.c CDIread.c CDIwrite.c Cat.c Change.c Change_e5slm.c \
-	Cloudlayer.c Command.c Comp.c Compc.c Complextorect.c Cond.c \
-	Cond2.c Condc.c Consecstat.c Copy.c Deltime.c Derivepar.c \
-	Detrend.c Diff.c Duplicate.c EOFs.c Eof3d.c EcaIndices.c \
-	Echam5ini.c Enlarge.c Enlargegrid.c Ensstat.c Ensstat3.c \
-	Ensval.c Eofcoeff.c Eofcoeff3d.c Exprf.c FC.c Filedes.c \
-	Fillmiss.c Filter.c Fldrms.c Fldstat.c Fldstat2.c Fourier.c \
-	Gather.c Gengrid.c Gradsdes.c Gridboxstat.c Gridcell.c \
-	Harmonic.c Hi.c Histogram.c Importamsr.c Importbinary.c \
-	Importcmsaf.c Importobs.c Info.c Input.c Intgrid.c \
-	Intgridtraj.c Intlevel.c Intlevel3d.c Intntime.c Inttime.c \
-	Intyear.c Invert.c Invertlev.c Isosurface.c Kvl.c Log.c \
-	Maskbox.c Mastrfu.c Math.c Merge.c Mergegrid.c Mergetime.c \
-	Merstat.c Monarith.c Mrotuv.c Mrotuvb.c Ninfo.c Nmltest.c \
-	Output.c Outputgmt.c Pack.c Pinfo.c Pressure.c Regres.c \
-	Remap.c Remapeta.c Replace.c Replacevalues.c Rhopot.c Rotuv.c \
-	Runpctl.c Runstat.c Scatter.c Seascount.c Seaspctl.c \
-	Seasstat.c Selbox.c Select.c Seloperator.c Selrec.c Seltime.c \
-	Selvar.c Set.c Setbox.c Setgatt.c Setgrid.c Sethalo.c \
-	Setmiss.c Setpartab.c Setrcaname.c Settime.c Setzaxis.c \
-	Showinfo.c Sinfo.c Smooth9.c Sort.c Sorttimestamp.c Specinfo.c \
-	Spectral.c Spectrum.c Split.c Splitrec.c Splitsel.c \
-	Splittime.c Splityear.c SSOpar.c Subtrend.c Tee.c Templates.c \
-	Test.c Tests.c Timcount.c Timpctl.c Timselpctl.c Timselstat.c \
-	Timsort.c Timstat.c Timstat2.c Timstat3.c Tinfo.c Tocomplex.c \
-	Transpose.c Trend.c Trms.c Tstepcount.c Vardup.c Vargen.c \
-	Varrms.c Vertint.c Vertstat.c Vertwind.c Wct.c Wind.c \
-	Writegrid.c Writerandom.c YAR.c Yearmonstat.c Ydayarith.c \
-	Ydaypctl.c Ydaystat.c Ydrunpctl.c Ydrunstat.c Yhourarith.c \
-	Yhourstat.c Ymonarith.c Ymonpctl.c Ymonstat.c Yseaspctl.c \
-	Yseasstat.c Zonstat.c cdo.h cdo_int.h cdo_pthread.c \
-	cdo_vlist.c cdo_getopt.c cdo_getopt.h color.c color.h \
-	commandline.c const.h counter.h dmemory.h dtypes.h ecacore.c \
-	ecacore.h ecautil.c ecautil.h error.h etopo.h temp.h mask.h \
-	exception.c expr.c expr.h expr_lex.c expr_yacc.c expr_yacc.h \
-	features.c field.c field.h field2.c fieldc.c fieldmem.c \
-	fieldmer.c fieldzon.c fouriertrans.c functs.h gradsdeslib.c \
-	gradsdeslib.h grid.c grid.h grid_area.c grid_gme.c grid_lcc.c \
-	grid_rot.c gridreference.c griddes.c griddes.h griddes_h5.c \
-	griddes_nc.c hetaeta.c hetaeta.h history.c institution.c \
-	interpol.c interpol.h job.c juldate.c kvlist.c kvlist.h \
-	legendre.c list.c list.h merge_sort2.c merge_sort2.h modules.c \
-	modules.h namelist.c namelist.h normal.c nth_element.c \
-	nth_element.h operator_help.h par_io.c par_io.h percentiles.c \
-	percentiles.h pipe.c pipe.h printinfo.h process.c process.h \
+	Cloudlayer.c Collgrid.c Command.c Comp.c Compc.c \
+	Complextorect.c Cond.c Cond2.c Condc.c Consecstat.c Copy.c \
+	Deltime.c Derivepar.c Detrend.c Diff.c Distgrid.c Duplicate.c \
+	EOFs.c Eof3d.c EcaIndices.c Echam5ini.c Enlarge.c \
+	Enlargegrid.c Ensstat.c Ensstat3.c Ensval.c Eofcoeff.c \
+	Eofcoeff3d.c Exprf.c FC.c Filedes.c Fillmiss.c Filter.c \
+	Fldrms.c Fldstat.c Fldstat2.c Fourier.c Gengrid.c Gradsdes.c \
+	Gridboxstat.c Gridcell.c Gridsearch.c Harmonic.c Hi.c \
+	Histogram.c Importamsr.c Importbinary.c Importcmsaf.c \
+	Importobs.c Info.c Input.c Intgrid.c Intgridtraj.c Intlevel.c \
+	Intlevel3d.c Intntime.c Inttime.c Intyear.c Invert.c \
+	Invertlev.c Isosurface.c Kvl.c Log.c Maskbox.c Mastrfu.c \
+	Math.c Merge.c Mergegrid.c Mergetime.c Merstat.c Monarith.c \
+	Mrotuv.c Mrotuvb.c Ninfo.c Nmltest.c Output.c Outputgmt.c \
+	Pack.c Pinfo.c Pressure.c Regres.c Remap.c Remapeta.c \
+	Replace.c Replacevalues.c Rhopot.c Rotuv.c Runpctl.c Runstat.c \
+	Seascount.c Seaspctl.c Seasstat.c Selbox.c Select.c \
+	Seloperator.c Selrec.c Seltime.c Selvar.c Set.c Setbox.c \
+	Setgatt.c Setgrid.c Sethalo.c Setmiss.c Setpartab.c \
+	Setrcaname.c Settime.c Setzaxis.c Showinfo.c Sinfo.c Smooth9.c \
+	Sort.c Sorttimestamp.c Specinfo.c Spectral.c Spectrum.c \
+	Split.c Splitrec.c Splitsel.c Splittime.c Splityear.c SSOpar.c \
+	Subtrend.c Tee.c Templates.c Test.c Tests.c Timcount.c \
+	Timpctl.c Timselpctl.c Timselstat.c Timsort.c Timstat.c \
+	Timstat2.c Timstat3.c Tinfo.c Tocomplex.c Transpose.c Trend.c \
+	Trms.c Tstepcount.c Vardup.c Vargen.c Varrms.c Vertint.c \
+	Vertstat.c Vertwind.c Wct.c Wind.c Writegrid.c Writerandom.c \
+	YAR.c Yearmonstat.c Ydayarith.c Ydaypctl.c Ydaystat.c \
+	Ydrunpctl.c Ydrunstat.c Yhourarith.c Yhourstat.c Ymonarith.c \
+	Ymonpctl.c Ymonstat.c Yseaspctl.c Yseasstat.c Zonstat.c cdo.h \
+	cdo_int.h cdo_pthread.c cdo_vlist.c cdo_getopt.c cdo_getopt.h \
+	color.c color.h commandline.c const.h counter.h dmemory.h \
+	dtypes.h ecacore.c ecacore.h ecautil.c ecautil.h error.h \
+	etopo.h temp.h mask.h exception.c expr.c expr.h expr_lex.c \
+	expr_yacc.c expr_yacc.h features.c field.c field.h field2.c \
+	fieldc.c fieldmem.c fieldmer.c fieldzon.c fouriertrans.c \
+	functs.h gradsdeslib.c gradsdeslib.h grid.c grid.h grid_area.c \
+	grid_gme.c grid_lcc.c grid_rot.c gridreference.c griddes.c \
+	griddes.h griddes_h5.c griddes_nc.c hetaeta.c hetaeta.h \
+	history.c institution.c interpol.c interpol.h job.c juldate.c \
+	kvlist.c kvlist.h legendre.c list.c list.h merge_sort2.c \
+	merge_sort2.h modules.c modules.h namelist.c namelist.h \
+	normal.c nth_element.c nth_element.h operator_help.h par_io.c \
+	par_io.h percentiles.c percentiles.h pipe.c pipe.h \
+	pragma_omp_atomic_update.h printinfo.h process.c process.h \
 	pstream.c pstream.h pstream_int.h pthread_debug.c \
 	pthread_debug.h readline.c realtime.c remap.h remaplib.c \
 	remapsort.c remap_scrip_io.c remap_search_reg2d.c \
@@ -740,6 +747,26 @@ clean-noinstPROGRAMS:
 	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
 	echo " rm -f" $$list; \
 	rm -f $$list
+clipping/$(am__dirstamp):
+	@$(MKDIR_P) clipping
+	@: > clipping/$(am__dirstamp)
+clipping/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) clipping/$(DEPDIR)
+	@: > clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-clipping.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-area.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-ensure_array_size.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-geometry_tools.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-grid_cell.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-intersection.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
+clipping/cdo-utils.$(OBJEXT): clipping/$(am__dirstamp) \
+	clipping/$(DEPDIR)/$(am__dirstamp)
 
 cdo$(EXEEXT): $(cdo_OBJECTS) $(cdo_DEPENDENCIES) $(EXTRA_cdo_DEPENDENCIES) 
 	@rm -f cdo$(EXEEXT)
@@ -751,6 +778,7 @@ cdotest$(EXEEXT): $(cdotest_OBJECTS) $(cdotest_DEPENDENCIES) $(EXTRA_cdotest_DEP
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
+	-rm -f clipping/*.$(OBJEXT)
 
 distclean-compile:
 	-rm -f *.tab.c
@@ -768,6 +796,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Change.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Change_e5slm.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Cloudlayer.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Collgrid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Command.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Comp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Compc.Po at am__quote@
@@ -781,6 +810,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Derivepar.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Detrend.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Diff.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Distgrid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Duplicate.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-EOFs.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-EcaIndices.Po at am__quote@
@@ -802,11 +832,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Fldstat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Fldstat2.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Fourier.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gather.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gengrid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gradsdes.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gridboxstat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gridcell.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Gridsearch.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Harmonic.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Hi.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Histogram.Po at am__quote@
@@ -858,7 +888,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Runpctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Runstat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-SSOpar.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Scatter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seascount.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seaspctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seasstat.Po at am__quote@
@@ -936,17 +965,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Yseaspctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Yseasstat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Zonstat.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-area.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-cdo.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-cdo_getopt.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-cdo_pthread.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-cdo_vlist.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-clipping.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-color.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-commandline.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-ecacore.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-ecautil.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-ensure_array_size.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-exception.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-expr.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-expr_lex.Po at am__quote@
@@ -959,11 +985,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-fieldmer.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-fieldzon.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-fouriertrans.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-geometry_tools.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-gradsdeslib.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid_area.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid_cell.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid_gme.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid_lcc.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-grid_rot.Po at am__quote@
@@ -975,7 +999,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-history.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-institution.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-interpol.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-intersection.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-job.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-juldate.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-kvlist.Po at am__quote@
@@ -1016,28 +1039,37 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-timer.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-userlog.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-util.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-utils.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-vinterp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-zaxis.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdotest-cdotest.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-area.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-clipping.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-ensure_array_size.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-geometry_tools.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-grid_cell.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-intersection.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at clipping/$(DEPDIR)/cdo-utils.Po at am__quote@
 
 .c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
 
 .c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
 .c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -1224,6 +1256,20 @@ cdo-Cloudlayer.obj: Cloudlayer.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Cloudlayer.obj `if test -f 'Cloudlayer.c'; then $(CYGPATH_W) 'Cloudlayer.c'; else $(CYGPATH_W) '$(srcdir)/Cloudlayer.c'; fi`
 
+cdo-Collgrid.o: Collgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Collgrid.o -MD -MP -MF $(DEPDIR)/cdo-Collgrid.Tpo -c -o cdo-Collgrid.o `test -f 'Collgrid.c' || echo '$(srcdir)/'`Collgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Collgrid.Tpo $(DEPDIR)/cdo-Collgrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Collgrid.c' object='cdo-Collgrid.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Collgrid.o `test -f 'Collgrid.c' || echo '$(srcdir)/'`Collgrid.c
+
+cdo-Collgrid.obj: Collgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Collgrid.obj -MD -MP -MF $(DEPDIR)/cdo-Collgrid.Tpo -c -o cdo-Collgrid.obj `if test -f 'Collgrid.c'; then $(CYGPATH_W) 'Collgrid.c'; else $(CYGPATH_W) '$(srcdir)/Collgrid.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Collgrid.Tpo $(DEPDIR)/cdo-Collgrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Collgrid.c' object='cdo-Collgrid.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Collgrid.obj `if test -f 'Collgrid.c'; then $(CYGPATH_W) 'Collgrid.c'; else $(CYGPATH_W) '$(srcdir)/Collgrid.c'; fi`
+
 cdo-Command.o: Command.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Command.o -MD -MP -MF $(DEPDIR)/cdo-Command.Tpo -c -o cdo-Command.o `test -f 'Command.c' || echo '$(srcdir)/'`Command.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Command.Tpo $(DEPDIR)/cdo-Command.Po
@@ -1406,6 +1452,20 @@ cdo-Diff.obj: Diff.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Diff.obj `if test -f 'Diff.c'; then $(CYGPATH_W) 'Diff.c'; else $(CYGPATH_W) '$(srcdir)/Diff.c'; fi`
 
+cdo-Distgrid.o: Distgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Distgrid.o -MD -MP -MF $(DEPDIR)/cdo-Distgrid.Tpo -c -o cdo-Distgrid.o `test -f 'Distgrid.c' || echo '$(srcdir)/'`Distgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Distgrid.Tpo $(DEPDIR)/cdo-Distgrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Distgrid.c' object='cdo-Distgrid.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Distgrid.o `test -f 'Distgrid.c' || echo '$(srcdir)/'`Distgrid.c
+
+cdo-Distgrid.obj: Distgrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Distgrid.obj -MD -MP -MF $(DEPDIR)/cdo-Distgrid.Tpo -c -o cdo-Distgrid.obj `if test -f 'Distgrid.c'; then $(CYGPATH_W) 'Distgrid.c'; else $(CYGPATH_W) '$(srcdir)/Distgrid.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Distgrid.Tpo $(DEPDIR)/cdo-Distgrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Distgrid.c' object='cdo-Distgrid.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Distgrid.obj `if test -f 'Distgrid.c'; then $(CYGPATH_W) 'Distgrid.c'; else $(CYGPATH_W) '$(srcdir)/Distgrid.c'; fi`
+
 cdo-Duplicate.o: Duplicate.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Duplicate.o -MD -MP -MF $(DEPDIR)/cdo-Duplicate.Tpo -c -o cdo-Duplicate.o `test -f 'Duplicate.c' || echo '$(srcdir)/'`Duplicate.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Duplicate.Tpo $(DEPDIR)/cdo-Duplicate.Po
@@ -1700,20 +1760,6 @@ cdo-Fourier.obj: Fourier.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Fourier.obj `if test -f 'Fourier.c'; then $(CYGPATH_W) 'Fourier.c'; else $(CYGPATH_W) '$(srcdir)/Fourier.c'; fi`
 
-cdo-Gather.o: Gather.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Gather.o -MD -MP -MF $(DEPDIR)/cdo-Gather.Tpo -c -o cdo-Gather.o `test -f 'Gather.c' || echo '$(srcdir)/'`Gather.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Gather.Tpo $(DEPDIR)/cdo-Gather.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Gather.c' object='cdo-Gather.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Gather.o `test -f 'Gather.c' || echo '$(srcdir)/'`Gather.c
-
-cdo-Gather.obj: Gather.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Gather.obj -MD -MP -MF $(DEPDIR)/cdo-Gather.Tpo -c -o cdo-Gather.obj `if test -f 'Gather.c'; then $(CYGPATH_W) 'Gather.c'; else $(CYGPATH_W) '$(srcdir)/Gather.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Gather.Tpo $(DEPDIR)/cdo-Gather.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Gather.c' object='cdo-Gather.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Gather.obj `if test -f 'Gather.c'; then $(CYGPATH_W) 'Gather.c'; else $(CYGPATH_W) '$(srcdir)/Gather.c'; fi`
-
 cdo-Gengrid.o: Gengrid.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Gengrid.o -MD -MP -MF $(DEPDIR)/cdo-Gengrid.Tpo -c -o cdo-Gengrid.o `test -f 'Gengrid.c' || echo '$(srcdir)/'`Gengrid.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Gengrid.Tpo $(DEPDIR)/cdo-Gengrid.Po
@@ -1770,6 +1816,20 @@ cdo-Gridcell.obj: Gridcell.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Gridcell.obj `if test -f 'Gridcell.c'; then $(CYGPATH_W) 'Gridcell.c'; else $(CYGPATH_W) '$(srcdir)/Gridcell.c'; fi`
 
+cdo-Gridsearch.o: Gridsearch.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Gridsearch.o -MD -MP -MF $(DEPDIR)/cdo-Gridsearch.Tpo -c -o cdo-Gridsearch.o `test -f 'Gridsearch.c' || echo '$(srcdir)/'`Gridsearch.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Gridsearch.Tpo $(DEPDIR)/cdo-Gridsearch.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Gridsearch.c' object='cdo-Gridsearch.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Gridsearch.o `test -f 'Gridsearch.c' || echo '$(srcdir)/'`Gridsearch.c
+
+cdo-Gridsearch.obj: Gridsearch.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Gridsearch.obj -MD -MP -MF $(DEPDIR)/cdo-Gridsearch.Tpo -c -o cdo-Gridsearch.obj `if test -f 'Gridsearch.c'; then $(CYGPATH_W) 'Gridsearch.c'; else $(CYGPATH_W) '$(srcdir)/Gridsearch.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Gridsearch.Tpo $(DEPDIR)/cdo-Gridsearch.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Gridsearch.c' object='cdo-Gridsearch.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Gridsearch.obj `if test -f 'Gridsearch.c'; then $(CYGPATH_W) 'Gridsearch.c'; else $(CYGPATH_W) '$(srcdir)/Gridsearch.c'; fi`
+
 cdo-Harmonic.o: Harmonic.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Harmonic.o -MD -MP -MF $(DEPDIR)/cdo-Harmonic.Tpo -c -o cdo-Harmonic.o `test -f 'Harmonic.c' || echo '$(srcdir)/'`Harmonic.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Harmonic.Tpo $(DEPDIR)/cdo-Harmonic.Po
@@ -2428,20 +2488,6 @@ cdo-Runstat.obj: Runstat.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Runstat.obj `if test -f 'Runstat.c'; then $(CYGPATH_W) 'Runstat.c'; else $(CYGPATH_W) '$(srcdir)/Runstat.c'; fi`
 
-cdo-Scatter.o: Scatter.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Scatter.o -MD -MP -MF $(DEPDIR)/cdo-Scatter.Tpo -c -o cdo-Scatter.o `test -f 'Scatter.c' || echo '$(srcdir)/'`Scatter.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Scatter.Tpo $(DEPDIR)/cdo-Scatter.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Scatter.c' object='cdo-Scatter.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Scatter.o `test -f 'Scatter.c' || echo '$(srcdir)/'`Scatter.c
-
-cdo-Scatter.obj: Scatter.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Scatter.obj -MD -MP -MF $(DEPDIR)/cdo-Scatter.Tpo -c -o cdo-Scatter.obj `if test -f 'Scatter.c'; then $(CYGPATH_W) 'Scatter.c'; else $(CYGPATH_W) '$(srcdir)/Scatter.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Scatter.Tpo $(DEPDIR)/cdo-Scatter.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Scatter.c' object='cdo-Scatter.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Scatter.obj `if test -f 'Scatter.c'; then $(CYGPATH_W) 'Scatter.c'; else $(CYGPATH_W) '$(srcdir)/Scatter.c'; fi`
-
 cdo-Seascount.o: Seascount.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Seascount.o -MD -MP -MF $(DEPDIR)/cdo-Seascount.Tpo -c -o cdo-Seascount.o `test -f 'Seascount.c' || echo '$(srcdir)/'`Seascount.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Seascount.Tpo $(DEPDIR)/cdo-Seascount.Po
@@ -4528,103 +4574,103 @@ cdo-zaxis.obj: zaxis.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-zaxis.obj `if test -f 'zaxis.c'; then $(CYGPATH_W) 'zaxis.c'; else $(CYGPATH_W) '$(srcdir)/zaxis.c'; fi`
 
-cdo-clipping.o: clipping/clipping.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-clipping.o -MD -MP -MF $(DEPDIR)/cdo-clipping.Tpo -c -o cdo-clipping.o `test -f 'clipping/clipping.c' || echo '$(srcdir)/'`clipping/clipping.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-clipping.Tpo $(DEPDIR)/cdo-clipping.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/clipping.c' object='cdo-clipping.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-clipping.o: clipping/clipping.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-clipping.o -MD -MP -MF clipping/$(DEPDIR)/cdo-clipping.Tpo -c -o clipping/cdo-clipping.o `test -f 'clipping/clipping.c' || echo '$(srcdir)/'`clipping/clipping.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-clipping.Tpo clipping/$(DEPDIR)/cdo-clipping.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/clipping.c' object='clipping/cdo-clipping.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-clipping.o `test -f 'clipping/clipping.c' || echo '$(srcdir)/'`clipping/clipping.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-clipping.o `test -f 'clipping/clipping.c' || echo '$(srcdir)/'`clipping/clipping.c
 
-cdo-clipping.obj: clipping/clipping.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-clipping.obj -MD -MP -MF $(DEPDIR)/cdo-clipping.Tpo -c -o cdo-clipping.obj `if test -f 'clipping/clipping.c'; then $(CYGPATH_W) 'clipping/clipping.c'; else $(CYGPATH_W) '$(srcdir)/clipping/clipping.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-clipping.Tpo $(DEPDIR)/cdo-clipping.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/clipping.c' object='cdo-clipping.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-clipping.obj: clipping/clipping.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-clipping.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-clipping.Tpo -c -o clipping/cdo-clipping.obj `if test -f 'clipping/clipping.c'; then $(CYGPATH_W) 'clipping/clipping.c'; else $(CYGPATH_W) '$(srcdir)/clipping/clipping.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-clipping.Tpo clipping/$(DEPDIR)/cdo-clipping.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/clipping.c' object='clipping/cdo-clipping.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-clipping.obj `if test -f 'clipping/clipping.c'; then $(CYGPATH_W) 'clipping/clipping.c'; else $(CYGPATH_W) '$(srcdir)/clipping/clipping.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-clipping.obj `if test -f 'clipping/clipping.c'; then $(CYGPATH_W) 'clipping/clipping.c'; else $(CYGPATH_W) '$(srcdir)/clipping/clipping.c'; fi`
 
-cdo-area.o: clipping/area.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-area.o -MD -MP -MF $(DEPDIR)/cdo-area.Tpo -c -o cdo-area.o `test -f 'clipping/area.c' || echo '$(srcdir)/'`clipping/area.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-area.Tpo $(DEPDIR)/cdo-area.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/area.c' object='cdo-area.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-area.o: clipping/area.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-area.o -MD -MP -MF clipping/$(DEPDIR)/cdo-area.Tpo -c -o clipping/cdo-area.o `test -f 'clipping/area.c' || echo '$(srcdir)/'`clipping/area.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-area.Tpo clipping/$(DEPDIR)/cdo-area.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/area.c' object='clipping/cdo-area.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-area.o `test -f 'clipping/area.c' || echo '$(srcdir)/'`clipping/area.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-area.o `test -f 'clipping/area.c' || echo '$(srcdir)/'`clipping/area.c
 
-cdo-area.obj: clipping/area.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-area.obj -MD -MP -MF $(DEPDIR)/cdo-area.Tpo -c -o cdo-area.obj `if test -f 'clipping/area.c'; then $(CYGPATH_W) 'clipping/area.c'; else $(CYGPATH_W) '$(srcdir)/clipping/area.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-area.Tpo $(DEPDIR)/cdo-area.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/area.c' object='cdo-area.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-area.obj: clipping/area.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-area.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-area.Tpo -c -o clipping/cdo-area.obj `if test -f 'clipping/area.c'; then $(CYGPATH_W) 'clipping/area.c'; else $(CYGPATH_W) '$(srcdir)/clipping/area.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-area.Tpo clipping/$(DEPDIR)/cdo-area.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/area.c' object='clipping/cdo-area.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-area.obj `if test -f 'clipping/area.c'; then $(CYGPATH_W) 'clipping/area.c'; else $(CYGPATH_W) '$(srcdir)/clipping/area.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-area.obj `if test -f 'clipping/area.c'; then $(CYGPATH_W) 'clipping/area.c'; else $(CYGPATH_W) '$(srcdir)/clipping/area.c'; fi`
 
-cdo-ensure_array_size.o: clipping/ensure_array_size.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-ensure_array_size.o -MD -MP -MF $(DEPDIR)/cdo-ensure_array_size.Tpo -c -o cdo-ensure_array_size.o `test -f 'clipping/ensure_array_size.c' || echo '$(srcdir)/'`clipping/ensure_array_size.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-ensure_array_size.Tpo $(DEPDIR)/cdo-ensure_array_size.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/ensure_array_size.c' object='cdo-ensure_array_size.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-ensure_array_size.o: clipping/ensure_array_size.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-ensure_array_size.o -MD -MP -MF clipping/$(DEPDIR)/cdo-ensure_array_size.Tpo -c -o clipping/cdo-ensure_array_size.o `test -f 'clipping/ensure_array_size.c' || echo '$(srcdir)/'`clipping/ensure_array_size.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-ensure_array_size.Tpo clipping/$(DEPDIR)/cdo-ensure_array_size.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/ensure_array_size.c' object='clipping/cdo-ensure_array_size.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-ensure_array_size.o `test -f 'clipping/ensure_array_size.c' || echo '$(srcdir)/'`clipping/ensure_array_size.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-ensure_array_size.o `test -f 'clipping/ensure_array_size.c' || echo '$(srcdir)/'`clipping/ensure_array_size.c
 
-cdo-ensure_array_size.obj: clipping/ensure_array_size.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-ensure_array_size.obj -MD -MP -MF $(DEPDIR)/cdo-ensure_array_size.Tpo -c -o cdo-ensure_array_size.obj `if test -f 'clipping/ensure_array_size.c'; then $(CYGPATH_W) 'clipping/ensure_array_size.c'; else $(CYGPATH_W) '$(srcdir)/clipping/ensure_array_size.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-ensure_array_size.Tpo $(DEPDIR)/cdo-ensure_array_size.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/ensure_array_size.c' object='cdo-ensure_array_size.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-ensure_array_size.obj: clipping/ensure_array_size.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-ensure_array_size.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-ensure_array_size.Tpo -c -o clipping/cdo-ensure_array_size.obj `if test -f 'clipping/ensure_array_size.c'; then $(CYGPATH_W) 'clipping/ensure_array_size.c'; else $(CYGPATH_W) '$(srcdir)/clipping/ensure_array_size.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-ensure_array_size.Tpo clipping/$(DEPDIR)/cdo-ensure_array_size.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/ensure_array_size.c' object='clipping/cdo-ensure_array_size.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-ensure_array_size.obj `if test -f 'clipping/ensure_array_size.c'; then $(CYGPATH_W) 'clipping/ensure_array_size.c'; else $(CYGPATH_W) '$(srcdir)/clipping/ensure_array_size.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-ensure_array_size.obj `if test -f 'clipping/ensure_array_size.c'; then $(CYGPATH_W) 'clipping/ensure_array_size.c'; else $(CYGPATH_W) '$(srcdir)/clipping/ensure_array_size.c'; fi`
 
-cdo-geometry_tools.o: clipping/geometry_tools.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-geometry_tools.o -MD -MP -MF $(DEPDIR)/cdo-geometry_tools.Tpo -c -o cdo-geometry_tools.o `test -f 'clipping/geometry_tools.c' || echo '$(srcdir)/'`clipping/geometry_tools.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-geometry_tools.Tpo $(DEPDIR)/cdo-geometry_tools.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/geometry_tools.c' object='cdo-geometry_tools.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-geometry_tools.o: clipping/geometry_tools.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-geometry_tools.o -MD -MP -MF clipping/$(DEPDIR)/cdo-geometry_tools.Tpo -c -o clipping/cdo-geometry_tools.o `test -f 'clipping/geometry_tools.c' || echo '$(srcdir)/'`clipping/geometry_tools.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-geometry_tools.Tpo clipping/$(DEPDIR)/cdo-geometry_tools.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/geometry_tools.c' object='clipping/cdo-geometry_tools.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-geometry_tools.o `test -f 'clipping/geometry_tools.c' || echo '$(srcdir)/'`clipping/geometry_tools.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-geometry_tools.o `test -f 'clipping/geometry_tools.c' || echo '$(srcdir)/'`clipping/geometry_tools.c
 
-cdo-geometry_tools.obj: clipping/geometry_tools.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-geometry_tools.obj -MD -MP -MF $(DEPDIR)/cdo-geometry_tools.Tpo -c -o cdo-geometry_tools.obj `if test -f 'clipping/geometry_tools.c'; then $(CYGPATH_W) 'clipping/geometry_tools.c'; else $(CYGPATH_W) '$(srcdir)/clipping/geometry_tools.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-geometry_tools.Tpo $(DEPDIR)/cdo-geometry_tools.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/geometry_tools.c' object='cdo-geometry_tools.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-geometry_tools.obj: clipping/geometry_tools.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-geometry_tools.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-geometry_tools.Tpo -c -o clipping/cdo-geometry_tools.obj `if test -f 'clipping/geometry_tools.c'; then $(CYGPATH_W) 'clipping/geometry_tools.c'; else $(CYGPATH_W) '$(srcdir)/clipping/geometry_tools.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-geometry_tools.Tpo clipping/$(DEPDIR)/cdo-geometry_tools.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/geometry_tools.c' object='clipping/cdo-geometry_tools.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-geometry_tools.obj `if test -f 'clipping/geometry_tools.c'; then $(CYGPATH_W) 'clipping/geometry_tools.c'; else $(CYGPATH_W) '$(srcdir)/clipping/geometry_tools.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-geometry_tools.obj `if test -f 'clipping/geometry_tools.c'; then $(CYGPATH_W) 'clipping/geometry_tools.c'; else $(CYGPATH_W) '$(srcdir)/clipping/geometry_tools.c'; fi`
 
-cdo-grid_cell.o: clipping/grid_cell.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-grid_cell.o -MD -MP -MF $(DEPDIR)/cdo-grid_cell.Tpo -c -o cdo-grid_cell.o `test -f 'clipping/grid_cell.c' || echo '$(srcdir)/'`clipping/grid_cell.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-grid_cell.Tpo $(DEPDIR)/cdo-grid_cell.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/grid_cell.c' object='cdo-grid_cell.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-grid_cell.o: clipping/grid_cell.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-grid_cell.o -MD -MP -MF clipping/$(DEPDIR)/cdo-grid_cell.Tpo -c -o clipping/cdo-grid_cell.o `test -f 'clipping/grid_cell.c' || echo '$(srcdir)/'`clipping/grid_cell.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-grid_cell.Tpo clipping/$(DEPDIR)/cdo-grid_cell.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/grid_cell.c' object='clipping/cdo-grid_cell.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-grid_cell.o `test -f 'clipping/grid_cell.c' || echo '$(srcdir)/'`clipping/grid_cell.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-grid_cell.o `test -f 'clipping/grid_cell.c' || echo '$(srcdir)/'`clipping/grid_cell.c
 
-cdo-grid_cell.obj: clipping/grid_cell.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-grid_cell.obj -MD -MP -MF $(DEPDIR)/cdo-grid_cell.Tpo -c -o cdo-grid_cell.obj `if test -f 'clipping/grid_cell.c'; then $(CYGPATH_W) 'clipping/grid_cell.c'; else $(CYGPATH_W) '$(srcdir)/clipping/grid_cell.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-grid_cell.Tpo $(DEPDIR)/cdo-grid_cell.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/grid_cell.c' object='cdo-grid_cell.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-grid_cell.obj: clipping/grid_cell.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-grid_cell.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-grid_cell.Tpo -c -o clipping/cdo-grid_cell.obj `if test -f 'clipping/grid_cell.c'; then $(CYGPATH_W) 'clipping/grid_cell.c'; else $(CYGPATH_W) '$(srcdir)/clipping/grid_cell.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-grid_cell.Tpo clipping/$(DEPDIR)/cdo-grid_cell.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/grid_cell.c' object='clipping/cdo-grid_cell.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-grid_cell.obj `if test -f 'clipping/grid_cell.c'; then $(CYGPATH_W) 'clipping/grid_cell.c'; else $(CYGPATH_W) '$(srcdir)/clipping/grid_cell.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-grid_cell.obj `if test -f 'clipping/grid_cell.c'; then $(CYGPATH_W) 'clipping/grid_cell.c'; else $(CYGPATH_W) '$(srcdir)/clipping/grid_cell.c'; fi`
 
-cdo-intersection.o: clipping/intersection.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-intersection.o -MD -MP -MF $(DEPDIR)/cdo-intersection.Tpo -c -o cdo-intersection.o `test -f 'clipping/intersection.c' || echo '$(srcdir)/'`clipping/intersection.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-intersection.Tpo $(DEPDIR)/cdo-intersection.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/intersection.c' object='cdo-intersection.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-intersection.o: clipping/intersection.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-intersection.o -MD -MP -MF clipping/$(DEPDIR)/cdo-intersection.Tpo -c -o clipping/cdo-intersection.o `test -f 'clipping/intersection.c' || echo '$(srcdir)/'`clipping/intersection.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-intersection.Tpo clipping/$(DEPDIR)/cdo-intersection.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/intersection.c' object='clipping/cdo-intersection.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-intersection.o `test -f 'clipping/intersection.c' || echo '$(srcdir)/'`clipping/intersection.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-intersection.o `test -f 'clipping/intersection.c' || echo '$(srcdir)/'`clipping/intersection.c
 
-cdo-intersection.obj: clipping/intersection.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-intersection.obj -MD -MP -MF $(DEPDIR)/cdo-intersection.Tpo -c -o cdo-intersection.obj `if test -f 'clipping/intersection.c'; then $(CYGPATH_W) 'clipping/intersection.c'; else $(CYGPATH_W) '$(srcdir)/clipping/intersection.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-intersection.Tpo $(DEPDIR)/cdo-intersection.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/intersection.c' object='cdo-intersection.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-intersection.obj: clipping/intersection.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-intersection.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-intersection.Tpo -c -o clipping/cdo-intersection.obj `if test -f 'clipping/intersection.c'; then $(CYGPATH_W) 'clipping/intersection.c'; else $(CYGPATH_W) '$(srcdir)/clipping/intersection.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-intersection.Tpo clipping/$(DEPDIR)/cdo-intersection.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/intersection.c' object='clipping/cdo-intersection.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-intersection.obj `if test -f 'clipping/intersection.c'; then $(CYGPATH_W) 'clipping/intersection.c'; else $(CYGPATH_W) '$(srcdir)/clipping/intersection.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-intersection.obj `if test -f 'clipping/intersection.c'; then $(CYGPATH_W) 'clipping/intersection.c'; else $(CYGPATH_W) '$(srcdir)/clipping/intersection.c'; fi`
 
-cdo-utils.o: clipping/utils.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-utils.o -MD -MP -MF $(DEPDIR)/cdo-utils.Tpo -c -o cdo-utils.o `test -f 'clipping/utils.c' || echo '$(srcdir)/'`clipping/utils.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-utils.Tpo $(DEPDIR)/cdo-utils.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/utils.c' object='cdo-utils.o' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-utils.o: clipping/utils.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-utils.o -MD -MP -MF clipping/$(DEPDIR)/cdo-utils.Tpo -c -o clipping/cdo-utils.o `test -f 'clipping/utils.c' || echo '$(srcdir)/'`clipping/utils.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-utils.Tpo clipping/$(DEPDIR)/cdo-utils.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/utils.c' object='clipping/cdo-utils.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-utils.o `test -f 'clipping/utils.c' || echo '$(srcdir)/'`clipping/utils.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-utils.o `test -f 'clipping/utils.c' || echo '$(srcdir)/'`clipping/utils.c
 
-cdo-utils.obj: clipping/utils.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-utils.obj -MD -MP -MF $(DEPDIR)/cdo-utils.Tpo -c -o cdo-utils.obj `if test -f 'clipping/utils.c'; then $(CYGPATH_W) 'clipping/utils.c'; else $(CYGPATH_W) '$(srcdir)/clipping/utils.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-utils.Tpo $(DEPDIR)/cdo-utils.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/utils.c' object='cdo-utils.obj' libtool=no @AMDEPBACKSLASH@
+clipping/cdo-utils.obj: clipping/utils.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/cdo-utils.obj -MD -MP -MF clipping/$(DEPDIR)/cdo-utils.Tpo -c -o clipping/cdo-utils.obj `if test -f 'clipping/utils.c'; then $(CYGPATH_W) 'clipping/utils.c'; else $(CYGPATH_W) '$(srcdir)/clipping/utils.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) clipping/$(DEPDIR)/cdo-utils.Tpo clipping/$(DEPDIR)/cdo-utils.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='clipping/utils.c' object='clipping/cdo-utils.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-utils.obj `if test -f 'clipping/utils.c'; then $(CYGPATH_W) 'clipping/utils.c'; else $(CYGPATH_W) '$(srcdir)/clipping/utils.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clipping/cdo-utils.obj `if test -f 'clipping/utils.c'; then $(CYGPATH_W) 'clipping/utils.c'; else $(CYGPATH_W) '$(srcdir)/clipping/utils.c'; fi`
 
 cdo-Magplot.o: Magplot.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Magplot.o -MD -MP -MF $(DEPDIR)/cdo-Magplot.Tpo -c -o cdo-Magplot.o `test -f 'Magplot.c' || echo '$(srcdir)/'`Magplot.c
@@ -4874,6 +4920,8 @@ clean-generic:
 distclean-generic:
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f clipping/$(DEPDIR)/$(am__dirstamp)
+	-rm -f clipping/$(am__dirstamp)
 
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
@@ -4884,7 +4932,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool \
 	clean-noinstPROGRAMS mostlyclean-am
 
 distclean: distclean-am
-	-rm -rf ./$(DEPDIR)
+	-rm -rf ./$(DEPDIR) clipping/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-tags
@@ -4930,7 +4978,7 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR)
+	-rm -rf ./$(DEPDIR) clipping/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/src/Merstat.c b/src/Merstat.c
index 159fd9e..9e53884 100644
--- a/src/Merstat.c
+++ b/src/Merstat.c
@@ -44,7 +44,6 @@ void *Merstat(void *argument)
   int vlistID1, vlistID2;
   int gridID1, gridID2 = -1, lastgrid = -1;
   int wstatus = FALSE;
-  int code = 0, oldcode = 0;
   int nlonmax;
   int index, ngrids;
   int recID, nrecs;
@@ -53,10 +52,9 @@ void *Merstat(void *argument)
   int ndiffgrids;
   int taxisID1, taxisID2;
   int needWeights = FALSE;
-  field_t field1, field2;
-  /* RQ */
   int pn = 0;
-  /* QR */
+  field_t field1, field2;
+  char varname[CDI_MAX_NAME];
 
   cdoInitialize(argument);
 
@@ -67,9 +65,7 @@ void *Merstat(void *argument)
   cdoOperatorAdd("meravg",  func_avg,  0, NULL);
   cdoOperatorAdd("mervar",  func_var,  0, NULL);
   cdoOperatorAdd("merstd",  func_std,  0, NULL);
-  /* RQ */
   cdoOperatorAdd("merpctl", func_pctl, 0, NULL);
-  /* QR */
  
   operatorID = cdoOperatorID();
   operfunc = cdoOperatorF1(operatorID);
@@ -153,25 +149,24 @@ void *Merstat(void *argument)
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
 
-	  field1.grid    = vlistInqVarGrid(vlistID1, varID);
+	  field1.grid = vlistInqVarGrid(vlistID1, varID);
 	  if ( needWeights && field1.grid != lastgrid )
 	    {
 	      lastgrid = field1.grid;
 	      wstatus = gridWeights(field1.grid, field1.weight);
 	    }
-	  code = vlistInqVarCode(vlistID1, varID);
-	  if ( wstatus != 0 && tsID == 0 && code != oldcode )
-	    cdoWarning("Using constant area weights for code %d!", oldcode=code);
-
+	  if ( wstatus != 0 && tsID == 0 && levelID == 0 )
+	    {
+	      vlistInqVarName(vlistID1, varID, varname);
+	      cdoWarning("Using constant grid cell area weights for variable %s!", varname);
+	    }
 	  field1.missval = vlistInqVarMissval(vlistID1, varID);
 	  field2.missval = vlistInqVarMissval(vlistID1, varID);
 
-	  /* RQ */
 	  if ( operfunc == func_pctl )
 	    merpctl(field1, & field2, pn);
 	  else  
 	    merfun(field1, &field2, operfunc);
-	  /* QR */  
 
 	  streamDefRecord(streamID2, varID,  levelID);
 	  streamWriteRecord(streamID2, field2.ptr, field2.nmiss);
diff --git a/src/Outputgmt.c b/src/Outputgmt.c
index 77187c3..7a4189e 100644
--- a/src/Outputgmt.c
+++ b/src/Outputgmt.c
@@ -145,9 +145,7 @@ int intersect(double pix, double piy, double pjx, double pjy,
 	     ccw(pkx, pky, plx, ply, pjx, pjy) <= 0 ) );
 }
 
-#ifndef MAX_CORNERS 
-#define MAX_CORNERS 8+1
-#endif
+static
 void verify_grid(int gridtype, int gridsize, int ncorner,
 		double *grid_center_lon, double *grid_center_lat,
 		double *grid_corner_lon, double *grid_corner_lat)
@@ -156,11 +154,12 @@ void verify_grid(int gridtype, int gridsize, int ncorner,
   int l0;
   int nout;
   int isinside, convex, alone, isnegative;
-  int cuts[MAX_CORNERS][MAX_CORNERS];  
+  const int mnv = ncorner+1;
+  int cuts[mnv][mnv];  
   int *alone_cell;          
   int check_corners;
   double lon, lat = 0;
-  double lon_bounds[MAX_CORNERS], lat_bounds[MAX_CORNERS];
+  double lon_bounds[mnv], lat_bounds[mnv];
   double area, sumarea;
 
   alone_cell = (int*) malloc(gridsize*ncorner*sizeof(int));
@@ -385,7 +384,7 @@ void verify_grid(int gridtype, int gridsize, int ncorner,
 
   if ( nout )
     cdoWarning("%d of %d cells are not Convex!", nout, gridsize);
-  
+
   if ( check_corners )
     {
       /* 
diff --git a/src/Remap.c b/src/Remap.c
index f534915..f4a3fc6 100644
--- a/src/Remap.c
+++ b/src/Remap.c
@@ -70,7 +70,7 @@ void get_map_type(int operfunc, int *map_type, int *submap_type, int *num_neighb
       break;
     case REMAPLAF:
     case GENLAF:
-      *map_type = MAP_TYPE_CONSERV;
+      *map_type = MAP_TYPE_CONSERV_YAC;
       *submap_type = SUBMAP_TYPE_LAF;
       break;
     case REMAPSUM:
@@ -108,29 +108,29 @@ int maptype2operfunc(int map_type, int submap_type, int num_neighbors, int remap
 
   if ( map_type == MAP_TYPE_CONSERV )
     {
-      if ( submap_type == SUBMAP_TYPE_LAF )
+      if ( remap_order == 2 )
 	{
-	  operfunc = REMAPLAF;
-	  // cdoPrint("Using remaplaf");
+	  operfunc = REMAPCON2;
+	  // cdoPrint("Using remapcon2");
 	}
       else
 	{
-	  if ( remap_order == 2 )
-	    {
-	      operfunc = REMAPCON2;
-	      // cdoPrint("Using remapcon2");
-	    }
-	  else
-	    {
-	      operfunc = REMAPCON;
-	      // cdoPrint("Using remapcon");
-	    }
+	  operfunc = REMAPCON;
+	  // cdoPrint("Using remapcon");
 	}
     }
   else if ( map_type == MAP_TYPE_CONSERV_YAC )
     {
-      operfunc = REMAPYCON;
-      // cdoPrint("Using remapycon");
+      if ( submap_type == SUBMAP_TYPE_LAF )
+	{
+	  operfunc = REMAPLAF;
+	  // cdoPrint("Using remaplaf");
+	}
+      else
+	{
+	  operfunc = REMAPYCON;
+	  // cdoPrint("Using remapycon");
+	}
     }
   else if ( map_type == MAP_TYPE_BILINEAR )
     {
@@ -175,7 +175,7 @@ void print_remap_info(int operfunc, remapgrid_t *src_grid, remapgrid_t *tgt_grid
   else if ( operfunc == REMAPDIS  || operfunc == GENDIS  )  strcpy(line, "SCRIP distance-weighted average");
   else if ( operfunc == REMAPCON  || operfunc == GENCON  )  strcpy(line, "SCRIP first order conservative");
   else if ( operfunc == REMAPCON2 || operfunc == GENCON2 )  strcpy(line, "SCRIP second order conservative");
-  else if ( operfunc == REMAPLAF  || operfunc == GENLAF  )  strcpy(line, "SCRIP largest area fraction");
+  else if ( operfunc == REMAPLAF  || operfunc == GENLAF  )  strcpy(line, "YAC largest area fraction");
   else if ( operfunc == REMAPYCON || operfunc == GENYCON )  strcpy(line, "YAC first order conservative");
   else                                                      strcpy(line, "Unknown");
 
@@ -217,7 +217,7 @@ int remap_genweights = TRUE;
 int lextrapolate = FALSE;
 int max_remaps = -1;
 int sort_mode = HEAP_SORT;
-double remap_area_min = 0;
+double remap_frac_min = 0;
 
 
 static
@@ -344,9 +344,9 @@ void get_remap_env(void)
       fval = atof(envstr);
       if ( fval > 0 )
 	{
-	  remap_area_min = fval;
+	  remap_frac_min = fval;
 	  if ( cdoVerbose )
-	    cdoPrint("Set REMAP_AREA_MIN to %g", remap_area_min);
+	    cdoPrint("Set REMAP_AREA_MIN to %g", remap_frac_min);
 	}
     }
 
@@ -569,31 +569,24 @@ int set_max_remaps(int vlistID)
 }
 
 static
-int get_norm_opt()
+int get_norm_opt(void)
 {
   int norm_opt = NORM_OPT_FRACAREA;
   char *envstr = getenv("CDO_REMAP_NORMALIZE_OPT");
 
   if ( envstr && *envstr )
     {
-      if      ( memcmp(envstr, "frac", 4) == 0 )
-	norm_opt = NORM_OPT_FRACAREA;
-      else if ( memcmp(envstr, "dest", 4) == 0 )
-	norm_opt = NORM_OPT_DESTAREA;
-      else if ( memcmp(envstr, "none", 4) == 0 )
-	norm_opt = NORM_OPT_NONE;
-      else
-	cdoWarning("CDO_REMAP_NORMALIZE_OPT=%s unsupported!", envstr);
+      if      ( memcmp(envstr, "frac", 4) == 0 ) norm_opt = NORM_OPT_FRACAREA;
+      else if ( memcmp(envstr, "dest", 4) == 0 ) norm_opt = NORM_OPT_DESTAREA;
+      else if ( memcmp(envstr, "none", 4) == 0 ) norm_opt = NORM_OPT_NONE;
+      else cdoWarning("CDO_REMAP_NORMALIZE_OPT=%s unsupported!", envstr);
     }
 
   if ( cdoVerbose )
     {
-      if ( norm_opt == NORM_OPT_FRACAREA )
-	cdoPrint("Normalization option: frac");
-      else if ( norm_opt == NORM_OPT_DESTAREA )
-	cdoPrint("Normalization option: dest");
-      else
-	cdoPrint("Normalization option: none");
+      if      ( norm_opt == NORM_OPT_FRACAREA ) cdoPrint("Normalization option: frac");
+      else if ( norm_opt == NORM_OPT_DESTAREA ) cdoPrint("Normalization option: dest");
+      else                                      cdoPrint("Normalization option: none");
     }
 
   return (norm_opt);
@@ -602,6 +595,7 @@ int get_norm_opt()
 static
 void remap_normalize(int norm_opt, int gridsize, double *array, double missval, remapgrid_t *tgt_grid)
 {
+  /* used only to check the result of remapcon */
   int i;
   double grid_err;
 
@@ -612,8 +606,9 @@ void remap_normalize(int norm_opt, int gridsize, double *array, double missval,
 	  if ( !DBL_IS_EQUAL(array[i], missval) )
 	    {
 	      grid_err = tgt_grid->cell_frac[i]*tgt_grid->cell_area[i];
+
 	      if ( fabs(grid_err) > 0 )
-		array[i] = array[i]/grid_err;
+		array[i] /= grid_err;
 	      else
 		array[i] = missval;
 	    }
@@ -626,19 +621,23 @@ void remap_normalize(int norm_opt, int gridsize, double *array, double missval,
 	  if ( !DBL_IS_EQUAL(array[i], missval) )
 	    {
 	      if ( fabs(tgt_grid->cell_frac[i]) > 0 )
-		array[i] = array[i]/tgt_grid->cell_frac[i];
+		array[i] /= tgt_grid->cell_frac[i];
 	      else
 		array[i] = missval;
 	    }
 	}
     }
+}
 
-  if ( remap_area_min > 0 )
+static
+void remap_set_frac_min(int gridsize, double *array, double missval, remapgrid_t *tgt_grid)
+{
+  if ( remap_frac_min > 0 )
     {
-      for ( i = 0; i < gridsize; i++ )
+      for ( int i = 0; i < gridsize; i++ )
 	{
 	  //printf("%d %g %g\n", i, remaps[r].tgt_grid.cell_frac[i], remaps[r].tgt_grid.cell_area[i]);
-	  if ( tgt_grid->cell_frac[i] < remap_area_min ) array[i] = missval;
+	  if ( tgt_grid->cell_frac[i] < remap_frac_min ) array[i] = missval;
 	}
     }
 }
@@ -1069,10 +1068,10 @@ void *Remap(void *argument)
 		{
 		  print_remap_info(operfunc, &remaps[r].src_grid, &remaps[r].tgt_grid, nmiss1);
 
-		  if      ( map_type == MAP_TYPE_CONSERV   ) scrip_remap_weights_conserv(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
-		  else if ( map_type == MAP_TYPE_BILINEAR  ) scrip_remap_weights_bilinear(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
-		  else if ( map_type == MAP_TYPE_BICUBIC   ) scrip_remap_weights_bicubic(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
-		  else if ( map_type == MAP_TYPE_DISTWGT   ) scrip_remap_weights_distwgt(num_neighbors, &remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
+		  if      ( map_type == MAP_TYPE_CONSERV     ) scrip_remap_weights_conserv(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
+		  else if ( map_type == MAP_TYPE_BILINEAR    ) scrip_remap_weights_bilinear(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
+		  else if ( map_type == MAP_TYPE_BICUBIC     ) scrip_remap_weights_bicubic(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
+		  else if ( map_type == MAP_TYPE_DISTWGT     ) scrip_remap_weights_distwgt(num_neighbors, &remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
 		  else if ( map_type == MAP_TYPE_CONSERV_YAC ) remap_weights_conserv(&remaps[r].src_grid, &remaps[r].tgt_grid, &remaps[r].vars);
 
 		  if ( remaps[r].vars.num_links != remaps[r].vars.max_links )
@@ -1123,9 +1122,13 @@ void *Remap(void *argument)
 
 	  gridsize2 = gridInqSize(gridID2);
 
-	  /* used only to check the result of remapcon */
 	  if ( operfunc == REMAPCON || operfunc == REMAPCON2 || operfunc == REMAPYCON )
-	    remap_normalize(remaps[r].vars.norm_opt, gridsize2, array2, missval, &remaps[r].tgt_grid);
+	    {
+	      /* used only to check the result of remapcon */
+	      if ( 0 ) remap_normalize(remaps[r].vars.norm_opt, gridsize2, array2, missval, &remaps[r].tgt_grid);
+
+	      remap_set_frac_min(gridsize2, array2, missval, &remaps[r].tgt_grid);
+	    }
 
 	  if ( operfunc == REMAPSUM )
 	    {
@@ -1183,7 +1186,7 @@ void *Remap(void *argument)
 
   streamClose(streamID2);
 
-  WRITE_REMAP:
+ WRITE_REMAP:
  
   if ( lwrite_remap ) 
     write_remap_scrip(cdoStreamName(1)->args, map_type, submap_type, num_neighbors, remap_order,
diff --git a/src/Runpctl.c b/src/Runpctl.c
index bdd3044..3cfda6d 100644
--- a/src/Runpctl.c
+++ b/src/Runpctl.c
@@ -33,7 +33,6 @@ void *Runpctl(void *argument)
   int gridsize;
   int varID;
   int recID;
-  int gridID;
   int nrecs, nrecords;
   int levelID;
   int tsID;
diff --git a/src/Selbox.c b/src/Selbox.c
index 9e1f54a..e650600 100644
--- a/src/Selbox.c
+++ b/src/Selbox.c
@@ -871,6 +871,9 @@ void *Selbox(void *argument)
 	{
 	  if ( operatorID == SELLONLATBOX )
 	    {
+	      int gridsize = gridInqSize(gridID1);
+	      if ( gridsize == 1 ) continue;
+
 	      if ( gridtype == GRID_UNSTRUCTURED )
 		gridID2 = gencellgrid(gridID1, &sbox[index].nvals, &sbox[index].cellidx);
 	      else
@@ -913,6 +916,11 @@ void *Selbox(void *argument)
 	}
     }
 
+  for ( varID = 0; varID < nvars; varID++ )
+    if ( vars[varID] == TRUE ) break;
+
+  if ( varID >= nvars ) cdoWarning("No variables selected!");
+
   streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
 
   streamDefVlist(streamID2, vlistID2);
diff --git a/src/Select.c b/src/Select.c
index 854624a..a34b57e 100644
--- a/src/Select.c
+++ b/src/Select.c
@@ -576,9 +576,12 @@ void *Select(void *argument)
   streamCnt = cdoStreamCnt();
   nfiles = streamCnt - 1;
 
+  if ( !cdoVerbose && nfiles > 1 ) progressInit();
+
   tsID2 = 0;
   for ( indf = 0; indf < nfiles; indf++ )
     {
+      if ( !cdoVerbose && nfiles > 1 ) progressStatus(0, 1, (indf+1.)/nfiles);
       if ( cdoVerbose ) cdoPrint("Process file: %s", cdoStreamName(indf)->args);
 
       streamID1 = streamOpenRead(cdoStreamName(indf));
@@ -778,11 +781,12 @@ void *Select(void *argument)
 	      if ( varID == nvars2 ) ntsteps = 0;
 	    }
 
-	  if ( operatorID == SELECT && npar_timestep == 1 ) ntsteps = 1;
+	  int ntsteps2 = ntsteps;
+	  if ( operatorID == SELECT && npar_timestep == 1 ) ntsteps2 = 1;
 	  
-	  if ( ntsteps == 0 || ntsteps == 1 ) vlistDefNtsteps(vlistID2, ntsteps);
+	  if ( ntsteps2 == 0 || ntsteps2 == 1 ) vlistDefNtsteps(vlistID2, ntsteps2);
 
-	  if ( ntsteps == 0 && nfiles > 1 )
+	  if ( ntsteps2 == 0 && nfiles > 1 )
 	    {	      
 	      for ( varID = 0; varID < nvars2; ++varID )
 		vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
diff --git a/src/Selvar.c b/src/Selvar.c
index 49ecb4f..db98b7c 100644
--- a/src/Selvar.c
+++ b/src/Selvar.c
@@ -382,7 +382,7 @@ void *Selvar(void *argument)
 	    }
 	}
     }
-  
+
   if ( npar == 0 ) cdoAbort("No variables selected!");
 
   vlistID2 = vlistCreate();
diff --git a/src/Setgrid.c b/src/Setgrid.c
index 3a99071..488947f 100644
--- a/src/Setgrid.c
+++ b/src/Setgrid.c
@@ -193,8 +193,6 @@ void *Setgrid(void *argument)
   taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
-
   if ( operatorID == SETGRID )
     {
       found = 0;
@@ -351,6 +349,8 @@ void *Setgrid(void *argument)
 	}
     }
 
+  streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
   streamDefVlist(streamID2, vlistID2);
   //vlistPrint(vlistID2);
 
diff --git a/src/Sinfo.c b/src/Sinfo.c
index f7681ff..24a3cce 100644
--- a/src/Sinfo.c
+++ b/src/Sinfo.c
@@ -31,16 +31,18 @@
 
 const char * tunit2str(int tunits)
 {
-  if      ( tunits == TUNIT_YEAR )    return ("years");
-  else if ( tunits == TUNIT_MONTH )   return ("months");
-  else if ( tunits == TUNIT_DAY )     return ("days");
-  else if ( tunits == TUNIT_12HOURS ) return ("12hours");
-  else if ( tunits == TUNIT_6HOURS )  return ("6hours");
-  else if ( tunits == TUNIT_3HOURS )  return ("3hours");
-  else if ( tunits == TUNIT_HOUR )    return ("hours");
-  else if ( tunits == TUNIT_MINUTE )  return ("minutes");
-  else if ( tunits == TUNIT_SECOND )  return ("seconds");
-  else                                return ("unknown");
+  if      ( tunits == TUNIT_YEAR )       return ("years");
+  else if ( tunits == TUNIT_MONTH )      return ("months");
+  else if ( tunits == TUNIT_DAY )        return ("days");
+  else if ( tunits == TUNIT_12HOURS )    return ("12hours");
+  else if ( tunits == TUNIT_6HOURS )     return ("6hours");
+  else if ( tunits == TUNIT_3HOURS )     return ("3hours");
+  else if ( tunits == TUNIT_HOUR )       return ("hours");
+  else if ( tunits == TUNIT_30MINUTES )  return ("30minutes");
+  else if ( tunits == TUNIT_QUARTER )    return ("15minutes");
+  else if ( tunits == TUNIT_MINUTE )     return ("minutes");
+  else if ( tunits == TUNIT_SECOND )     return ("seconds");
+  else                                   return ("unknown");
 }
 
 
@@ -177,6 +179,8 @@ void *Sinfo(void *argument)
 	  else if ( tsteptype == TSTEP_MIN      ) fprintf(stdout, "%-8s ", "min");
 	  else if ( tsteptype == TSTEP_MAX      ) fprintf(stdout, "%-8s ", "max");
 	  else if ( tsteptype == TSTEP_ACCUM    ) fprintf(stdout, "%-8s ", "accum");
+	  else if ( tsteptype == TSTEP_RANGE    ) fprintf(stdout, "%-8s ", "range");
+	  else if ( tsteptype == TSTEP_DIFF     ) fprintf(stdout, "%-8s ", "diff");
 	  else                                    fprintf(stdout, "%-8s ", "unknown");
 
 	  /* ensemble information */
diff --git a/src/Sort.c b/src/Sort.c
index 4755414..5b53e7e 100644
--- a/src/Sort.c
+++ b/src/Sort.c
@@ -49,8 +49,8 @@ static
 int cmpvarcode(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const varinfo_t *x = s1;
-  const varinfo_t *y = s2;
+  const varinfo_t *x = (const varinfo_t *) s1;
+  const varinfo_t *y = (const varinfo_t *) s2;
   /*
   printf("%d %d  %d %d\n", x->code, y->code, x, y);
   */
@@ -63,8 +63,8 @@ int cmpvarcode(const void *s1, const void *s2)
 static
 int cmpvarname(const void *s1, const void *s2)
 {
-  const varinfo_t *x = s1;
-  const varinfo_t *y = s2;
+  const varinfo_t *x = (const varinfo_t *) s1;
+  const varinfo_t *y = (const varinfo_t *) s2;
 
   return (strcmp(x->name, y->name));
 }
@@ -73,8 +73,8 @@ static
 int cmpvarlevel(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const levinfo_t *x = s1;
-  const levinfo_t *y = s2;
+  const levinfo_t *x = (const levinfo_t *) s1;
+  const levinfo_t *y = (const levinfo_t *) s2;
 
   if      ( x->level < y->level ) cmp = -1;
   else if ( x->level > y->level ) cmp =  1;
@@ -86,8 +86,8 @@ static
 int cmpvarlevelrev(const void *s1, const void *s2)
 {
   int cmp = 0;
-  const levinfo_t *x = s1;
-  const levinfo_t *y = s2;
+  const levinfo_t *x = (const levinfo_t *) s1;
+  const levinfo_t *y = (const levinfo_t *) s2;
 
   if      ( x->level > y->level ) cmp = -1;
   else if ( x->level < y->level ) cmp =  1;
@@ -132,6 +132,7 @@ void *Sort(void *argument)
   double **vardata = NULL;
   varinfo_t *varInfo;
   int taxisID1, taxisID2;
+  int (*cmpvarlev)(const void *, const void *) = cmpvarlevel;
 
   cdoInitialize(argument);
 
@@ -141,6 +142,14 @@ void *Sort(void *argument)
 
   operatorID = cdoOperatorID();
 
+  if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
+
+  if ( operatorID == SORTLEVEL && operatorArgc() == 1 )
+    {
+      int iarg = atoi(operatorArgv()[0]);
+      if ( iarg < 0 ) cmpvarlev = cmpvarlevelrev;
+    }
+
   streamID1 = streamOpenRead(cdoStreamName(0));
 
   vlistID1 = streamInqVlist(streamID1);
@@ -232,7 +241,7 @@ void *Sort(void *argument)
 	      for ( vindex = 0; vindex < nvars; vindex++ )
 		{
 		  nlevs = varInfo[vindex].nlevs;
-		  qsort(varInfo[vindex].levInfo, nlevs, sizeof(levinfo_t), cmpvarlevel);
+		  qsort(varInfo[vindex].levInfo, nlevs, sizeof(levinfo_t), cmpvarlev);
 		}
 	    }
 
diff --git a/src/Split.c b/src/Split.c
index 5dd01bf..e493eb4 100644
--- a/src/Split.c
+++ b/src/Split.c
@@ -71,6 +71,8 @@ void *Split(void *argument)
 
   cdoInitialize(argument);
 
+  if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
+
   SPLITCODE   = cdoOperatorAdd("splitcode",   0, 0, NULL);
   SPLITPARAM  = cdoOperatorAdd("splitparam",  0, 0, NULL);
   SPLITNAME   = cdoOperatorAdd("splitname",   0, 0, NULL);
diff --git a/src/Splitrec.c b/src/Splitrec.c
index 7cdfbf6..35a7bb2 100644
--- a/src/Splitrec.c
+++ b/src/Splitrec.c
@@ -47,6 +47,8 @@ void *Splitrec(void *argument)
 
   cdoInitialize(argument);
 
+  if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
+
   if ( UNCHANGED_RECORD ) lcopy = TRUE;
 
   streamID1 = streamOpenRead(cdoStreamName(0));
diff --git a/src/Splitsel.c b/src/Splitsel.c
index 182a1d1..2c770c4 100644
--- a/src/Splitsel.c
+++ b/src/Splitsel.c
@@ -58,6 +58,8 @@ void *Splitsel(void *argument)
 
   cdoInitialize(argument);
 
+  if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
+
   cdoOperatorAdd("splitsel",  0,  0, NULL);
 
   if ( UNCHANGED_RECORD ) lcopy = TRUE;
diff --git a/src/Splittime.c b/src/Splittime.c
index 446b842..9448876 100644
--- a/src/Splittime.c
+++ b/src/Splittime.c
@@ -86,11 +86,16 @@ void *Splittime(void *argument)
 
   cdoInitialize(argument);
 
+  if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
+
   SPLITHOUR = cdoOperatorAdd("splithour", func_time, 10000, NULL);
   SPLITDAY  = cdoOperatorAdd("splitday",  func_date,     1, NULL);
   SPLITMON  = cdoOperatorAdd("splitmon",  func_date,   100, NULL);
   SPLITSEAS = cdoOperatorAdd("splitseas", func_date,   100, NULL);
 
+  UNUSED(SPLITDAY);
+  UNUSED(SPLITHOUR);
+
   operatorID = cdoOperatorID();
   operfunc   = cdoOperatorF1(operatorID);
   operintval = cdoOperatorF2(operatorID);
diff --git a/src/Splityear.c b/src/Splityear.c
index 6189b5e..5d4ac40 100644
--- a/src/Splityear.c
+++ b/src/Splityear.c
@@ -54,6 +54,8 @@ void *Splityear(void *argument)
 
   cdoInitialize(argument);
 
+  if ( processSelf() != 0 ) cdoAbort("This operator can't be combined with other operators!");
+
   if ( UNCHANGED_RECORD ) lcopy = TRUE;
 
   memset(cyear, 0, MAX_YEARS*sizeof(int));
diff --git a/src/Timsort.c b/src/Timsort.c
index e3b2fe9..5483ed1 100644
--- a/src/Timsort.c
+++ b/src/Timsort.c
@@ -22,10 +22,6 @@
 */
 
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
-
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
@@ -62,7 +58,6 @@ void *Timsort(void *argument)
   int nmiss;
   int nvars, nlevel;
   int *vdate = NULL, *vtime = NULL;
-  int ompthID;
   double **sarray = NULL;
   field_t ***vars = NULL;
 
@@ -128,15 +123,12 @@ void *Timsort(void *argument)
       for ( levelID = 0; levelID < nlevel; levelID++ )
 	{
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, ompthID, tsID)
+#pragma omp parallel for default(shared) private(i, tsID)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
-#if defined(_OPENMP)
-	      ompthID = omp_get_thread_num();
-#else
-	      ompthID = 0;
-#endif
+	      int ompthID = cdo_omp_get_thread_num();
+
 	      for ( tsID = 0; tsID < nts; tsID++ )
 		sarray[ompthID][tsID] = vars[tsID][varID][levelID].ptr[i];
 
diff --git a/src/Tstepcount.c b/src/Tstepcount.c
index 7aba987..4cb7bf1 100644
--- a/src/Tstepcount.c
+++ b/src/Tstepcount.c
@@ -21,10 +21,6 @@
       Tstepcount  tstepcount  Count number of timesteps
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
-
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
@@ -57,7 +53,6 @@ double tstepcount(long nts, double missval1, double *array1, double refval)
 
 void *Tstepcount(void *argument)
 {
-  int ompthID;
   int gridsize;
   int nrecs;
   int gridID, varID, levelID, recID;
@@ -149,16 +144,13 @@ void *Tstepcount(void *argument)
       for ( levelID = 0; levelID < nlevel; levelID++ )
 	{
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(i, ompthID, tsID) \
+#pragma omp parallel for default(shared) private(i, tsID) \
   schedule(dynamic,1)
 #endif
 	  for ( i = 0; i < gridsize; i++ )
 	    {
-#if defined(_OPENMP)
-              ompthID = omp_get_thread_num();
-#else
-              ompthID = 0;
-#endif
+	      int ompthID = cdo_omp_get_thread_num();
+
 	      for ( tsID = 0; tsID < nts; tsID++ )
 		mem[ompthID].array1[tsID] = vars[tsID][varID][levelID].ptr[i];
 
diff --git a/src/Ydrunstat.c b/src/Ydrunstat.c
index 166b04a..1accdd5 100644
--- a/src/Ydrunstat.c
+++ b/src/Ydrunstat.c
@@ -60,10 +60,8 @@ void *Ydrunstat(void *argument)
 {
   int operatorID;
   int operfunc;
-  int gridsize;
   int varID;
   int recID;
-  int gridID;
   int nrecs, nrecords;
   int levelID;
   int tsID;
@@ -72,11 +70,8 @@ void *Ydrunstat(void *argument)
   int streamID1, streamID2;
   int vlistID1, vlistID2;
   int nmiss;
-  int nvars, nlevels;
   int *recVarID, *recLevelID;
-  int lmean = FALSE, lvarstd = FALSE, lstd = FALSE;
-  double missval;
-  double divisor;
+  int lvarstd = FALSE;
   field_t ***vars1 = NULL, ***vars2 = NULL;
   datetime_t *datetime;
   int taxisID1, taxisID2;
@@ -103,10 +98,7 @@ void *Ydrunstat(void *argument)
   operatorInputArg("number of timesteps");
   ndates = atoi(operatorArgv()[0]);
 
-  lmean   = operfunc == func_mean || operfunc == func_avg;
-  lstd    = operfunc == func_std || operfunc == func_std1;
   lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
-  divisor = operfunc == func_std1 || operfunc == func_var1;
   
   streamID1 = streamOpenRead(cdoStreamName(0));
 
@@ -125,7 +117,6 @@ void *Ydrunstat(void *argument)
 
   streamDefVlist(streamID2, vlistID2);
 
-  nvars    = vlistNvars(vlistID1);
   nrecords = vlistNrecs(vlistID1);
 
   recVarID   = (int*) malloc(nrecords*sizeof(int));
@@ -245,6 +236,23 @@ void *Ydrunstat(void *argument)
       tsID++;
     }
 
+  int outyear = 1e9;
+  for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+    if ( stats->nsets[dayoy] )
+      {
+	int year, month, day;
+	cdiDecodeDate(stats->vdate[dayoy], &year, &month, &day);
+	if ( year < outyear ) outyear = year;
+      }
+
+  for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+    if ( stats->nsets[dayoy] )
+      {
+	int year, month, day;
+	cdiDecodeDate(stats->vdate[dayoy], &year, &month, &day);
+	stats->vdate[dayoy] = cdiEncodeDate(outyear, month, day);
+      }
+
   ydstatFinalize(stats, operfunc);
   otsID = 0;
 
@@ -363,10 +371,8 @@ void ydstatUpdate(YDAY_STATS *stats, int vdate, int vtime,
   lvarstd = vars2 != NULL;
 
   nvars = vlistNvars(stats->vlist);
-  
-  year  =  vdate / 10000;
-  month = (vdate - year * 10000) / 100;
-  day   =  vdate - year * 10000 - month * 100;
+
+  cdiDecodeDate(vdate, &year, &month, &day);
 
   if ( month >= 1 && month <= 12 )
     dayoy = (month - 1) * 31 + day;
diff --git a/src/cdo.h b/src/cdo.h
index e45e053..77721d2 100644
--- a/src/cdo.h
+++ b/src/cdo.h
@@ -82,6 +82,9 @@ extern int cdoDiag;
 extern int cdoNumVarnames;
 extern char **cdoVarnames;
 
+int cdo_omp_get_thread_num(void);
+
+
 void    cdiError(int cdiErrno, const char *fmt, ...);
 void    cdoAbort(const char *fmt, ...);
 void    cdoWarning(const char *fmt, ...);
@@ -93,6 +96,7 @@ void timer_start(int it);
 void timer_stop(int it);
 double timer_val(int it);
 
+
 void    operatorInputArg(const char *enter);
 int     operatorArgc(void);
 char  **operatorArgv(void);
diff --git a/src/cdo_int.h b/src/cdo_int.h
index 0f8bb4c..bfdbbf2 100644
--- a/src/cdo_int.h
+++ b/src/cdo_int.h
@@ -193,5 +193,7 @@ void minmaxval(long nvals, double *array, int *imiss, double *minval, double *ma
 
 off_t filesize(const char *filename);
 
+char *expand_filename(const char *string);
+
 
 #endif  /* _CDO_INT_H */
diff --git a/src/cdo_vlist.c b/src/cdo_vlist.c
index 906bc29..e56cd61 100644
--- a/src/cdo_vlist.c
+++ b/src/cdo_vlist.c
@@ -175,23 +175,26 @@ void vlistCompare(int vlistID1, int vlistID2, int flag)
 
   for ( varID = 0; varID < nvars; varID++ )
     {
-      if ( flag & CMP_CODE )
-	if ( vlistInqVarCode(vlistID1, varID) != vlistInqVarCode(vlistID2, varID) )
-	  cdoAbort("Input streams have different structure!");
-
-      if ( (flag & CMP_NAME) && nvars > 1 )
+      if ( nvars > 1 )
 	{
-	  char name1[CDI_MAX_NAME], name2[CDI_MAX_NAME];
-	  vlistInqVarName(vlistID1, varID, name1);
-	  vlistInqVarName(vlistID2, varID, name2);
-	  strtolower(name1);
-	  strtolower(name2);
-	  if ( strcmp(name1, name2) != 0 )
+	  if ( flag & CMP_CODE )
+	    if ( vlistInqVarCode(vlistID1, varID) != vlistInqVarCode(vlistID2, varID) )
+	      cdoAbort("Input streams have different structure!");
+
+	  if ( flag & CMP_NAME )
 	    {
-	      cdoWarning("Input streams have different parameters!");
-	      lchecknames = TRUE;
-	      flag -= CMP_NAME;
-	      //    break;
+	      char name1[CDI_MAX_NAME], name2[CDI_MAX_NAME];
+	      vlistInqVarName(vlistID1, varID, name1);
+	      vlistInqVarName(vlistID2, varID, name2);
+	      strtolower(name1);
+	      strtolower(name2);
+	      if ( strcmp(name1, name2) != 0 )
+		{
+		  cdoWarning("Input streams have different parameters!");
+		  lchecknames = TRUE;
+		  flag -= CMP_NAME;
+		  //    break;
+		}
 	    }
 	}
 
diff --git a/src/clipping/area.c b/src/clipping/area.c
index e5614bd..d350e98 100644
--- a/src/clipping/area.c
+++ b/src/clipping/area.c
@@ -690,7 +690,7 @@ double partial_area ( double a_lon, double a_lat,
 
 /* ----------------------------------- */
 
-static double inline inner_angle ( double plat, double plon,
+static inline double inner_angle ( double plat, double plon,
                                    double qlat, double qlon ) {
 
   double t = sin((qlon-plon))*cos(qlat);
diff --git a/src/clipping/clipping.c b/src/clipping/clipping.c
index fb2e4b5..3ef1867 100644
--- a/src/clipping/clipping.c
+++ b/src/clipping/clipping.c
@@ -88,6 +88,8 @@ static unsigned get_cell_points_ordering(struct point_list * cell);
 static void generate_overlap_cell(struct point_list * list,
                                   struct grid_cell * cell);
 
+static enum cell_type get_cell_type(struct grid_cell target_cell);
+
 /* ------------------------- */
 
 void compute_overlap_areas(unsigned N,
@@ -132,6 +134,124 @@ void compute_overlap_areas(unsigned N,
 
 /* ------------------------- */
 
+void compute_concave_overlap_areas (unsigned N,
+                                    struct grid_cell * source_cell,
+                                    struct grid_cell target_cell,
+                                    double * target_node_x,
+                                    double * target_node_y,
+                                    double * partial_areas) {
+  enum cell_type target_cell_type;
+
+  if ( target_cell.num_corners > 3 )
+    target_cell_type = get_cell_type (target_cell);
+
+  if ( target_cell.num_corners < 4 || target_cell_type == LON_LAT_CELL ) {
+    compute_overlap_areas (N, source_cell, target_cell, partial_areas);
+    return;
+  }
+
+  if ( target_node_x == NULL || target_node_y == NULL )
+    abort_message("ERROR: missing target point coordinates "
+		  "(x_coordinates == NULL || y_coordinates == NULL)",
+		  __FILE__, __LINE__);
+
+  struct grid_cell target_partial_cell =
+    {.coordinates_x   = (double[3]){-1},
+     .coordinates_y   = (double[3]){-1},
+     .coordinates_xyz = (double[3*3]){-1},
+     .edge_type       = (enum edge_type[3]) {GREAT_CIRCLE},
+     .num_corners     = 3};
+
+  static struct grid_cell * overlap_buffer = NULL;
+  static unsigned overlap_buffer_size = 0;
+
+  // ensure that there are enough buffer cells
+
+  if (overlap_buffer_size < N) {
+
+    unsigned old_overlap_buffer_size = overlap_buffer_size;
+
+    ENSURE_ARRAY_SIZE(overlap_buffer, overlap_buffer_size, N);
+
+    for (; old_overlap_buffer_size < overlap_buffer_size;
+         ++old_overlap_buffer_size)
+      init_grid_cell(overlap_buffer + old_overlap_buffer_size);
+  }
+
+  /* Do the clipping and get the cell for the overlapping area */
+
+  for ( unsigned n = 0; n < N; n++) partial_areas[n] = 0.0;
+
+  // common node point to all partial target cells
+  target_partial_cell.coordinates_x[0] = *target_node_x;
+  target_partial_cell.coordinates_y[0] = *target_node_y;
+
+  LLtoXYZ ( *target_node_x, *target_node_y, target_partial_cell.coordinates_xyz );
+
+  for ( unsigned num_corners = 0; num_corners < target_cell.num_corners; ++num_corners ) {
+
+    unsigned corner_a = num_corners;
+    unsigned corner_b = (num_corners+1)%target_cell.num_corners;
+
+    // skip clipping and area calculation for degenerated triangles
+    //
+    // If this is not sufficient, instead we can try something like:
+    //
+    //     struct point_list target_list
+    //     init_point_list(&target_list);
+    //     generate_point_list(&target_list, target_cell);
+    //     struct grid_cell temp_target_cell;
+    //     generate_overlap_cell(target_list, temp_target_cell);
+    //     free_point_list(&target_list);
+    //
+    // and use temp_target_cell for triangulation.
+    //
+    // Compared to the if statement below the alternative seems
+    // to be quite costly.
+
+    if ( ( ( fabs(target_cell.coordinates_xyz[0+3*corner_a]-target_cell.coordinates_xyz[0+3*corner_b]) < tol ) &&
+           ( fabs(target_cell.coordinates_xyz[1+3*corner_a]-target_cell.coordinates_xyz[1+3*corner_b]) < tol ) &&
+           ( fabs(target_cell.coordinates_xyz[2+3*corner_a]-target_cell.coordinates_xyz[2+3*corner_b]) < tol ) ) ||
+    	 ( ( fabs(target_cell.coordinates_xyz[0+3*corner_a]-target_partial_cell.coordinates_xyz[0]) < tol    ) &&
+           ( fabs(target_cell.coordinates_xyz[1+3*corner_a]-target_partial_cell.coordinates_xyz[1]) < tol    ) &&
+           ( fabs(target_cell.coordinates_xyz[2+3*corner_a]-target_partial_cell.coordinates_xyz[2]) < tol    ) ) ||
+         ( ( fabs(target_cell.coordinates_xyz[0+3*corner_b]-target_partial_cell.coordinates_xyz[0]) < tol    ) &&
+           ( fabs(target_cell.coordinates_xyz[1+3*corner_b]-target_partial_cell.coordinates_xyz[1]) < tol    ) &&
+           ( fabs(target_cell.coordinates_xyz[2+3*corner_b]-target_partial_cell.coordinates_xyz[2]) < tol    ) ) )
+       continue;
+
+    target_partial_cell.coordinates_x[1] = target_cell.coordinates_x[corner_a];
+    target_partial_cell.coordinates_y[1] = target_cell.coordinates_y[corner_a];
+    target_partial_cell.coordinates_x[2] = target_cell.coordinates_x[corner_b];
+    target_partial_cell.coordinates_y[2] = target_cell.coordinates_y[corner_b];
+
+    target_partial_cell.coordinates_xyz[0+3*1] = target_cell.coordinates_xyz[0+3*corner_a];
+    target_partial_cell.coordinates_xyz[1+3*1] = target_cell.coordinates_xyz[1+3*corner_a];
+    target_partial_cell.coordinates_xyz[2+3*1] = target_cell.coordinates_xyz[2+3*corner_a];
+    target_partial_cell.coordinates_xyz[0+3*2] = target_cell.coordinates_xyz[0+3*corner_b];
+    target_partial_cell.coordinates_xyz[1+3*2] = target_cell.coordinates_xyz[1+3*corner_b];
+    target_partial_cell.coordinates_xyz[2+3*2] = target_cell.coordinates_xyz[2+3*corner_b];
+
+    cell_clipping ( N, source_cell, target_partial_cell, overlap_buffer);
+
+    /* Get the partial areas for the overlapping regions as sum over the partial target cells. */
+
+    for (unsigned n = 0; n < N; n++) {
+      partial_areas[n] += huiliers_area (overlap_buffer[n]);
+      // we cannot use pole_area because it is rather inaccurate for great circle
+      // edges that are nearly circles of longitude
+      //partial_areas[n] = pole_area (overlap_buffer[n]);
+    }
+  }
+
+#ifdef VERBOSE
+  for (unsigned n = 0; n < N; n++)
+	    printf("overlap area %i: %lf \n", n, partial_areas[n]);
+#endif
+}
+
+/* ------------------------- */
+
 static double dotproduct(double a[], double b[]) {
 
   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
@@ -323,6 +443,9 @@ static void get_edge_middle_point(double a[3], double b[3],
 
     default:
       abort_message("ERROR: invalid edge type\n", __FILE__, __LINE__);
+      middle[0] = -1; // program should never reach this point
+      middle[1] = -1;
+      middle[2] = -1;
   };
 }
 
@@ -336,8 +459,37 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
                          struct point_list target_list, int target_ordering,
                          unsigned nct, double * tgt_edge_norm_vec) {
 
-  struct point_list_element * prev_tgt_point = target_list.first;
-  struct point_list_element * curr_tgt_point = target_list.first->next;
+  struct {
+    double * edge_norm_vec;
+    struct point_list_element * point;
+  } tgt_points[nct];
+
+  // to avoid some problems that can occur close the the pole, we process the
+  // target lat-circle edges at the end
+  {
+
+    int count = 0;
+
+    struct point_list_element * curr_tgt_point = target_list.first;
+
+    for (int i = 0; i < nct; ++i, curr_tgt_point = curr_tgt_point->next) {
+
+      if (curr_tgt_point->edge_type == LAT_CIRCLE) continue;
+
+      tgt_points[count].edge_norm_vec = tgt_edge_norm_vec + i * 3;
+      tgt_points[count++].point = curr_tgt_point;
+    }
+
+    if (count != nct) {
+      for (int i = 0; i < nct; ++i, curr_tgt_point = curr_tgt_point->next) {
+
+        if (curr_tgt_point->edge_type != LAT_CIRCLE) continue;
+
+        tgt_points[count].edge_norm_vec = tgt_edge_norm_vec + i * 3;
+        tgt_points[count++].point = curr_tgt_point;
+      }
+    }
+  }
 
   for (int i = 0; i < nct; ++i) {
 
@@ -347,31 +499,32 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
     unsigned prev_is_inside, curr_is_inside;
 
     prev_is_inside = is_inside(prev_src_point->vec_coords,
-                               tgt_edge_norm_vec + 3 * i,
-                               prev_tgt_point->edge_type, target_ordering);
+                               tgt_points[i].edge_norm_vec,
+                               tgt_points[i].point->edge_type, target_ordering);
 
     // for all edges of the target cell
     do {
 
       curr_is_inside = is_inside(curr_src_point->vec_coords,
-                                 tgt_edge_norm_vec + 3 * i,
-                                 prev_tgt_point->edge_type, target_ordering);
+                                 tgt_points[i].edge_norm_vec,
+                                 tgt_points[i].point->edge_type,
+                                 target_ordering);
 
       double p[3], q[3];
-      int intersect;
+      int intersect = -1;
 
       if ((curr_is_inside + prev_is_inside == 1) ||
           (((prev_src_point->edge_type == LAT_CIRCLE) ^
-            (prev_tgt_point->edge_type == LAT_CIRCLE)) && 
+            (tgt_points[i].point->edge_type == LAT_CIRCLE)) &&
            (prev_is_inside + curr_is_inside < 4))) {
 
         // get intersection points
         intersect = intersect_vec(prev_src_point->edge_type,
                                   prev_src_point->vec_coords,
                                   curr_src_point->vec_coords,
-                                  prev_tgt_point->edge_type,
-                                  prev_tgt_point->vec_coords,
-                                  curr_tgt_point->vec_coords,
+                                  tgt_points[i].point->edge_type,
+                                  tgt_points[i].point->vec_coords,
+                                  tgt_points[i].point->next->vec_coords,
                                   p, q);
 
         // if both edges are on an identical great circle
@@ -397,27 +550,28 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
 
           struct point_list_element * temp_src_point;
 
-          switch (prev_tgt_point->edge_type) {
+          switch (tgt_points[i].point->edge_type) {
 
             case (LON_CIRCLE) :
             case (GREAT_CIRCLE) :
               temp_src_point =
                 (fabs(dotproduct(prev_src_point->vec_coords,
-                                 tgt_edge_norm_vec + 3 * i)) <
+                                 tgt_points[i].edge_norm_vec)) <
                  fabs(dotproduct(curr_src_point->vec_coords,
-                                 tgt_edge_norm_vec + 3 * i)))?
+                                 tgt_points[i].edge_norm_vec)))?
                 prev_src_point:curr_src_point;
               break;
             case (LAT_CIRCLE) :
               temp_src_point =
                 (fabs(1.0 - fabs(prev_src_point->vec_coords[2] +
-                                 tgt_edge_norm_vec[3 * i + 2])) < 
+                                 tgt_points[i].edge_norm_vec[2])) <
                  fabs(1.0 - fabs(curr_src_point->vec_coords[2] +
-                                 tgt_edge_norm_vec[3 * i + 2])))?
+                                 tgt_points[i].edge_norm_vec[2])))?
                 prev_src_point:curr_src_point;
               break;
             default:
               abort_message("invalid edge type\n", __FILE__, __LINE__);
+              return;
           };
 
           p[0] = temp_src_point->vec_coords[0];
@@ -429,7 +583,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
         if ((intersect & ((1 << 0) | (1 << 1))) == ((1 << 0) | (1 << 1))) {
 
           if (!((prev_src_point->edge_type == LAT_CIRCLE) ^
-                (prev_tgt_point->edge_type == LAT_CIRCLE))) {
+                (tgt_points[i].point->edge_type == LAT_CIRCLE))) {
 
             abort_message("ERROR: ...this should not have happened...\n",
                           __FILE__, __LINE__);
@@ -450,25 +604,26 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
 
             int prev_is_closer;
 
-            switch (prev_tgt_point->edge_type) {
+            switch (tgt_points[i].point->edge_type) {
 
               case (LON_CIRCLE) :
               case (GREAT_CIRCLE) :
                 prev_is_closer =
                   fabs(dotproduct(prev_src_point->vec_coords,
-                                  tgt_edge_norm_vec + 3 * i)) <
+                                  tgt_points[i].edge_norm_vec)) <
                   fabs(dotproduct(curr_src_point->vec_coords,
-                                  tgt_edge_norm_vec + 3 * i));
+                                  tgt_points[i].edge_norm_vec));
                 break;
               case (LAT_CIRCLE) :
                 prev_is_closer =
                   fabs(1.0 - fabs(prev_src_point->vec_coords[2] +
-                                  tgt_edge_norm_vec[3 * i + 2])) < 
+                                  tgt_points[i].edge_norm_vec[2])) <
                   fabs(1.0 - fabs(curr_src_point->vec_coords[2] +
-                                  tgt_edge_norm_vec[3 * i + 2]));
+                                  tgt_points[i].edge_norm_vec[2]));
                 break;
               default:
                 abort_message("invalid edge type\n", __FILE__, __LINE__);
+                return;
             };
 
             if (prev_is_closer)
@@ -497,7 +652,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
             intersect_point = prev_src_point;
 
           if (prev_is_inside)
-            intersect_point->edge_type = prev_tgt_point->edge_type;
+            intersect_point->edge_type = tgt_points[i].point->edge_type;
           else
             intersect_point->edge_type = prev_src_point->edge_type;
 
@@ -524,7 +679,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
       // if the one edge is a circle of latitude while the other is not
       // and both corners are not directly on the edge
       if (((prev_src_point->edge_type == LAT_CIRCLE) ^
-           (prev_tgt_point->edge_type == LAT_CIRCLE)) && 
+           (tgt_points[i].point->edge_type == LAT_CIRCLE)) &&
           ((prev_is_inside + curr_is_inside == 0) ||
            (prev_is_inside + curr_is_inside == 2) ||
            (prev_is_inside + curr_is_inside == 3))) {
@@ -578,7 +733,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
               prev_src_point->edge_type;
             intersect_points[(prev_is_inside == 0) ||
                              (curr_is_inside == 0)]->edge_type =
-              prev_tgt_point->edge_type;
+              tgt_points[i].point->edge_type;
 
             if (prev_is_inside == 2 || curr_is_inside == 2) {
 
@@ -587,7 +742,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
               {
                 double edge_middle[3];
 
-                get_edge_middle_point(p, q, prev_tgt_point->edge_type,
+                get_edge_middle_point(p, q, tgt_points[i].point->edge_type,
                                       edge_middle);
 
                 double norm_vec[3];
@@ -647,7 +802,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
       // if the one edge is a circle of latitude while the other is not
       // and both corners are directly on the edge
       } else if (((prev_src_point->edge_type == LAT_CIRCLE) ^
-                  (prev_tgt_point->edge_type == LAT_CIRCLE)) && 
+                  (tgt_points[i].point->edge_type == LAT_CIRCLE)) &&
                  (prev_is_inside == 2) && (curr_is_inside == 2)) {
 
         double cross_src_z, cross_tgt_z;
@@ -656,10 +811,10 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
                       (long double)curr_src_point->vec_coords[1] -
                       (long double)prev_src_point->vec_coords[1] *
                       (long double)curr_src_point->vec_coords[0];
-        cross_tgt_z = (long double)prev_tgt_point->vec_coords[0] *
-                      (long double)curr_tgt_point->vec_coords[1] -
-                      (long double)prev_tgt_point->vec_coords[1] *
-                      (long double)curr_tgt_point->vec_coords[0];
+        cross_tgt_z = (long double)tgt_points[i].point->vec_coords[0] *
+                      (long double)tgt_points[i].point->next->vec_coords[1] -
+                      (long double)tgt_points[i].point->vec_coords[1] *
+                      (long double)tgt_points[i].point->next->vec_coords[0];
 
         int same_ordering = source_ordering == target_ordering;
         int same_direction = (cross_src_z > 0) == (cross_tgt_z > 0);
@@ -684,7 +839,7 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
       // if the previous points was on the target edge and the current
       // one is outside
       if (prev_is_inside == 2 && curr_is_inside == 0)
-        prev_src_point->edge_type = prev_tgt_point->edge_type;
+        prev_src_point->edge_type = tgt_points[i].point->edge_type;
 
       if (!prev_is_inside)
         prev_src_point->to_be_removed = 1;
@@ -701,9 +856,6 @@ void point_list_clipping(struct point_list * source_list, int source_ordering,
 
     // if there are no more corners in the source cell
     if (source_list->first == NULL) break;
-
-    prev_tgt_point = curr_tgt_point;
-    curr_tgt_point = curr_tgt_point->next;
   }
 }
 
@@ -715,22 +867,22 @@ static void copy_point_list(struct point_list in, struct point_list * out) {
 
   if (curr == NULL) return;
 
-  struct point_list_element * newelem = get_free_point_list_element(out);
-  out->first = newelem;
-  *newelem = *curr;
+  struct point_list_element * new = get_free_point_list_element(out);
+  out->first = new;
+  *new = *curr;
   curr = curr->next;
 
   do {
 
-    newelem->next = get_free_point_list_element(out);
-    newelem = newelem->next;    
-    *newelem = *curr;
+    new->next = get_free_point_list_element(out);
+    new = new->next;
+    *new = *curr;
     curr = curr->next;
-    
+
   } while (curr != in.first);
 
-  newelem->next = out->first;
-  out->last = newelem;
+  new->next = out->first;
+  out->last = new;
 }
 
 void cell_clipping(unsigned N,
@@ -748,8 +900,6 @@ void cell_clipping(unsigned N,
 
   double * norm_vec; /* norm vector for temporary target edge plane */
 
-  nct = target_cell.num_corners;
-
   enum cell_type tgt_cell_type = get_cell_type(target_cell);
 
   if (tgt_cell_type == MIXED_CELL)
@@ -775,6 +925,12 @@ void cell_clipping(unsigned N,
   struct point_list_element * prev_tgt_point = target_list.first;
   struct point_list_element * curr_tgt_point = target_list.first->next;
 
+  nct = 0;
+  do {
+    nct++;
+    prev_tgt_point = prev_tgt_point->next;
+  } while (prev_tgt_point != target_list.first);
+
   norm_vec = malloc(3 * nct * sizeof(*norm_vec));
 
   // compute norm vectors for all edges
@@ -816,23 +972,33 @@ void cell_clipping(unsigned N,
                     "of great circles and circles of latitude)\n", __FILE__,
                     __LINE__);
 
-    ncs = source_cell[n].num_corners;
-
-    if (ncs < 2)
+    if (source_cell[n].num_corners < 2)
       continue;
 
     // generate point list for current source list
     generate_point_list(&source_list, source_cell[n]);
 
+    {
+      struct point_list_element * src_point = source_list.first;
+
+      ncs = 0;
+      do {
+        ncs++;
+        src_point = src_point->next;
+      } while (src_point != source_list.first);
+    }
+
     // compute source direction
     source_ordering = get_cell_points_ordering(&source_list);
 
     struct point_list * overlap;
 
-    // in this case there can be some problems if the great circle cell includes
-    // a pole, but this only occurs if the lon-lat cell is the target cell
-    if ((((tgt_cell_type == LON_LAT_CELL) || (tgt_cell_type == LAT_CELL)) &&
-         src_cell_type == GREAT_CIRCLE_CELL) ||
+    // in this case the source an target cell are both LAT_CELL's than the
+    // bigger one has to be the target cell
+    // a similar problem occurs when the target cell is a LAT_CELL and the
+    // source is a GREAT_CIRCLE_CELL which overlaps with the pole that is also
+    // include in the target cell
+    if (((tgt_cell_type == LAT_CELL) && (src_cell_type == GREAT_CIRCLE_CELL)) ||
         ((tgt_cell_type == LAT_CELL) && (src_cell_type == LAT_CELL) &&
          (fabs(target_cell.coordinates_y[0]) >
           fabs(source_cell[n].coordinates_y[0])))) {
@@ -912,10 +1078,10 @@ void correct_weights ( unsigned nSourceCells, double * weight ) {
       weight_diff -= weight[n];
 
 #ifdef VERBOSE
-    printf ("weight sum is %.15f \n", weight_sum); 
-    printf ("weights are  "); 
+    printf ("weight sum is %.15f \n", weight_sum);
+    printf ("weights are  ");
     for (unsigned i = 0; i < nSourceCells; ++i)
-      printf (" %.15f", weight[i]); 
+      printf (" %.15f", weight[i]);
     printf("\n");
 #endif
 
@@ -1172,7 +1338,7 @@ static int is_empty_gc_cell(struct point_list * list, unsigned num_edges) {
     return 1;
 
   struct point_list_element * curr = list->first;
-    
+
   for (unsigned i = 0; i < num_edges; ++i) {
 
     if (curr->edge_type == LAT_CIRCLE) return 0;
diff --git a/src/clipping/clipping.h b/src/clipping/clipping.h
index 78f8b4b..587813b 100644
--- a/src/clipping/clipping.h
+++ b/src/clipping/clipping.h
@@ -73,14 +73,17 @@ void cell_clipping ( unsigned N,
 
 /**
   * \brief calculates partial areas for all overlapping parts of the source
-  *        cells, this is required for conservative remapping
+  *        cells with triangular target cells. This is required for
+  *        conservative remapping
   *
   * Some of the underlying concepts can be found in
   *
   * See e.g. Joseph O'Rourke, Computational Geometry in C, 2nd Ed., 1998
   *          Sec. 7.6 Intersections of Convex Polygons, page 253.
   *
-  * The routine takes (a list of) source cells and a target cell. It determines the
+  * The routine takes (a list of) source cells and a convex target cell. As
+  * a triangle is always convex we recommend to use this routine only for
+  * triangular target cells. It determines the
   * clipping points of the intersection between a source and the target cells using
   * cell_clipping internally. In a second step areas are calculated for each
   * intersection described in the overlap cells. If a target cell is fully
@@ -102,6 +105,40 @@ void compute_overlap_areas(unsigned N,
                            double * partial_areas);
 
 /**
+  * \brief calculates partial areas for all overlapping parts of the source
+  *        cells with arbitrary target cells, this is required for conservative
+  *        remapping.
+  *
+  * Some of the underlying concepts can be found in
+  *
+  * See e.g. Joseph O'Rourke, Computational Geometry in C, 2nd Ed., 1998
+  *          Sec. 7.6 Intersections of Convex Polygons, page 253.
+  *
+  * The routine takes (a list of) source cells and a target cell. It determines the
+  * clipping points of the intersection between a source and the target cells using
+  * cell_clipping internally. In a second step areas are calculated for each
+  * intersection described in the overlap cells. If a target cell is fully
+  * covered by N source cells the N partial areas should add up to the area of
+  * the target cell.
+  *
+  * @param[in]  N             number of source cells
+  * @param[in]  source_cell   list of source cells
+  * @param[in]  target_cell   target cell
+  * @param[in]  target_node_x x-coordinate of target cell node or center point
+  * @param[in]  target_node_y y-coordinate of target cell node or center point
+  * @param[out] partial_areas list of N partial weights, one weight for each
+  *                           source-target intersection
+  *
+  * \remark source and target cell have to be convex
+  *
+ **/
+void compute_concave_overlap_areas (unsigned N,
+                                    struct grid_cell * source_cell,
+                                    struct grid_cell target_cell,
+                                    double * target_node_x,
+                                    double * target_node_y,
+                                    double * partial_areas);
+/**
   * \brief correct interpolation weights
   *
   * Returns weights with a sum close to 1.0
diff --git a/src/clipping/geometry.h b/src/clipping/geometry.h
index 645f650..f0d51e4 100644
--- a/src/clipping/geometry.h
+++ b/src/clipping/geometry.h
@@ -381,8 +381,10 @@ int gcxlatc (struct edge edge_a, struct edge edge_b,
  * compute the intersection points of a great circles
  * and a circle of latitude \n
  * based on http://geospatialmethods.org/spheres/GCIntersect.html
- * @param[in] edge_a edge defining a great circle
- * @param[in] edge_b edge defining a circle of latitude
+ * @param[in] a first point of edge on a great circle
+ * @param[in] b second point of edge on a great circle
+ * @param[in] c first point of edge on a circle of latitude
+ * @param[in] d second point of edge on a circle of latitude
  * @param[out] p intersection point
  * @param[out] q intersection point
  * @return  0 if the intersection points are neither on edge a or b \n
@@ -639,19 +641,70 @@ static inline void crossproduct_d (double a[], double b[], double cross[]) {
  * @return great circle distance in rad between both points
  */
 static inline double get_vector_angle(double a[3], double b[3]) {
+
+   double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+
+   // the acos most accurate in the range [-0.5;0.5]
+   if (fabs(dot_product) <= 0.5) // the range in which the acos is most accurate
+
+      return acos(dot_product);
+
+   else {
+
+      double cross_ab[3];
+
+      crossproduct_ld(a, b, cross_ab);
+
+      double asin_tmp = asin(sqrt(cross_ab[0]*cross_ab[0]+
+                                  cross_ab[1]*cross_ab[1]+
+                                  cross_ab[2]*cross_ab[2]));
+
+      if (dot_product < 0.0) // if the angle is bigger than (PI / 2)
+         return MIN(M_PI - asin_tmp, M_PI);
+      else
+         return MAX(asin_tmp,0.0);
+   }
+
+   /*
+   // this solution is simpler, but has a much worse performance
    double cross[3], dot, cross_abs;
 
    crossproduct_ld(a, b, cross);
    dot = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
    cross_abs = sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
 
-   //   return fabs(atan2(cross_abs, dot));
-   double asin_tmp = asin(cross_abs);
+   return fabs(atan2(cross_abs, dot));
+   */
+}
+
+/**
+ * determines whether two given points are (nearly) identically
+ * @param[in] a point coordinates of point a
+ * @param[in] b point coordinates of point b
+ * @return true if both points are (nearly) identically
+ */
+static inline int points_are_identically(double * a, double * b) {
+
+   double dot_product = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+
+   // if the angle is bigger than ~0.81 degree
+   // (in this range the acos is still rather accurate)
+   if (dot_product < 0.9999) // (acos(0.9999) = ~0.81 degree)
+
+      return 0;
+
+   else { // both points are close to each other -> use cross product for higher
+          // accuracy
+
+      double cross_ab[3];
+
+      crossproduct_ld(a, b, cross_ab);
 
-   if (dot < 0.0) // if the angle is bigger than (PI / 2)
-     return M_PI - asin_tmp;
-   else
-     return asin_tmp;
+      // for very small angles: asin(alpha) = ~alpha   (alpha in rad)
+      return sqrt(cross_ab[0]*cross_ab[0] +
+                  cross_ab[1]*cross_ab[1] +
+                  cross_ab[2]*cross_ab[2]) < angle_tol;
+   }
 }
 
 /**
diff --git a/src/clipping/grid.h b/src/clipping/grid.h
index 779c88f..cd0b815 100644
--- a/src/clipping/grid.h
+++ b/src/clipping/grid.h
@@ -109,7 +109,7 @@ struct grid_vtable {
    void (*pack_grid)(struct grid *, double **, unsigned, unsigned *, unsigned *,
                      unsigned **, unsigned, unsigned *, unsigned *);
    struct grid_search * (*get_grid_search)(struct grid * grid);
-   void (*xdelete)(struct grid *);
+   void (*delete)(struct grid *);
 };
 
 struct grid {
@@ -140,6 +140,7 @@ void get_grid_cell (struct grid * grid, unsigned cell_index,
  * @param[in] grid
  * @param[in] cell_index local cell index of the requested cell
  * @param[out] cell requested cell (grid_cell object has be initialised once before)
+ * @param[out] bnd_circle bounding circle of input cell
  * @see init_grid_cell
  */
 void get_grid_cell2 (struct grid * grid, unsigned cell_index, 
diff --git a/src/clipping/grid_cell.c b/src/clipping/grid_cell.c
index 3d8c36f..c12aabf 100644
--- a/src/clipping/grid_cell.c
+++ b/src/clipping/grid_cell.c
@@ -127,7 +127,8 @@ void unpack_grid_cell(struct grid_cell * cell, double * dble_buf,
 
    unsigned num_corners;
 
-   num_corners = uint_buf[0];
+   num_corners = *uint_buf;
+   uint_buf++;
 
    *dble_buf_data_size = 2 * num_corners;
    *uint_buf_data_size = num_corners + 1;
@@ -151,9 +152,8 @@ void unpack_grid_cell(struct grid_cell * cell, double * dble_buf,
    memcpy(cell->coordinates_x, dble_buf, num_corners * sizeof(double));
    memcpy(cell->coordinates_y, dble_buf+num_corners, num_corners * sizeof(double));
 
-   unsigned i;
-   for (i = 1; i <= num_corners; ++i) {
-     cell->edge_type[i-1] = (enum edge_type)uint_buf[i];
+   for (unsigned i = 0; i < num_corners; ++i) {
+     cell->edge_type[i] = (enum edge_type)uint_buf[i];
      LLtoXYZ(cell->coordinates_x[i], cell->coordinates_y[i],
              cell->coordinates_xyz + 3*i);
    }
diff --git a/src/clipping/intersection.c b/src/clipping/intersection.c
index 84f3d9e..eea2273 100644
--- a/src/clipping/intersection.c
+++ b/src/clipping/intersection.c
@@ -73,21 +73,31 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
 /* determines whether p is between a and b
    (a, b, p have the same latitude)*/
 
+/*  I. a_0 * alpha + b_0 * beta = p_0
+   II. a_1 * alpha + b_1 * beta = p_1
+   
+   if alpha > 0 and beta > 0 -> p is between a and b */
+
    if (fabs(fabs(a[2]) - 1.0) < tol) return 1;
 
-   long double a_0 = a[0], a_1 = a[1];
-   long double b_0 = b[0], b_1 = b[1];
-   long double p_0 = p[0], p_1 = p[1];
+   int flag = fabs(a[0]) > fabs(a[1]);
+   double a_0 = a[flag], a_1 = a[flag^1];
+   double b_0 = b[flag], b_1 = b[flag^1];
+   double p_0 = p[flag], p_1 = p[flag^1];
+
+   double temp = b_0 - (b_1 * a_0) / a_1;
+
+   // if a and b are nearly identical
+   if (fabs(temp) < tol) return (fabs(a_0 - p_0) < tol) &&
+                                (fabs(a_1 - p_1) < tol);
+
+   double beta = (p_0 - (p_1 * a_0) / a_1) / temp;
 
-   if (((a_0*p_0+a_1*p_1) < 0) || ((b_0*p_0+b_1*p_1) < 0))
-    return 0;
+   if (beta < -tol) return 0;
 
-   double cross_ab = fabs(a_0*b_1-a_1*b_0);
-   double cross_ap = fabs(a_0*p_1-a_1*p_0);
-   double cross_bp = fabs(b_0*p_1-b_1*p_0);
+   double alpha = (p_1 - b_1 * beta) / a_1;
 
-   // maybe this should be the cross_** should be scaled by z at some point
-   return (cross_ap < cross_ab + tol) && (cross_bp < cross_ab + tol);
+   return alpha > -tol;
 }
 
 /** \brief compute the intersection points of two great circles
@@ -144,114 +154,127 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
  int gcxgc_vec (double a[3], double b[3], double c[3], double d[3],
                 double p[3], double q[3]) {
 
-   double e_ab[3], e_cd[3], n;
-   double cross_ab[3], cross_cd[3];
-   int ab_is_point, cd_is_point;
-
-   // compute unit vector of ab plane
-   crossproduct_ld(a, b, cross_ab);
-   n = sqrt(cross_ab[0] * cross_ab[0] +
-            cross_ab[1] * cross_ab[1] +
-            cross_ab[2] * cross_ab[2]);
-
-   ab_is_point = n < tol;
+   double length_cross_ab, length_cross_cd, length_cross_abxcd;
+   long double cross_ab[3], cross_cd[3], cross_abxcd[3];
 
-   if (!ab_is_point) {
-
-      n = 1.0 / n;
-      e_ab[0] = cross_ab[0] * n;
-      e_ab[1] = cross_ab[1] * n;
-      e_ab[2] = cross_ab[2] * n;
-   }
-
-   // compute unit vector of cd plane
-   crossproduct_ld(c, d, cross_cd);
-   n = sqrt(cross_cd[0] * cross_cd[0] +
-            cross_cd[1] * cross_cd[1] +
-            cross_cd[2] * cross_cd[2]);
-   cd_is_point = n < tol;
-
-   if (!cd_is_point) {
-      n = 1.0 / n;
-      e_cd[0] = cross_cd[0] * n;
-      e_cd[1] = cross_cd[1] * n;
-      e_cd[2] = cross_cd[2] * n;
+   // p' = (a X b) X (c X d)
+   // p  = p' / length(p')
+   {
+      long double a_[3] = {a[0], a[1], a[2]};
+      long double b_[3] = {b[0], b[1], b[2]};
+      long double c_[3] = {c[0], c[1], c[2]};
+      long double d_[3] = {d[0], d[1], d[2]};
+
+      cross_ab[0] = a_[1] * b_[2] - a_[2] * b_[1];
+      cross_ab[1] = a_[2] * b_[0] - a_[0] * b_[2];
+      cross_ab[2] = a_[0] * b_[1] - a_[1] * b_[0];
+      cross_cd[0] = c_[1] * d_[2] - c_[2] * d_[1];
+      cross_cd[1] = c_[2] * d_[0] - c_[0] * d_[2];
+      cross_cd[2] = c_[0] * d_[1] - c_[1] * d_[0];
+      cross_abxcd[0] = cross_ab[1] * cross_cd[2] - cross_ab[2] * cross_cd[1];
+      cross_abxcd[1] = cross_ab[2] * cross_cd[0] - cross_ab[0] * cross_cd[2];
+      cross_abxcd[2] = cross_ab[0] * cross_cd[1] - cross_ab[1] * cross_cd[0];
    }
 
-   if (ab_is_point && cd_is_point) {
+   length_cross_ab = sqrtl(cross_ab[0] * cross_ab[0] +
+                           cross_ab[1] * cross_ab[1] +
+                           cross_ab[2] * cross_ab[2]);
+   length_cross_cd = sqrtl(cross_cd[0] * cross_cd[0] +
+                           cross_cd[1] * cross_cd[1] +
+                           cross_cd[2] * cross_cd[2]);
+   length_cross_abxcd = sqrtl(cross_abxcd[0] * cross_abxcd[0] +
+                              cross_abxcd[1] * cross_abxcd[1] +
+                              cross_abxcd[2] * cross_abxcd[2]);
 
-      double angle = get_vector_angle(a, c);
+   if (length_cross_ab < tol) {
 
       if (p != NULL) p[0] = a[0], p[1] = a[1], p[2] = a[2];
       if (q != NULL) q[0] = -a[0], q[1] = -a[1], q[2] = -a[2];
 
-      // if points are identically
-      if (angle < tol)
-         return 1 + 4;
-      // if the points are directly opposit of each other
-      else if (fabs(angle - M_PI) < tol)
-         return 1 + 8;
-      else
-         return -1;
+      if (length_cross_cd < tol) {
 
-   } else if (ab_is_point) {
+         double cross_ac[3], angle_ac;
 
-      if (p != NULL) p[0] = a[0], p[1] = a[1], p[2] = a[2];
-      if (q != NULL) q[0] = -a[0], q[1] = -a[1], q[2] = -a[2];
+         // we only care about accuracy of the angle in case the angle is very
+         // small or nearly 180°, therefore we use directly the cross product
+         // instead of the routine get_vector_angle
+         crossproduct_ld(a, c, cross_ac);
+         angle_ac = asin(cross_ac[0] * cross_ac[0] +
+                         cross_ac[1] * cross_ac[1] +
+                         cross_ac[2] * cross_ac[2]);
 
-      // if ab is on the plane of cd
-      if (fabs(get_vector_angle(a, e_cd) - M_PI_2) < tol) {
+         // if points are identically or have an angle of 180°
+         if (fabs(angle_ac) < tol) {
 
-         int result = 1;
-         double angle_cd = -1;
-         double dot_cd = c[0]*d[0] + c[1]*d[1] + c[2]*d[2];
-	 double an[3] = {-a[0], -a[1], -a[2]};
+            double dot_ac = a[0]*c[0] + a[1]*c[1] + a[2]*c[2];
 
-         if (vector_is_between(c, d, a, &angle_cd, dot_cd))
-            result |= 1 << 2;
-         if (vector_is_between(c, d, an, &angle_cd,
-                               dot_cd)) result |= 1 << 3;
+            return (1 + ((dot_ac > 0)?4:8));
 
-         return result;
-      }
+         } else
 
-      return -1;
+            return -1;
 
-   } else if (cd_is_point) {
+      } else {
 
-      if (p != NULL) p[0] = c[0], p[1] = c[1], p[2] = c[2];
-      if (q != NULL) q[0] = -c[0], q[1] = -c[1], q[2] = -c[2];
+         // dot product is most accurate for angles around half PI
+         // (for angles very close to half PI: alpha = fabs(acos(alpha))
+         double angle = fabs(cross_cd[0] * a[0] +
+                             cross_cd[1] * a[1] +
+                             cross_cd[2] * a[2]) / length_cross_cd ;
 
-      // if cd is on the plane of ab
-      if (fabs(get_vector_angle(c, e_ab) - M_PI_2) < tol) {
+         // if ab is on the plane of cd
+         if (fabs(angle) < tol) {
 
-         int result = 4;
+            int result = 1;
+            double angle_cd = -1;
+            double dot_cd = c[0]*d[0] + c[1]*d[1] + c[2]*d[2];
 
-         double angle_ab = -1;
-         double dot_ab = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
-	 double cn[3] = {-c[0], -c[1], -c[2]};
+            if (vector_is_between(c, d, a, &angle_cd, dot_cd))
+               result |= 1 << 2;
+            if (vector_is_between(c, d, (double[]){-a[0], -a[1], -a[2]}, &angle_cd,
+                                  dot_cd)) result |= 1 << 3;
 
-         if (vector_is_between(a, b, c, &angle_ab, dot_ab))
-            result |= 1 << 0;
-         if (vector_is_between(a, b, cn, &angle_ab,
-                               dot_ab)) result |= 1 << 1;
+            return result;
+         }
 
-         return result;
+         return -1;
       }
 
-      return -1;
-   }
+   } else {
+
+      if (length_cross_cd < tol) {
+
+         if (p != NULL) p[0] = c[0], p[1] = c[1], p[2] = c[2];
+         if (q != NULL) q[0] = -c[0], q[1] = -c[1], q[2] = -c[2];
+
+         // dot product is most accurate for angles around half PI
+         // (for angles very close to half PI: alpha = fabs(acos(alpha))
+         double angle = fabs(cross_ab[0] * c[0] +
+                             cross_ab[1] * c[1] +
+                             cross_ab[2] * c[2]) / length_cross_ab;
+
+         // if cd is on the plane of ab
+         if (fabs(angle) < tol) {
+
+            int result = 4;
 
-   double temp_cross[3];
+            double angle_ab = -1;
+            double dot_ab = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
 
-   // compute unit vector of ab plane
-   crossproduct_ld(e_ab, e_cd, temp_cross);
-   n = sqrt(temp_cross[0] * temp_cross[0] +
-            temp_cross[1] * temp_cross[1] +
-            temp_cross[2] * temp_cross[2]);
+            if (vector_is_between(a, b, c, &angle_ab, dot_ab))
+               result |= 1 << 0;
+            if (vector_is_between(a, b, (double[]){-c[0], -c[1], -c[2]}, &angle_ab,
+                                  dot_ab)) result |= 1 << 1;
+
+            return result;
+         }
+
+         return -1;
+      }
+   }
 
    // if both great circles are nearly identically
-   if (n < tol) {
+   if (length_cross_abxcd / (length_cross_ab * length_cross_cd) < tol) {
 
       int ret_value = 1 << 4;
 
@@ -314,13 +337,13 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
       return ret_value;
    }
 
-    n = 1.0 / n;
+    long double scale = 1.0l / length_cross_abxcd;
     // determine p and q
     double p_[3], q_[3];
 
-    p_[0]= temp_cross[0] * n;
-    p_[1]= temp_cross[1] * n;
-    p_[2]= temp_cross[2] * n;
+    p_[0]= cross_abxcd[0] * scale;
+    p_[1]= cross_abxcd[1] * scale;
+    p_[2]= cross_abxcd[2] * scale;
 
     q_[0]=-p_[0];
     q_[1]=-p_[1];
@@ -355,76 +378,101 @@ static int vector_is_between_lat (double a[], double b[], double p[]) {
 
 int gcxgc_vec_ (double a[3], double b[3], double c[3], double d[3]) {
 
-   double e_ab[3] = {0, 0, 0}, e_cd[3] = {0, 0, 0}, n;
-   double cross_ab[3], cross_cd[3];
-   int ab_is_point, cd_is_point;
+   double length_cross_ab, length_cross_cd, length_cross_abxcd;
+   long double cross_ab[3], cross_cd[3], cross_abxcd[3];
 
-   // compute unit vector of ab plane
-   crossproduct_ld(a, b, cross_ab);
-   n = sqrt(cross_ab[0] * cross_ab[0] +
-            cross_ab[1] * cross_ab[1] +
-            cross_ab[2] * cross_ab[2]);
+   // p' = (a X b) X (c X d)
+   // p  = p' / length(p')
+   {
+      long double a_[3] = {a[0], a[1], a[2]};
+      long double b_[3] = {b[0], b[1], b[2]};
+      long double c_[3] = {c[0], c[1], c[2]};
+      long double d_[3] = {d[0], d[1], d[2]};
+
+      cross_ab[0] = a_[1] * b_[2] - a_[2] * b_[1];
+      cross_ab[1] = a_[2] * b_[0] - a_[0] * b_[2];
+      cross_ab[2] = a_[0] * b_[1] - a_[1] * b_[0];
+      cross_cd[0] = c_[1] * d_[2] - c_[2] * d_[1];
+      cross_cd[1] = c_[2] * d_[0] - c_[0] * d_[2];
+      cross_cd[2] = c_[0] * d_[1] - c_[1] * d_[0];
+      cross_abxcd[0] = cross_ab[1] * cross_cd[2] - cross_ab[2] * cross_cd[1];
+      cross_abxcd[1] = cross_ab[2] * cross_cd[0] - cross_ab[0] * cross_cd[2];
+      cross_abxcd[2] = cross_ab[0] * cross_cd[1] - cross_ab[1] * cross_cd[0];
+   }
 
-   ab_is_point = n < tol;
+   length_cross_ab = sqrtl(cross_ab[0] * cross_ab[0] +
+                           cross_ab[1] * cross_ab[1] +
+                           cross_ab[2] * cross_ab[2]);
+   length_cross_cd = sqrtl(cross_cd[0] * cross_cd[0] +
+                           cross_cd[1] * cross_cd[1] +
+                           cross_cd[2] * cross_cd[2]);
+   length_cross_abxcd = sqrtl(cross_abxcd[0] * cross_abxcd[0] +
+                              cross_abxcd[1] * cross_abxcd[1] +
+                              cross_abxcd[2] * cross_abxcd[2]);
 
-   if (!ab_is_point) {
+   if (length_cross_ab < tol) {
 
-      n = 1.0 / n;
-      e_ab[0] = cross_ab[0] * n;
-      e_ab[1] = cross_ab[1] * n;
-      e_ab[2] = cross_ab[2] * n;
-   }
+      if (length_cross_cd < tol) {
 
-   // compute unit vector of cd plane
-   crossproduct_ld(c, d, cross_cd);
-   n = sqrt(cross_cd[0] * cross_cd[0] +
-            cross_cd[1] * cross_cd[1] +
-            cross_cd[2] * cross_cd[2]);
-   cd_is_point = n < tol;
-
-   if (!cd_is_point) {
-      n = 1.0 / n;
-      e_cd[0] = cross_cd[0] * n;
-      e_cd[1] = cross_cd[1] * n;
-      e_cd[2] = cross_cd[2] * n;
-   }
+         double dot_ac = a[0]*c[0] + a[1]*c[1] + a[2]*c[2];
 
-   if (ab_is_point && cd_is_point) {
+         // if the angle between a and c is bigger than ~45°
+         if (dot_ac < 0.75) return 0;
 
-      return get_vector_angle(a, c) < tol;
+         double cross_ac[3], angle_ac;
 
-   } else if (ab_is_point) {
+         // we only care about accuracy of the angle in case the angle is very
+         // small or nearly 180°, therefore we use directly the cross product
+         // instead of the routine get_vector_angle
+         crossproduct_ld(a, c, cross_ac);
+         angle_ac = asin(cross_ac[0] * cross_ac[0] +
+                         cross_ac[1] * cross_ac[1] +
+                         cross_ac[2] * cross_ac[2]);
 
-      // if ab is not on the plane of cd
-      if (fabs(get_vector_angle(a, e_cd) - M_PI_2) > tol)
-         return 0;
+         // if points are identically or have an angle of 180°
+         return fabs(angle_ac) < tol;
 
-      double angle_cd = -1;
-      double dot_cd = c[0]*d[0] + c[1]*d[1] + c[2]*d[2];
+      } else {
 
-      return vector_is_between(c, d, a, &angle_cd, dot_cd);
+         // dot product is most accurate for angles around half PI
+         // (for angles very close to half PI: alpha = fabs(acos(alpha))
+         double angle = fabs(cross_cd[0] * a[0] +
+                             cross_cd[1] * a[1] +
+                             cross_cd[2] * a[2]) / length_cross_cd ;
 
-   } else if (cd_is_point) {
+         // if ab is not on the plane of cd
+         if (fabs(angle) >= tol)
+            return 0;
 
-      // if cd is not on the plane of ab
-      if (fabs(get_vector_angle(c, e_ab) - M_PI_2) > tol) return 0;
+         double angle_cd = -1;
+         double dot_cd = c[0]*d[0] + c[1]*d[1] + c[2]*d[2];
 
-      double angle_ab = -1;
-      double dot_ab = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+         return vector_is_between(c, d, a, &angle_cd, dot_cd);
+      }
 
-      return vector_is_between(a, b, c, &angle_ab, dot_ab);
-   }
+   } else {
 
-   double temp_cross[3];
+      if (length_cross_cd < tol) {
 
-   // compute unit vector of ab plane
-   crossproduct_ld(e_ab, e_cd, temp_cross);
-   n = sqrt(temp_cross[0] * temp_cross[0] +
-            temp_cross[1] * temp_cross[1] +
-            temp_cross[2] * temp_cross[2]);
+         // dot product is most accurate for angles around half PI
+         // (for angles very close to half PI: alpha = fabs(acos(alpha))
+         double angle = fabs(cross_ab[0] * c[0] +
+                             cross_ab[1] * c[1] +
+                             cross_ab[2] * c[2]) / length_cross_ab;
+
+         // if cd is not on the plane of ab
+         if (fabs(angle) >= tol)
+            return 0;
+
+         double angle_ab = -1;
+         double dot_ab = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+
+         return vector_is_between(a, b, c, &angle_ab, dot_ab);
+      }
+   }
 
    // if both great circles are nearly identically
-   if (n < tol) {
+   if (length_cross_abxcd / (length_cross_ab * length_cross_cd) < tol) {
 
       double angle_ab = -1;
       double angle_cd = -1;
@@ -437,11 +485,13 @@ int gcxgc_vec_ (double a[3], double b[3], double c[3], double d[3]) {
              vector_is_between(a, b, d, &angle_ab, dot_ab);
    }
 
-    n = 1.0 / n;
+    long double scale = 1.0l / length_cross_abxcd;
+    // determine p and q
     double p_[3];
-    p_[0] = temp_cross[0] * n;
-    p_[1] = temp_cross[1] * n;
-    p_[2] = temp_cross[2] * n;
+
+    p_[0]= cross_abxcd[0] * scale;
+    p_[1]= cross_abxcd[1] * scale;
+    p_[2]= cross_abxcd[2] * scale;
 
     double angle_ab = -1;
     double angle_cd = -1;
@@ -459,6 +509,7 @@ int gcxgc_vec_ (double a[3], double b[3], double c[3], double d[3]) {
 
     return vector_is_between(a, b, q_, &angle_ab, dot_ab) &&
            vector_is_between(c, d, q_, &angle_cd, dot_cd);
+
 }
 
 /** \brief compute the intersection point two circles of latitude
diff --git a/src/clipping/utils.h b/src/clipping/utils.h
index e945267..bd6c56f 100644
--- a/src/clipping/utils.h
+++ b/src/clipping/utils.h
@@ -41,10 +41,6 @@
 
 #include <stdlib.h>
 
-#ifdef __WITHOUT_ISO_C_BINDING
-#include "cfortran.h"
-#endif
-
 /**
  * gives a unique index for a given pointer
  * @param[in] pointer
@@ -75,10 +71,6 @@ void free_pointer_unique_lookup();
  */
 void abort_message ( char * text, char * file, int line );
 
-#ifdef __WITHOUT_ISO_C_BINDING
-     FCALLSCSUB3 ( yac_abort_message, YAC_ABORT_MESSAGE, yac_abort_message, STRING, STRING, PINT )
-#endif
-
 /** \example test_quicksort.c
  * This contains an example of how to use quicksort_index.
  */
@@ -108,6 +100,62 @@ void yac_mergesort(void* base, size_t num, size_t size,
 
 unsigned int hash(const char *str);
 
+/**
+ * remove duplicated entries from a list of integers
+ * @param[in,out] array array containing a sorted (ascending) list of integers
+ * @param[in,out] n     number of entries in array
+ */
+static inline void yac_remove_duplicates_int(int * array, unsigned * n) {
+
+   unsigned const N = *n;
+   unsigned pos = 0;
+
+   if (N == 0) return;
+
+   int prev = array[0];
+
+   for (unsigned i = 1; i < N; ++i) {
+
+      if (array[i] == prev) continue;
+
+      prev = array[i];
+      ++pos;
+
+      if (pos != i)
+         array[pos] = array[i];
+   }
+
+   *n = pos + 1;
+}
+
+/**
+ * remove duplicated entries from a list of integers
+ * @param[in,out] array array containing a sorted (ascending) list of integers
+ * @param[in,out] n     number of entries in array
+ */
+static inline void yac_remove_duplicates_uint(unsigned * array, unsigned * n) {
+
+   unsigned const N = *n;
+   unsigned pos = 0;
+
+   if (N == 0) return;
+
+   unsigned prev = array[0];
+
+   for (unsigned i = 1; i < N; ++i) {
+
+      if (array[i] == prev) continue;
+
+      prev = array[i];
+      ++pos;
+
+      if (pos != i)
+         array[pos] = array[i];
+   }
+
+   *n = pos + 1;
+}
+
 /* =======================================================================
    Macros
    ======================================================================= */
diff --git a/src/config.h.in b/src/config.h.in
index 8783c6f..75feedd 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -142,12 +142,12 @@
 /* Define to 1 if you have the <proj_api.h> header file. */
 #undef HAVE_PROJ_API_H
 
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
 /* Define to 1 if you have the <pthread.h> header file. */
 #undef HAVE_PTHREAD_H
 
+/* Have PTHREAD_PRIO_INHERIT. */
+#undef HAVE_PTHREAD_PRIO_INHERIT
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
diff --git a/src/exception.c b/src/exception.c
index 8e3b092..41a3753 100644
--- a/src/exception.c
+++ b/src/exception.c
@@ -30,7 +30,7 @@ void cdiError(int cdiErrno, const char *fmt, ...)
   if ( _ExitOnError ) exit(EXIT_FAILURE);
 }
 
-
+void pstreamCloseAll(void);
 void cdoAbort(const char *fmt, ...)
 {
   va_list args;
@@ -48,6 +48,7 @@ void cdoAbort(const char *fmt, ...)
 
   va_end(args);
 
+  if ( _ExitOnError ) pstreamCloseAll();
   if ( _ExitOnError ) exit(EXIT_FAILURE);
 }
 
diff --git a/src/functs.h b/src/functs.h
index da92a63..7bf0ea2 100644
--- a/src/functs.h
+++ b/src/functs.h
@@ -55,7 +55,7 @@ enum cmp_flag {
   CMP_GRIDSIZE = 16,
   CMP_HRD      = CMP_CODE | CMP_GRIDSIZE,
   CMP_DIM      =            CMP_GRIDSIZE | CMP_NLEVEL | CMP_GRID,
-  CMP_ALL      = CMP_NAME | CMP_GRIDSIZE | CMP_NLEVEL | CMP_GRID,
+  CMP_ALL      = CMP_NAME | CMP_GRIDSIZE | CMP_NLEVEL | CMP_GRID
 };
 
 void    vlistCompare(int vlistID1, int vlistID2, int flag);
diff --git a/src/gradsdeslib.c b/src/gradsdeslib.c
index ce11181..9f98b18 100644
--- a/src/gradsdeslib.c
+++ b/src/gradsdeslib.c
@@ -10,7 +10,7 @@
 
 static char pout[512];
 FILE *descr;             /* File descriptor pointer */
-int cal365 = 0;
+int cal365 = -1;
 int fullyear = -999;
 
 void dsets_init(dsets_t *pfi)
@@ -31,7 +31,7 @@ void dsets_init(dsets_t *pfi)
   pfi->pa2mb      = 0;
   pfi->calendar   = 0;
   pfi->type       = 1;      /* Assume grid unless told otherwise */
-  pfi->idxflg = 0;       /* Assume binary */
+  pfi->idxflg     = 0;      /* Assume binary */
   pfi->ncflg      = 0;      /* Assume not netcdf */
 
   pfi->undef = -9.99E33; 
@@ -2059,7 +2059,6 @@ int read_gradsdes(char *filename, dsets_t *pfi)
 
 /* set the global calendar and check if we are trying to change with a new file...
    we do this here to set the calandar for templating */
-
   if (/*mfcmn.*/cal365<0) {
     /*mfcmn.*/cal365=pfi->calendar;
   } else {
diff --git a/src/grid.c b/src/grid.c
index db37cc9..5215d18 100644
--- a/src/grid.c
+++ b/src/grid.c
@@ -169,13 +169,19 @@ void grid_gen_corners(long n, const double* restrict vals, double* restrict corn
 {
   long i;
 
-  for ( i = 0; i < n-1; ++i )
+  if ( n == 1 )
     {
-      corners[i+1] = 0.5*(vals[i] + vals[i+1]);
+      corners[0] = vals[0];
+      corners[1] = vals[0];
     }
+  else
+    {
+      for ( i = 0; i < n-1; ++i )
+	corners[i+1] = 0.5*(vals[i] + vals[i+1]);
 
-  corners[0] = 2*vals[0] - corners[1];
-  corners[n] = 2*vals[n-1] - corners[n-1];
+      corners[0] = 2*vals[0] - corners[1];
+      corners[n] = 2*vals[n-1] - corners[n-1];
+    }
 }
 
 
@@ -464,7 +470,6 @@ void lcc_to_geo(int gridID, int gridsize, double *xvals, double *yvals)
   double zlat, zlon;
   double xi, xj;
   int projflag, scanflag;
-  int status;
   long i;
   proj_info_t proj;
 
@@ -692,8 +697,8 @@ void grib_get_reduced_row(long pl,double lon_first,double lon_last,long* npoints
 }
 
 
-int    qu2reg3(double *pfield, int *kpoint, int klat, int klon,
-	       double msval, int *kret, int omisng, int operio, int oveggy);
+int qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
+		   double msval, int *kret, int omisng, int operio, int oveggy);
 
 static
 int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast, 
@@ -758,7 +763,7 @@ int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast,
 
   if ( gridsize != size ) cdoAbort("gridsize1 inconsistent!");
 
-  (void) qu2reg3(work, rowlon, ny, np4, missval, iret, lmiss, lperio, lveggy);
+  (void) qu2reg3_double(work, rowlon, ny, np4, missval, iret, lmiss, lperio, lveggy);
 
   wlen = 0;
   pwork[0] = work;
@@ -825,7 +830,7 @@ void field2regular(int gridID1, int gridID2, double missval, double *array, int
   else
     {
       nx = 2*ny;
-      (void) qu2reg3(array, rowlon, ny, nx, missval, &iret, lmiss, lperio, lveggy);
+      (void) qu2reg3_double(array, rowlon, ny, nx, missval, &iret, lmiss, lperio, lveggy);
     }
 
   if ( gridInqSize(gridID2) != nx*ny ) Error("Gridsize differ!");
@@ -1464,7 +1469,6 @@ int gridCurvilinearToRegular(int gridID1)
 {
   int gridID2 = -1;
   int gridtype, gridsize;
-  long index;
   long i, j;
   int nx, ny;
   int lx = TRUE, ly = TRUE;
diff --git a/src/grid_area.c b/src/grid_area.c
index b71bb42..547d04d 100644
--- a/src/grid_area.c
+++ b/src/grid_area.c
@@ -14,10 +14,6 @@
   GNU General Public License for more details.
 */
 
-#if defined(_OPENMP)
-#  include <omp.h>
-#endif
-
 #include <cdi.h>
 #include "cdo.h"
 #include "cdo_int.h"
@@ -222,6 +218,40 @@ double huiliers_area(int num_corners, double *cell_corner_lon, double *cell_corn
   return (sum);
 }
 
+static
+double huiliers_area2(int num_corners, double *cell_corner_lon, double *cell_corner_lat, double cell_center_lon, double cell_center_lat)
+{
+  if ( num_corners < 3 ) return 0;
+
+  // sum areas around cell
+  double sum = 0.0;
+  double pnt1[3], pnt2[3], pnt3[3];
+
+  lonlat_to_xyz(cell_center_lon, cell_center_lat, pnt1);
+  lonlat_to_xyz(cell_corner_lon[0], cell_corner_lat[0], pnt2);
+
+  for ( int i = 1; i < num_corners; i++ )
+    {
+      if ( IS_EQUAL(cell_corner_lon[i], cell_corner_lon[i-1]) && IS_EQUAL(cell_corner_lat[i], cell_corner_lat[i-1]) ) continue;
+
+      // points that make up a side of cell
+      lonlat_to_xyz(cell_corner_lon[i], cell_corner_lat[i], pnt3);
+ 
+      // compute angle for pnt2
+      sum += tri_area(pnt1, pnt2, pnt3);
+
+      pnt2[0] = pnt3[0]; pnt2[1] = pnt3[1]; pnt2[2] = pnt3[2];
+    }
+
+  if ( !(IS_EQUAL(cell_corner_lon[0], cell_corner_lon[num_corners-1]) && IS_EQUAL(cell_corner_lat[0], cell_corner_lat[num_corners-1])) )
+    {
+      lonlat_to_xyz(cell_corner_lon[0], cell_corner_lat[0], pnt3);
+      sum += tri_area(pnt1, pnt2, pnt3);
+    }
+
+  return (sum);
+}
+
 
 int gridGenArea(int gridID, double* area)
 {
@@ -232,6 +262,8 @@ int gridGenArea(int gridID, double* area)
   long i;
   long nv, gridsize;
   int* grid_mask = NULL;
+  double* grid_center_lon = NULL;
+  double* grid_center_lat = NULL;
   double* grid_corner_lon = NULL;
   double* grid_corner_lat = NULL;
 
@@ -302,6 +334,17 @@ int gridGenArea(int gridID, double* area)
       return (status);
     }
 
+  char xunitstr[CDI_MAX_NAME];
+  char yunitstr[CDI_MAX_NAME];
+  gridInqXunits(gridID, xunitstr);
+  gridInqYunits(gridID, yunitstr);
+
+  grid_center_lon = (double*) malloc(gridsize*sizeof(double));
+  grid_center_lat = (double*) malloc(gridsize*sizeof(double));
+
+  gridInqXvals(gridID, grid_center_lon);
+  gridInqYvals(gridID, grid_center_lat);
+
   grid_corner_lon = (double*) malloc(nv*gridsize*sizeof(double));
   grid_corner_lat = (double*) malloc(nv*gridsize*sizeof(double));
 
@@ -314,30 +357,13 @@ int gridGenArea(int gridID, double* area)
     {
       if ( lgrid_gen_bounds )
 	{
-	  char xunitstr[CDI_MAX_NAME];
-	  char yunitstr[CDI_MAX_NAME];
 	  int nlon = gridInqXsize(gridID);
 	  int nlat = gridInqYsize(gridID);
 	  double dlon = 0;
 	  if ( nlon == 1 ) dlon = 1;
 
-	  double *grid_center_lon = NULL;
-	  double *grid_center_lat = NULL;
-
-	  grid_center_lon = (double*) malloc(gridsize*sizeof(double));
-	  grid_center_lat = (double*) malloc(gridsize*sizeof(double));
-
-	  gridInqXvals(gridID, grid_center_lon);
-	  gridInqYvals(gridID, grid_center_lat);
-
-	  gridInqXunits(gridID, xunitstr);
-	  gridInqYunits(gridID, yunitstr);
-
 	  grid_cell_center_to_bounds_X2D(xunitstr, nlon, nlat, grid_center_lon, grid_corner_lon, dlon);
 	  grid_cell_center_to_bounds_Y2D(yunitstr, nlon, nlat, grid_center_lat, grid_corner_lat);
-
-	  free(grid_center_lon);
-	  free(grid_center_lat);
 	}
       else
 	{
@@ -347,28 +373,33 @@ int gridGenArea(int gridID, double* area)
     }
   
   /* Convert lat/lon units if required */
-  {
-    char units[CDI_MAX_NAME];
-
-    gridInqXunits(gridID, units);
-
-    if ( memcmp(units, "radian", 6) == 0 )
-      {
-	/* No conversion necessary */
-      }
-    else if ( memcmp(units, "degree", 6) == 0 )
-      {
-	for ( i = 0; i < gridsize*nv; ++i )
-	  {
-	    grid_corner_lon[i] *= DEG2RAD;
-	    grid_corner_lat[i] *= DEG2RAD;
-	  }
-      }
-    else
-      {
-	cdoWarning("Unknown units supplied for grid1 center lat/lon: proceeding assuming radians");
-      }
-  }
+  if ( memcmp(xunitstr, "radian", 6) == 0 )
+    {
+      /* No conversion necessary */
+    }
+  else if ( memcmp(xunitstr, "degree", 6) == 0 )
+    {
+      for ( i = 0; i < gridsize; ++i ) grid_center_lon[i] *= DEG2RAD;
+      for ( i = 0; i < gridsize*nv; ++i ) grid_corner_lon[i] *= DEG2RAD;
+    }
+  else
+    {
+      cdoWarning("Unknown units supplied for grid1 center lat/lon: proceeding assuming radians");
+    }
+
+  if ( memcmp(yunitstr, "radian", 6) == 0 )
+    {
+      /* No conversion necessary */
+    }
+  else if ( memcmp(yunitstr, "degree", 6) == 0 )
+    {
+      for ( i = 0; i < gridsize; ++i ) grid_center_lat[i] *= DEG2RAD;
+      for ( i = 0; i < gridsize*nv; ++i ) grid_corner_lat[i] *= DEG2RAD;
+    }
+  else
+    {
+      cdoWarning("Unknown units supplied for grid1 center lat/lon: proceeding assuming radians");
+    }
 
   if ( lgriddestroy ) gridDestroy(gridID);
 
@@ -378,23 +409,25 @@ int gridGenArea(int gridID, double* area)
 
 #if defined(_OPENMP)
 #pragma omp parallel for default(none)        \
-  shared(findex, gridsize, area, nv, grid_corner_lon, grid_corner_lat) \
+  shared(findex, gridsize, area, nv, grid_corner_lon, grid_corner_lat, grid_center_lon, grid_center_lat) \
   private(i)
 #endif
   for ( i = 0; i < gridsize; ++i )
     {
       int lprogress = 1;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
+
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
-#if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/gridsize);
 
       //area[i] = cell_area(nv, grid_corner_lon+i*nv, grid_corner_lat+i*nv);
-      area[i] = huiliers_area(nv, grid_corner_lon+i*nv, grid_corner_lat+i*nv);
+      if ( nv <= 4 )
+	area[i] = huiliers_area(nv, grid_corner_lon+i*nv, grid_corner_lat+i*nv);
+      else
+	area[i] = huiliers_area2(nv, grid_corner_lon+i*nv, grid_corner_lat+i*nv, grid_center_lon[i], grid_center_lat[i]);
     }
 
   if ( cdoVerbose )
@@ -404,6 +437,8 @@ int gridGenArea(int gridID, double* area)
       cdoPrint("Total area = %g steradians", total_area);
     }
 
+  free(grid_center_lon);
+  free(grid_center_lat);
   free(grid_corner_lon);
   free(grid_corner_lat);
   if ( grid_mask ) free(grid_mask);
diff --git a/src/griddes.c b/src/griddes.c
index 06004b2..0c70266 100644
--- a/src/griddes.c
+++ b/src/griddes.c
@@ -1771,8 +1771,16 @@ int cdoDefineGrid(const char *gridfile)
   struct stat filestat;
   int fileno;
   int isreg = FALSE;
+  int lalloc = FALSE;
+  char *filename;
 
-  fileno = open(gridfile, O_RDONLY);
+  filename = expand_filename(gridfile);
+  if ( filename )
+    lalloc = TRUE;
+  else
+    filename =  (char *) gridfile;
+
+  fileno = open(filename, O_RDONLY);
   if ( fileno >= 0 )
     {
       if ( fstat(fileno, &filestat) == 0 )
@@ -1790,14 +1798,14 @@ int cdoDefineGrid(const char *gridfile)
   else
     {
       if ( read(fileno, buffer, 4) != 4 )
-	SysError("Read grid from %s failed!", gridfile);
+	SysError("Read grid from %s failed!", filename);
 
       close(fileno);
 
       if ( cmpstr(buffer, "CDF", len) == 0 )
 	{
 	  if ( cdoDebug ) cdoPrint("Grid from netCDF file");
-	  gridID = gridFromNCfile(gridfile);
+	  gridID = gridFromNCfile(filename);
 	}
 
       if ( gridID == -1 )
@@ -1805,7 +1813,7 @@ int cdoDefineGrid(const char *gridfile)
 	  if ( cmpstr(buffer+1, "HDF", len) == 0 )
 	    {
 	      if ( cdoDebug ) cdoPrint("Grid from HDF5 file");
-	      gridID = gridFromH5file(gridfile);
+	      gridID = gridFromH5file(filename);
 	    }
 	}
 
@@ -1814,7 +1822,7 @@ int cdoDefineGrid(const char *gridfile)
 	  if ( cmpstr(buffer+1, "HDF", len) == 0 )
 	    {
 	      if ( cdoDebug ) cdoPrint("Grid from netCDF4 file");
-	      gridID = gridFromNCfile(gridfile);
+	      gridID = gridFromNCfile(filename);
 	    }
 	}
 
@@ -1823,7 +1831,7 @@ int cdoDefineGrid(const char *gridfile)
 	  int streamID;
 	  if ( cdoDebug ) cdoPrint("Grid from CDI file");
 	  openLock();
-	  streamID = streamOpenRead(gridfile);
+	  streamID = streamOpenRead(filename);
 	  openUnlock();
 	  if ( streamID >= 0 )
 	    {
@@ -1837,22 +1845,28 @@ int cdoDefineGrid(const char *gridfile)
       if ( gridID == -1 )
 	{
 	  if ( cdoDebug ) cdoPrint("grid from ASCII file");
-	  gfp = fopen(gridfile, "r");
-	  gridID = gridFromFile(gfp, gridfile);
+	  gfp = fopen(filename, "r");
+	  //size_t buffersize = 20*1024*1024;
+	  //char *buffer = (char*) malloc(buffersize);
+	  //setvbuf(gfp, buffer, _IOFBF, buffersize);
+	  gridID = gridFromFile(gfp, filename);
 	  fclose(gfp);
+	  //free(buffer);
 	}
 
       if ( gridID == -1 )
 	{
 	  if ( cdoDebug ) cdoPrint("grid from PINGO file");
-	  gfp = fopen(gridfile, "r");
-	  gridID = gridFromPingo(gfp, gridfile);
+	  gfp = fopen(filename, "r");
+	  gridID = gridFromPingo(gfp, filename);
 	  fclose(gfp);
 	}
 
-      if ( gridID == -1 ) cdoAbort("Invalid grid description file %s!", gridfile);
+      if ( gridID == -1 ) cdoAbort("Invalid grid description file %s!", filename);
     }
 
+  if ( lalloc ) free(filename);
+
   return (gridID);
 }
 
diff --git a/src/hetaeta.c b/src/hetaeta.c
index f8c839d..6c71713 100644
--- a/src/hetaeta.c
+++ b/src/hetaeta.c
@@ -730,10 +730,7 @@ void hetaeta(int ltq, int ngp, const int *imiss,
   for ( ij = 0; ij < ngp; ++ij )
     {
 #if defined(_OPENMP)
-      int ompthID;
-      long iv;      
-
-      ompthID = omp_get_thread_num();
+      int ompthID = omp_get_thread_num();
 
       ph1    = ph1_2[ompthID];
       lnph1  = lnph1_2[ompthID];
@@ -770,7 +767,7 @@ void hetaeta(int ltq, int ngp, const int *imiss,
 
       if ( nvars > 0 )
 	{
-	  for ( iv = 0; iv < nvars; ++iv )
+	  for ( int iv = 0; iv < nvars; ++iv )
 	    vars_pbl[iv] = vars_pbl_2[ompthID][iv];
 	}
 #endif
diff --git a/src/interpol.c b/src/interpol.c
index 4cf343c..142429d 100644
--- a/src/interpol.c
+++ b/src/interpol.c
@@ -4,9 +4,6 @@
 #include "grid.h"
 #include "util.h"  /* progressStatus */
 
-#if defined(_OPENMP)
-#include <omp.h>  // omp_get_thread_num()
-#endif
 
 #define  ZERO     0.0
 #define  ONE      1.0
@@ -260,14 +257,12 @@ void intlinarr2(double missval, int lon_is_circular,
       long iix;
       int lfound;
       int lprogress = 1;
-#if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
 
       field[i] = missval;
 
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/gridsize2);
@@ -458,7 +453,7 @@ void intconarr2(double missval, int lon_is_circular,
       ndeps = 0;
       /*
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
 #endif
       */
       field[i] = missval;
@@ -475,7 +470,7 @@ void intconarr2(double missval, int lon_is_circular,
       //printf("bound_box %ld  lon: %g %g lat: %g %g\n", i, bound_box[2]*RAD2DEG, bound_box[3]*RAD2DEG, bound_box[0]*RAD2DEG, bound_box[1]*RAD2DEG);
       /*
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       */
       findex++;
diff --git a/src/modules.c b/src/modules.c
index 97bf974..a5de5bf 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -54,6 +54,7 @@ void *CDIwrite(void *argument);
 void *Change(void *argument);
 void *Change_e5slm(void *argument);
 void *Cloudlayer(void *argument);
+void *Collgrid(void *argument);
 void *Command(void *argument);
 void *Comp(void *argument);
 void *Compc(void *argument);
@@ -67,6 +68,7 @@ void *Deltime(void *argument);
 void *Derivepar(void *argument);
 void *Detrend(void *argument);
 void *Diff(void *argument);
+void *Distgrid(void *argument);
 void *Duplicate(void *argument);
 void *Echam5ini(void *argument);
 void *Enlarge(void *argument);
@@ -87,11 +89,11 @@ void *Fldrms(void *argument);
 void *Fldstat(void *argument);
 void *Fldstat2(void *argument);
 void *Fourier(void *argument);
-void *Gather(void *argument);
 void *Gengrid(void *argument);
 void *Gradsdes(void *argument);
 void *Gridboxstat(void *argument);
 void *Gridcell(void *argument);
+void *Gridsearch(void *argument);
 void *Harmonic(void *argument);
 void *Histogram(void *argument);
 void *Importamsr(void *argument);
@@ -157,7 +159,6 @@ void *Setpartab(void *argument);
 void *Setrcaname(void *argument);
 void *Settime(void *argument);
 void *Setzaxis(void *argument);
-void *Scatter(void *argument);
 void *Showinfo(void *argument);
 void *Sinfo(void *argument);
 void *Smooth9(void *argument);
@@ -283,6 +284,7 @@ void *Maggraph(void *argument);
 #define  ChangeOperators        {"chcode", "chtabnum", "chparam", "chname", "chunit", "chlevel", "chlevelc", "chlevelv", "chltype"}
 #define  Change_e5slmOperators  {"change_e5slm", "change_e5lsm", "change_e5mask"}
 #define  CloudlayerOperators    {"cloudlayer"}
+#define  CollgridOperators      {"collgrid"}
 #define  CommandOperators       {"command", "com", "cmd"}
 #define  CompOperators          {"eq",  "ne",  "le",  "lt",  "ge",  "gt"}
 #define  CompcOperators         {"eqc", "nec", "lec", "ltc", "gec", "gtc"}
@@ -296,6 +298,7 @@ void *Maggraph(void *argument);
 #define  DeriveparOperators     {"gheight", "sealevelpressure"}
 #define  DetrendOperators       {"detrend"}
 #define  DiffOperators          {"diff", "diffp", "diffn", "diffc"}
+#define  DistgridOperators      {"distgrid"}
 #define  DuplicateOperators     {"duplicate"}
 #define  Echam5iniOperators     {"import_e5ml", "import_e5res", \
                                  "export_e5ml", "export_e5res"}
@@ -319,11 +322,11 @@ void *Maggraph(void *argument);
 #define  FldcorOperators        {"fldcor"}
 #define  FldcovarOperators      {"fldcovar"}
 #define  FourierOperators       {"fourier"}
-#define  GatherOperators        {"gather"}
 #define  GengridOperators       {"gengrid"}
 #define  GradsdesOperators      {"gradsdes", "dumpmap"}
 #define  GridboxstatOperators   {"gridboxmin", "gridboxmax", "gridboxsum", "gridboxmean", "gridboxavg", "gridboxvar", "gridboxstd"}
 #define  GridcellOperators      {"gridarea", "gridweights", "gridmask", "griddx", "griddy"}
+#define  GridsearchOperators    {"testpointsearch", "testcellsearch"}
 #define  HarmonicOperators      {"harmonic"}
 #define  HistogramOperators     {"histcount", "histsum", "histmean", "histfreq"}
 #define  ImportamsrOperators    {"import_amsr"}
@@ -339,13 +342,11 @@ void *Maggraph(void *argument);
 #define  InttimeOperators       {"inttime"}
 #define  IntntimeOperators      {"intntime"}
 #define  IntyearOperators       {"intyear"}
-#define  InvertOperators        {"invertlat", "invertlon", "invertlatdes", "invertlondes", \
-                                 "invertlatdata", "invertlondata"}
+#define  InvertOperators        {"invertlat", "invertlon", "invertlatdes", "invertlondes", "invertlatdata", "invertlondata"}
 #define  InvertlevOperators     {"invertlev"}
 #define  IsosurfaceOperators    {"isosurface"}
 #define  KvlOperators           {"read_cmor_table", "conv_cmor_table"}
-#define  LogOperators           {"dumplogs", "daylogs", "monlogs", "dumplogo", \
-                                 "snamelogo", "scalllogo", "smemlogo", "stimelogo", "sperclogo"}
+#define  LogOperators           {"dumplogs", "daylogs", "monlogs", "dumplogo", "snamelogo", "scalllogo", "smemlogo", "stimelogo", "sperclogo"}
 #define  MaskboxOperators       {"masklonlatbox", "maskindexbox"}
 #define  MaskregionOperators    {"maskregion"}
 #define  MastrfuOperators       {"mastrfu"}
@@ -389,18 +390,18 @@ void *Maggraph(void *argument);
 #define  SelrecOperators        {"selrec"}
 #define  SeltimeOperators       {"seltimestep", "selyear", "selseas", "selmon", "selday", "selhour", "seldate", \
                                  "seltime", "selsmon"}
-#define  SetOperators           {"setpartab", "setcode", "setparam", "setname", "setunit", "setlevel", "setltype", "settabnum"}
+#define  SetOperators           {"setcode", "setparam", "setname", "setunit", "setlevel", "setltype", "settabnum"}
 #define  SetboxOperators        {"setclonlatbox", "setcindexbox"}
 #define  SetgattOperators       {"setgatt", "setgatts"}
 #define  SetgridOperators       {"setgrid", "setgridtype", "setgridarea", "setgridmask", "unsetgridmask", "setgridnumber", "setgriduri"}
 #define  SethaloOperators       {"sethalo", "tpnhalo"}
 #define  SetmissOperators       {"setmissval", "setctomiss", "setmisstoc", "setrtomiss", "setvrange"}
+#define  Setpartab0Operators    {"setpartab"}
 #define  SetpartabOperators     {"setpartabc", "setpartabp", "setpartabn"}
 #define  SetrcanameOperators    {"setrcaname"}
 #define  SettimeOperators       {"setyear", "setmon", "setday", "setdate", "settime", "settunits", \
                                  "settaxis", "setreftime", "setcalendar", "shifttime"}
 #define  SetzaxisOperators      {"setzaxis"}
-#define  ScatterOperators       {"scatter"}
 #define  ShowinfoOperators      {"showyear", "showmon", "showdate", "showtime", "showtimestamp", "showcode", "showunit", \
                                  "showparam", "showname", "showstdname", "showlevel", "showltype", "showformat"}
 #define  SinfoOperators         {"sinfo", "sinfop", "sinfon", "sinfoc", "seinfo", "seinfop", "seinfon", "seinfoc"}
@@ -454,8 +455,7 @@ void *Maggraph(void *argument);
 #define  VardupOperators        {"pardup", "parmul"}
 #define  VargenOperators        {"random", "const", "sincos", "coshill", "for", "topo", "temp", "mask", "stdatm"}
 #define  VarrmsOperators        {"varrms"}
-#define  VertintOperators       {"ml2pl", "ml2hl", "ml2plx", "ml2hlx", \
-                                 "ml2pl_lp", "ml2hl_lp", "ml2plx_lp", "ml2hlx_lp"}
+#define  VertintOperators       {"ml2pl", "ml2hl", "ml2plx", "ml2hlx", "ml2pl_lp", "ml2hl_lp", "ml2plx_lp", "ml2hlx_lp"}
 #define  VertstatOperators      {"vertmin", "vertmax", "vertsum", "vertmean", "vertavg", "vertvar", "vertstd"}
 #define  VertwindOperators      {"vertwind"}
 #define  WindOperators          {"uv2dv", "uv2dvl", "dv2uv", "dv2uvl", "dv2ps"}
@@ -552,6 +552,7 @@ static modules_t Modules[] =
   { Change,         ChangeHelp,        ChangeOperators,        CDI_REAL,  1,  1 },
   { Change_e5slm,   NULL,              Change_e5slmOperators,  CDI_REAL,  1,  1 },
   { Cloudlayer,     NULL,              CloudlayerOperators,    CDI_REAL,  1,  1 },
+  { Collgrid,       CollgridHelp,      CollgridOperators,      CDI_REAL, -1,  1 },
   { Command,        NULL,              CommandOperators,       CDI_REAL,  1,  0 },
   { Comp,           CompHelp,          CompOperators,          CDI_REAL,  2,  1 },
   { Compc,          CompcHelp,         CompcOperators,         CDI_REAL,  1,  1 },
@@ -565,6 +566,7 @@ static modules_t Modules[] =
   { Derivepar,      DeriveparHelp,     DeriveparOperators,     CDI_REAL,  1,  1 },
   { Detrend,        DetrendHelp,       DetrendOperators,       CDI_REAL,  1,  1 },
   { Diff,           DiffHelp,          DiffOperators,          CDI_REAL,  2,  0 },
+  { Distgrid,       DistgridHelp,      DistgridOperators,       CDI_REAL,  1,  1 },
   { Duplicate,      DuplicateHelp,     DuplicateOperators,     CDI_REAL,  1,  1 },
   { Echam5ini,      NULL,              Echam5iniOperators,     CDI_REAL,  1,  1 },
   { Enlarge,        EnlargeHelp,       EnlargeOperators,       CDI_REAL,  1,  1 },
@@ -586,11 +588,11 @@ static modules_t Modules[] =
   { Fldstat2,       FldcorHelp,        FldcorOperators,        CDI_REAL,  2,  1 },
   { Fldstat2,       FldcovarHelp,      FldcovarOperators,      CDI_REAL,  2,  1 },
   { Fourier,        NULL,              FourierOperators,       CDI_COMP,  1,  1 },
-  { Gather,         NULL,              GatherOperators,        CDI_REAL, -1,  1 },
   { Gengrid,        NULL,              GengridOperators,       CDI_REAL,  2,  1 },
   { Gradsdes,       GradsdesHelp,      GradsdesOperators,      CDI_REAL,  1,  0 },
   { Gridboxstat,    GridboxstatHelp,   GridboxstatOperators,   CDI_REAL,  1,  1 },
   { Gridcell,       GridcellHelp,      GridcellOperators,      CDI_REAL,  1,  1 },
+  { Gridsearch,     NULL,              GridsearchOperators,    CDI_REAL,  0,  0 },
   { Harmonic,       NULL,              HarmonicOperators,      CDI_REAL,  1,  1 },
   { Histogram,      HistogramHelp,     HistogramOperators,     CDI_REAL,  1,  1 },
   { Importamsr,     ImportamsrHelp,    ImportamsrOperators,    CDI_REAL,  1,  1 },
@@ -655,11 +657,11 @@ static modules_t Modules[] =
   { Setgrid,        SetgridHelp,       SetgridOperators,       CDI_BOTH,  1,  1 },
   { Sethalo,        SethaloHelp,       SethaloOperators,       CDI_REAL,  1,  1 },
   { Setmiss,        SetmissHelp,       SetmissOperators,       CDI_REAL,  1,  1 },
+  { Setpartab,      SetHelp,           Setpartab0Operators,    CDI_REAL,  1,  1 },
   { Setpartab,      SetpartabHelp,     SetpartabOperators,     CDI_REAL,  1,  1 },
   { Setrcaname,     NULL,              SetrcanameOperators,    CDI_REAL,  1,  1 },
   { Settime,        SettimeHelp,       SettimeOperators,       CDI_BOTH,  1,  1 },
   { Setzaxis,       SetzaxisHelp,      SetzaxisOperators,      CDI_BOTH,  1,  1 },
-  { Scatter,        NULL,              ScatterOperators,       CDI_REAL,  1,  1 },
   { Showinfo,       ShowinfoHelp,      ShowinfoOperators,      CDI_BOTH,  1,  0 },
   { Sinfo,          SinfoHelp,         SinfoOperators,         CDI_BOTH, -1,  0 },
   { Smooth9,        Smooth9Help,       Smooth9Operators,       CDI_REAL,  1,  1 },
@@ -790,6 +792,7 @@ static char *opalias[][2] =
   {"diffv",               "diffn"      },
   {"covar0",              "timcovar"   },
   {"covar0r",             "fldcovar"   },
+  {"gather",              "collgrid"   },
   {"geopotheight",        "gheight"    },
   {"ggstat",              "info"       },
   {"ggstats",             "sinfo"      },
@@ -814,6 +817,7 @@ static char *opalias[][2] =
   {"read_e5ml",           "import_e5ml"},
   {"remapcon1",           "remaplaf"   },
   {"remapdis1",           "remapnn"    },
+  {"scatter",             "distgrid"   },
   {"showvar",             "showname"   },
   {"selgridname",         "selgrid"    },
   {"selzaxisname",        "selzaxis"   },
diff --git a/src/operator_help.h b/src/operator_help.h
index 5720e79..37cfb08 100644
--- a/src/operator_help.h
+++ b/src/operator_help.h
@@ -396,6 +396,51 @@ static char *SplitselHelp[] = {
     NULL
 };
 
+static char *DistgridHelp[] = {
+    "NAME",
+    "    distgrid - Distribute horizontal grid",
+    "",
+    "SYNOPSIS",
+    "    distgrid,nx[,ny]  ifile obase",
+    "",
+    "DESCRIPTION",
+    "    This operator distributes a dataset into smaller pieces. Each output file contains a different region of the horizontal ",
+    "    source grid. A target grid region contains a regular longitude/latitude box of the source grid. Only rectilinear source ",
+    "    grids are supported by this operator. The number of different regions can be specified with the parameter nx and ny.",
+    "    The output files will be named <obase><xxx><suffix> where suffix is the filename extension derived from the file format. ",
+    "    xxx will have five digits with the number of the target region.",
+    "",
+    "PARAMETER",
+    "    nx  INTEGER  Number of regions in x direction",
+    "    ny  INTEGER  Number of regions in y direction [default: 1]",
+    "",
+    "NOTE",
+    "    This operator needs to open all output files simultaneously.",
+    "    The maximum number of open files depents on the operating system!",
+    NULL
+};
+
+static char *CollgridHelp[] = {
+    "NAME",
+    "    collgrid - Collect horizontal grid",
+    "",
+    "SYNOPSIS",
+    "    collgrid[,names]  ifiles ofile",
+    "",
+    "DESCRIPTION",
+    "    This operator collects the data of the input files to one output file. ",
+    "    All input files need to have the same variables and the same number of timesteps on a different",
+    "    horizonal grid region. A source region must be a rectilinear longitude/latitude grid box.",
+    "",
+    "PARAMETER",
+    "    names  STRING  Comma separated list of variable names [default: all variables]",
+    "",
+    "NOTE",
+    "    This operator needs to open all input files simultaneously.",
+    "    The maximum number of open files depents on the operating system!",
+    NULL
+};
+
 static char *SelectHelp[] = {
     "NAME",
     "    select, delete - Select fields",
@@ -1945,7 +1990,7 @@ static char *TimselpctlHelp[] = {
     "    timselpctl,p,nsets[,noffset[,nskip]]  ifile1 ifile2 ifile3 ofile",
     "",
     "DESCRIPTION",
-    "    This operator computes percentile values over a selected number of time steps in ifile1.",
+    "    This operator computes percentile values over a selected number of timesteps in ifile1.",
     "    The algorithm uses histograms with minimum and maximum bounds given in ifile2 and ifile3,",
     "    respectively. The default number of histogram bins is 101. The default can be overridden by setting the",
     "    environment variable CDO_PCTL_NBINS to a different value. The files ifile2 and ifile3 ",
@@ -2027,8 +2072,8 @@ static char *RunpctlHelp[] = {
     "    runpctl,p,nts  ifile1 ofile",
     "",
     "DESCRIPTION",
-    "    This module computes running percentiles over a selected number of time steps in ifile1.",
-    "    The date information in ofile is the date of the medium contributing timestep in ifile1.",
+    "    This module computes running percentiles over a selected number of timesteps in ifile1.",
+    "    The date information in ofile is the date of the timestep in the middle of the contributing timesteps in ifile1.",
     "    ",
     "    o(t+(nts-1)/2,x) = pth percentile {i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
     "",
@@ -2897,20 +2942,17 @@ static char *YdrunstatHelp[] = {
     "    <operator>,nts  ifile ofile",
     "",
     "DESCRIPTION",
-    "    This module writes running statistical values for each day of year",
-    "    in ifile to ofile. Depending on the chosen operator, the minimum,",
-    "    maximum, sum, average, variance or standard deviation of all timesteps in",
-    "    running windows of wich the medium timestep corresponds to a certain day of",
-    "    year is computed. The date information in an output field is the date of the",
-    "    medium timestep in the last contributing running window.",
-    "    Note that the operator have to be applied to a continuous time series of daily",
-    "    measurements in order to yield physically meaningful results. Also note that",
-    "    the output time series begins (nts-1)/2 timesteps after the first timestep",
-    "    of the input time series and ends (nts-1)/2 timesteps before the last one.",
-    "    For input data which are complete but not continuous, such as time series of",
-    "    daily measurements for the same month or season within different years, the",
-    "    operator yields physically meaningful results only if the input time series",
-    "    does include the (nts-1)/2 days before and after each period of interest.",
+    "    This module writes running statistical values for each day of year in ifile to ofile.",
+    "    Depending on the chosen operator, the minimum, maximum, sum, average, variance or standard deviation ",
+    "    of all timesteps in running windows of which the medium timestep corresponds to a certain day of",
+    "    year is computed. The date information in an output field is the date of the timestep in the middle ",
+    "    of the last contributing running window.",
+    "    Note that the operator have to be applied to a continuous time series of daily measurements in order ",
+    "    to yield physically meaningful results. Also note that the output time series begins (nts-1)/2 timesteps",
+    "    after the first timestep of the input time series and ends (nts-1)/2 timesteps before the last one.",
+    "    For input data which are complete but not continuous, such as time series of daily measurements for ",
+    "    the same month or season within different years, the operator yields physically meaningful results ",
+    "    only if the input time series does include the (nts-1)/2 days before and after each period of interest.",
     "",
     "OPERATORS",
     "    ydrunmin   Multi-year daily running minimum",
@@ -2978,7 +3020,7 @@ static char *YdrunpctlHelp[] = {
     "    respectively. The default number of histogram bins is 101. The default can be overridden",
     "    by setting the environment variable CDO_PCTL_NBINS to a different value. The files ifile2 ",
     "    and ifile3 should be the result of corresponding ydrunmin and ydrunmax operations, respectively.",
-    "    The date information in an output field is the date of the medium time step in the last ",
+    "    The date information in an output field is the date of the timestep in the middle of the last ",
     "    contributing running window.",
     "    Note that the operator have to be applied to a continuous time series of daily measurements ",
     "    in order to yield physically meaningful results. Also note that the output time series begins",
@@ -3277,6 +3319,11 @@ static char *RemapgridHelp[] = {
     "    grid  STRING  Target grid description file or name",
     "",
     "ENVIRONMENT",
+    "    CDO_REMAP_NORMALIZE_OPT",
+    "        This variable is used to choose the normalization of the conservative ",
+    "        remapping. By default @env{CDO_REMAP_NORMALIZE_OPT} is set to 'fracarea' and will",
+    "        include the destination area fraction in the output weights; other ",
+    "        options are 'none' and 'destarea' (for more information see {SCRIP}).",
     "    REMAP_EXTRAPOLATE      ",
     "        This variable is used to switch the extrapolation feature 'on' or 'off'.",
     "        By default the extrapolation is enabled for remapdis, remapnn and for circular grids.",
@@ -3339,13 +3386,20 @@ static char *GenweightsHelp[] = {
     "    grid  STRING  Target grid description file or name",
     "",
     "ENVIRONMENT",
-    "    REMAP_EXTRAPOLATE",
+    "    CDO_REMAP_NORMALIZE_OPT",
+    "        This variable is used to choose the normalization of the conservative ",
+    "        interpolation. By default @env{CDO_REMAP_NORMALIZE_OPT} is set to 'fracarea' and will",
+    "        include the destination area fraction in the output weights; other ",
+    "        options are 'none' and 'destarea' (for more information see {SCRIP}).",
+    "    REMAP_EXTRAPOLATE      ",
     "        This variable is used to switch the extrapolation feature 'on' or 'off'.",
     "        By default the extrapolation is enabled for remapdis, remapnn",
     "        and for circular grids.",
-    "    REMAP_AREA_MIN   ",
+    "    REMAP_AREA_MIN         ",
     "        This variable is used to set the minimum destination area fraction. The default",
     "        of this variable is 0.0.",
+    "    CDO_REMAP_SEARCH_RADIUS",
+    "        Remap search radius in degree, default 180 degree.",
     "",
     "NOTE",
     "    For this module the author has converted the original Fortran 90 SCRIP ",
@@ -3374,12 +3428,19 @@ static char *RemapHelp[] = {
     "    weights  STRING  Interpolation weights (SCRIP netCDF file)",
     "",
     "ENVIRONMENT",
-    "    REMAP_EXTRAPOLATE",
+    "    CDO_REMAP_NORMALIZE_OPT",
+    "        This variable is used to choose the normalization of the conservative ",
+    "        interpolation. By default @env{CDO_REMAP_NORMALIZE_OPT} is set to 'fracarea' and will",
+    "        include the destination area fraction in the output weights; other ",
+    "        options are 'none' and 'destarea' (for more information see {SCRIP}).",
+    "    REMAP_EXTRAPOLATE      ",
     "        This variable is used to switch the extrapolation feature 'on' or 'off'.",
     "        By default the extrapolation is enabled for remapdis, remapnn and for circular grids.",
-    "    REMAP_AREA_MIN   ",
+    "    REMAP_AREA_MIN         ",
     "        This variable is used to set the minimum destination area fraction. The default",
     "        of this variable is 0.0.",
+    "    CDO_REMAP_SEARCH_RADIUS",
+    "        Remap search radius in degree, default 180 degree.",
     "",
     "NOTE",
     "    For this module the author has converted the original Fortran 90 SCRIP ",
@@ -3529,21 +3590,11 @@ static char *Intlevel3dHelp[] = {
     "",
     "OPERATORS",
     "    intlevel3d   Linear level interpolation onto a 3d vertical coordinate",
-    "                 To interpolate 3D variables from one set of 3d height levels",
-    "                 into another one where",
-    "                 - icoordinate contains a single 3d variable,",
-    "                   which represents the input 3d vert. coordinate",
-    "                 - ifile1 contains the source data,",
-    "                   which the vertical coordinate from icoordinate belongs to",
-    "                 - ifile2 only contains the target 3d height levels",
-    "                 ",
-    "                 call",
-    "                    cdo intlevel3,icoordinate ifile1 ifile2 ofile",
     "    intlevelx3d  like intlevel3d but with extrapolation",
     "",
     "PARAMETER",
     "    icoordinate  STRING  filename for vertical source coordinates variable",
-    "    ifile2       STRING target vertical coordinate field (intlevel3d only)",
+    "    ifile2       STRING  target vertical coordinate field (intlevel3d only)",
     NULL
 };
 
@@ -3810,16 +3861,18 @@ static char *InputHelp[] = {
     "OPERATORS",
     "    input     ASCII input",
     "              Reads fields with ASCII numbers from standard input and stores them",
-    "              in ofile. The numbers read are exactly that ones which are ",
-    "              written out by output.",
+    "              in ofile. The numbers read are exactly that ones which are written ",
+    "              out by the output operator.",
     "    inputsrv  SERVICE ASCII input",
     "              Reads fields with ASCII numbers from standard input and stores them ",
     "              in ofile. Each field should have a header of 8 integers (SERVICE likely).",
-    "              The numbers that are read are exactly that ones which are written out by outputsrv.",
+    "              The numbers that are read are exactly that ones which are written out by ",
+    "              the outputsrv operator.",
     "    inputext  EXTRA ASCII input",
     "              Read fields with ASCII numbers from standard input and stores them ",
     "              in ofile. Each field should have header of 4 integers (EXTRA likely).",
-    "              The numbers read are exactly that ones which are written out by outputext.",
+    "              The numbers read are exactly that ones which are written out by ",
+    "              the outputext operator.",
     "",
     "PARAMETER",
     "    grid  STRING  Grid description file or name",
diff --git a/src/pragma_omp_atomic_update.h b/src/pragma_omp_atomic_update.h
new file mode 100644
index 0000000..1ff553e
--- /dev/null
+++ b/src/pragma_omp_atomic_update.h
@@ -0,0 +1,7 @@
+#if defined(_OPENMP)
+#if _OPENMP >= OPENMP4
+#pragma omp atomic update
+#else
+#pragma omp atomic
+#endif
+#endif
diff --git a/src/process.c b/src/process.c
index 5f61b9f..32896b8 100644
--- a/src/process.c
+++ b/src/process.c
@@ -166,13 +166,11 @@ int processSelf(void)
 
 int processNums(void)
 {
-  int pnums = 0;
-
 #if defined(HAVE_LIBPTHREAD)
   pthread_mutex_lock(&processMutex);
 #endif
 
-  pnums = NumProcess;
+  int pnums = NumProcess;
 
 #if defined(HAVE_LIBPTHREAD)
   pthread_mutex_unlock(&processMutex);  
@@ -184,13 +182,11 @@ int processNums(void)
 
 int processNumsActive(void)
 {
-  int pnums = 0;
-
 #if defined(HAVE_LIBPTHREAD)
   pthread_mutex_lock(&processMutex);
 #endif
 
-  pnums = NumProcessActive;
+  int pnums = NumProcessActive;
 
 #if defined(HAVE_LIBPTHREAD)
   pthread_mutex_unlock(&processMutex);  
@@ -210,11 +206,7 @@ void processAddNvals(off_t nvals)
 
 off_t processInqNvals(int processID)
 {
-  off_t nvals = 0;
-
-  nvals = Process[processID].nvals;
-
-  return (nvals);
+  return (Process[processID].nvals);
 }
 
 
@@ -331,15 +323,32 @@ const char *processInqPrompt(void)
 }
 
 #if defined(HAVE_GLOB_H)
+static
+int get_glob_flags(void)
+{
+  int glob_flags = 0;
+
+#if defined (GLOB_NOCHECK)
+  glob_flags |= GLOB_NOCHECK;
+#endif
+#if defined (GLOB_TILDE)
+  glob_flags |= GLOB_TILDE;
+#endif
+
+  return (glob_flags);
+}
+
 /* Convert a wildcard pattern into a list of blank-separated filenames which match the wildcard. */
+static
 argument_t *glob_pattern(const char *restrict wildcard)
 {
   size_t cnt, length = 0;
+  int glob_flags = get_glob_flags();
   glob_t glob_results;
   char **p;
   argument_t *argument = NULL;
 
-  glob(wildcard, GLOB_NOCHECK, 0, &glob_results);
+  glob(wildcard, glob_flags, 0, &glob_results);
 
   /* How much space do we need?  */
   for ( p = glob_results.gl_pathv, cnt = glob_results.gl_pathc; cnt; p++, cnt-- )
@@ -545,20 +554,63 @@ void setStreamNames(int argc, char *argv[])
 }
 
 static
+int find_wildcard(const char *string, size_t len)
+{
+  int status = 0;
+
+  if ( len > 0 )
+    {
+      if ( string[0] == '~' ) status = 1;
+
+      if ( status == 0 )
+	{
+	  for ( size_t i = 0; i < len; ++i )
+	    if ( string[i] == '?' || string[i] == '*' || string[i] == '[' )
+	      {
+		status = 1;
+		break;
+	      }
+	}
+    }
+
+  return status;
+}
+
+
+char *expand_filename(const char *string)
+{
+  char *filename = NULL;
+
+  if ( find_wildcard(string, strlen(string)) )
+    {
+#if defined(HAVE_GLOB_H)
+      int glob_flags = get_glob_flags();
+      glob_t glob_results;
+
+      glob(string, glob_flags, 0, &glob_results);
+
+      if ( glob_results.gl_pathc == 1 ) filename = strdupx(glob_results.gl_pathv[0]);
+
+      globfree(&glob_results);
+#endif
+    }
+
+  return filename;
+}
+
+static
 int expand_wildcards(int processID, int streamCnt)
 {
-  int i;
   const char *streamname0 = Process[processID].streamNames[0].args;
-  int len = strlen(streamname0);
 
-  for ( i = 0; i < len; ++i ) if ( streamname0[i] == '?' || streamname0[i] == '*' || streamname0[i] == '[' ) break;
-  if ( i < len )
+  if ( find_wildcard(streamname0, strlen(streamname0)) )
     {
 #if defined(HAVE_GLOB_H)
       argument_t *glob_arg = glob_pattern(streamname0);
 
       if ( strcmp(streamname0, glob_arg->args) != 0 )
 	{
+	  int i;
 	  streamCnt = streamCnt - 1 + glob_arg->argc;
 
 	  free(Process[processID].streamNames[0].argv);
diff --git a/src/pstream.c b/src/pstream.c
index f99e696..3c616f2 100644
--- a/src/pstream.c
+++ b/src/pstream.c
@@ -61,6 +61,7 @@ static int _pstream_init = FALSE;
 #include <pthread.h>
 #include "pthread_debug.h"
 
+// TODO: make threadsafe
 static int pthreadScope = 0;
 
 static pthread_mutex_t streamOpenReadMutex  = PTHREAD_MUTEX_INITIALIZER;
@@ -112,10 +113,8 @@ void pstream_list_delete(void)
 
 static
 void pstream_init_pointer(void)
-{
-  int  i;
-  
-  for ( i = 0; i < _pstream_max; i++ )
+{  
+  for ( int i = 0; i < _pstream_max; i++ )
     {
       _pstreamList[i].next = _pstreamList + i + 1;
       _pstreamList[i].idx  = i;
@@ -718,11 +717,12 @@ int pstreamOpenWrite(const argument_t *argument, int filetype)
 	  streamDefCompType(fileID, cdoCompType);
 	  streamDefCompLevel(fileID, cdoCompLevel);
 
-	  if ( cdoCompType == COMPRESS_SZIP && (filetype != FILETYPE_GRB && filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
-	    cdoWarning("SZIP compression not available for non GRIB1/netCDF4 data!");
+	  if ( cdoCompType == COMPRESS_SZIP &&
+	       (filetype != FILETYPE_GRB && filetype != FILETYPE_GRB2 && filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
+	    cdoWarning("SZIP compression not available for non GRIB/netCDF4 data!");
 
 	  if ( cdoCompType == COMPRESS_JPEG && filetype != FILETYPE_GRB2 )
-	    cdoWarning("SZIP compression not available for non GRIB2 data!");
+	    cdoWarning("JPEG compression not available for non GRIB2 data!");
 
 	  if ( cdoCompType == COMPRESS_ZIP && (filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
 	    cdoWarning("Deflate compression not available for non netCDF4 data!");
@@ -855,7 +855,7 @@ void pstreamClose(int pstreamID)
 
 	  pstream_delete_entry(pstreamptr);
 	}
-      else
+      else if ( lwrite )
 	{
 	  pipe = pstreamptr->pipe;
 	  pthread_mutex_lock(pipe->mutex);
@@ -1533,11 +1533,45 @@ void cdoInitialize(void *argument)
 }
 
 
+void pstreamCloseAll(void)
+{
+  if ( _pstreamList == NULL ) return;
+
+  for ( int i = 0; i < _pstream_max; i++ )
+    {
+      pstream_t *pstreamptr = _pstreamList[i].ptr;
+      if ( pstreamptr && pstreamptr->isopen )
+	{
+	  if ( !pstreamptr->ispipe )
+	    {
+	      if ( PSTREAM_Debug )
+		Message("Close file %s id %d", pstreamptr->name, pstreamptr->fileID);
+	      streamClose(pstreamptr->fileID);
+	    }
+	}
+    }
+}
+
+static
+void processClosePipes(void)
+{
+  int nstream = processInqStreamNum();
+  for ( int sindex = 0; sindex < nstream; sindex++ )
+    {
+      int pstreamID = processInqStreamID(sindex);
+      pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
+
+      if ( PSTREAM_Debug )
+	Message("process %d  stream %d  close streamID %d", processSelf(), sindex, pstreamID);
+
+      if ( pstreamptr ) pstreamClose(pstreamID);
+    }
+}
+
+
 void cdoFinish(void)
 {
   int processID = processSelf();
-  int sindex, pstreamID;
-  int nstream;
   INT64 nvals;
   int nvars, ntimesteps;
   char memstring[32] = {""};
@@ -1545,7 +1579,6 @@ void cdoFinish(void)
   double e_utime, e_stime;
   double c_cputime = 0, c_usertime = 0, c_systime = 0;
   double p_cputime = 0, p_usertime = 0, p_systime = 0;
-  pstream_t *pstreamptr;
 
 #if defined(HAVE_LIBPTHREAD)
   if ( PSTREAM_Debug )
@@ -1653,16 +1686,7 @@ void cdoFinish(void)
   fprintf(stderr, "\n");
 #endif
 
-  nstream = processInqStreamNum();
-  for ( sindex = 0; sindex < nstream; sindex++ )
-    {
-      pstreamID = processInqStreamID(sindex);
-      pstreamptr = pstream_to_pointer(pstreamID);
-      if ( PSTREAM_Debug )
-	Message("process %d  stream %d  close streamID %d", processID, sindex, pstreamID);
-
-      if ( pstreamptr ) pstreamClose(pstreamID);
-    }
+  processClosePipes();
 
   processDelete();
 }
@@ -1703,13 +1727,28 @@ int pstreamInqByteorder(int pstreamID)
   return (byteorder);
 }
 
-void pstreamInqGinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum)
+void pstreamInqGRIBinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum)
 {
   pstream_t *pstreamptr;
 
   pstreamptr = pstream_to_pointer(pstreamID);
 
-  streamInqGinfo(pstreamptr->fileID, intnum, fltnum, bignum);
+  streamInqGRIBinfo(pstreamptr->fileID, intnum, fltnum, bignum);
+}
+
+
+void cdoVlistCopyFlag(int vlistID2, int vlistID1)
+{
+#if defined(HAVE_LIBPTHREAD)
+  pthread_mutex_lock(&streamMutex);
+#endif
+
+  vlistCopyFlag(vlistID2, vlistID1);
+
+#if defined(HAVE_LIBPTHREAD)
+  pthread_mutex_unlock(&streamMutex);
+#endif
+
 }
 
 
diff --git a/src/pstream.h b/src/pstream.h
index 0851991..0e0b883 100644
--- a/src/pstream.h
+++ b/src/pstream.h
@@ -43,7 +43,9 @@
 
 #define  streamCopyRecord         pstreamCopyRecord
 
-#define  streamInqGinfo           pstreamInqGinfo
+#define  streamInqGRIBinfo        pstreamInqGRIBinfo
+
+#define  vlistCopyFlag            cdoVlistCopyFlag
 
 
 int     pstreamOpenWrite(const argument_t *argument, int filetype);
@@ -68,7 +70,10 @@ void    pstreamWriteRecordF(int pstreamID, float *data, int nmiss);
 void    pstreamReadRecord(int pstreamID, double *data, int *nmiss);
 void    pstreamCopyRecord(int pstreamIDdest, int pstreamIDsrc);
 
-void    pstreamInqGinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum);
+void    pstreamInqGRIBinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum);
+
+void    cdoVlistCopyFlag(int vlistID2, int vlistID1);
+
 
 
 #endif  /* _PSTREAM_H */
diff --git a/src/pthread_debug.c b/src/pthread_debug.c
index a645597..3755bf6 100644
--- a/src/pthread_debug.c
+++ b/src/pthread_debug.c
@@ -132,11 +132,11 @@ int Pthread_create(const char *caller, pthread_t *th,
 {
   int status;
 
-  if ( PTHREAD_Debug ) Message("+%s", __func__);
+  if ( PTHREAD_Debug ) Message("%s", caller);
 
   if ( PTHREAD_Debug )
     {
-      Message("+%s attributes:", __func__);
+      Message("%s attributes:", caller);
       if ( attr )
 	print_pthread_attr(__func__, attr);
       else
@@ -145,7 +145,7 @@ int Pthread_create(const char *caller, pthread_t *th,
 
   status = pthread_create(th, attr, start_routine, arg);
 
-  //if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", __func__, (long) *th, status);
+  //if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", caller, (long) *th, status);
 
   return (status);
 }
@@ -155,11 +155,11 @@ int Pthread_join(const char *caller, pthread_t th, void **thread_return)
 {
   int status;
 
-  //  if ( PTHREAD_Debug ) Message("+%s (thID = %ld)", __func__, (void *) th);
+  //  if ( PTHREAD_Debug ) Message("+%s (thID = %ld)", caller, (void *) th);
 
   status = pthread_join(th, thread_return);
 
-  // if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", __func__, (void *) th, status);
+  // if ( PTHREAD_Debug ) Message("-%s (thID = %ld, status = %d)", caller, (void *) th, status);
 
   return (status);
 }
@@ -169,7 +169,7 @@ void Pthread_mutex_lock(const char *caller, pthread_mutex_t *mutex)
 {
   int status;
 
-  if ( PTHREAD_Debug ) Message("+%s (mutex = %p)", __func__, (void *) mutex);
+  if ( PTHREAD_Debug ) Message("%s (mutex = %p)", caller, (void *) mutex);
 
   status = pthread_mutex_lock(mutex);
   if ( status != 0 )
@@ -187,8 +187,6 @@ void Pthread_mutex_lock(const char *caller, pthread_mutex_t *mutex)
 	  break;
 	}
     }
-
-  if ( PTHREAD_Debug ) Message("-%s (mutex = %p)", __func__, (void *) mutex);
 }
 
 
@@ -196,7 +194,7 @@ void Pthread_mutex_unlock(const char *caller, pthread_mutex_t *mutex)
 {
   int status;
 
-  if ( PTHREAD_Debug ) Message("+%s (mutex = %p)", __func__, (void *) mutex);
+  if ( PTHREAD_Debug ) Message("%s (mutex = %p)", caller, (void *) mutex);
 
   status = pthread_mutex_unlock(mutex);
   if ( status != 0 )
@@ -214,30 +212,28 @@ void Pthread_mutex_unlock(const char *caller, pthread_mutex_t *mutex)
 	  break;
 	}
     }
-
-  if ( PTHREAD_Debug ) Message("-%s (mutex = %p)", __func__, (void *) mutex);
 }
 
 
 void Pthread_cond_signal(const char *caller, pthread_cond_t *cond)
 {
-  if ( PTHREAD_Debug ) Message("+%s (cond = %p)", __func__, (void *) cond);
+  if ( PTHREAD_Debug ) Message("+%s (cond = %p)", caller, (void *) cond);
 
   pthread_cond_signal(cond);
 
-  if ( PTHREAD_Debug ) Message("-%s (cond = %p)", __func__, (void *) cond);
+  if ( PTHREAD_Debug ) Message("-%s (cond = %p)", caller, (void *) cond);
 }
 
 
 void Pthread_cond_wait(const char *caller, pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
   if ( PTHREAD_Debug ) Message("+%s (cond = %p, mutex =  %p)",
-			       __func__, (void *) cond, (void *) mutex);
+			       caller, (void *) cond, (void *) mutex);
 
   pthread_cond_wait(cond, mutex);
 
   if ( PTHREAD_Debug ) Message("-%s (cond = %p, mutex = %p)",
-			       __func__, (void *) cond, (void *) mutex);
+			       caller, (void *) cond, (void *) mutex);
 }
 
 #endif
diff --git a/src/remap.h b/src/remap.h
index c1d72f4..0fbdc21 100644
--- a/src/remap.h
+++ b/src/remap.h
@@ -1,10 +1,6 @@
 #ifndef _REMAP_H
 #define _REMAP_H
 
-#if defined(_OPENMP)
-#include <omp.h>
-#endif
-
 #include <math.h>
 
 #ifndef  M_PI
diff --git a/src/remap_bicubic_scrip.c b/src/remap_bicubic_scrip.c
index c34563c..6c250b6 100644
--- a/src/remap_bicubic_scrip.c
+++ b/src/remap_bicubic_scrip.c
@@ -202,11 +202,10 @@ void scrip_remap_weights_bicubic(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
   for ( dst_add = 0; dst_add < tgt_grid_size; ++dst_add )
     {
       int lprogress = 1;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
+
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
-#if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
@@ -336,11 +335,10 @@ void scrip_remap_bicubic(remapgrid_t *src_grid, remapgrid_t *tgt_grid, const dou
   for ( dst_add = 0; dst_add < tgt_grid_size; ++dst_add )
     {
       int lprogress = 1;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
+
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
-#if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
diff --git a/src/remap_bilinear_scrip.c b/src/remap_bilinear_scrip.c
index 43f65bb..9626fdd 100644
--- a/src/remap_bilinear_scrip.c
+++ b/src/remap_bilinear_scrip.c
@@ -278,11 +278,10 @@ void scrip_remap_weights_bilinear(remapgrid_t* src_grid, remapgrid_t* tgt_grid,
   for ( dst_add = 0; dst_add < tgt_grid_size; ++dst_add )
     {
       int lprogress = 1;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
+
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
-#if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
@@ -409,14 +408,12 @@ void scrip_remap_bilinear(remapgrid_t* src_grid, remapgrid_t* tgt_grid, const do
   for ( dst_add = 0; dst_add < tgt_grid_size; ++dst_add )
     {
       int lprogress = 1;
-#if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
 
       if ( !cdoSilentMode )
 	{
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
 	  findex++;
 	  if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
diff --git a/src/remap_conserv.c b/src/remap_conserv.c
index 6cb41c3..04db320 100644
--- a/src/remap_conserv.c
+++ b/src/remap_conserv.c
@@ -5,6 +5,7 @@
 #include "remap_store_link.h"
 
 
+
 /*
     This routine stores the address and weight for this link in the appropriate 
     address and weight arrays and resizes those arrays if necessary.
@@ -277,7 +278,7 @@ void boundbox_from_corners1r(long ic, long nc, const double *restrict corner_lon
       if ( clon > bound_box[3] ) bound_box[3] = clon;
     }
 
-  if ( fabs(bound_box[3] - bound_box[2]) > RESTR_SCALE(PI) )
+  if ( RESTR_ABS(bound_box[3] - bound_box[2]) > RESTR_SCALE(PI) )
     {
       bound_box[2] = 0;
       bound_box[3] = RESTR_SCALE(PI2);
@@ -301,6 +302,15 @@ void boundbox_from_corners1r(long ic, long nc, const double *restrict corner_lon
 #include "clipping/geometry.h"
 
 static
+double gridcell_area(struct grid_cell cell)
+{
+  double area = huiliers_area(cell);
+  area /= (EarthRadius*EarthRadius);
+
+  return (area);
+}
+
+static
 void cdo_compute_overlap_areas(unsigned N,
 			       struct grid_cell *overlap_buffer,
 			       struct grid_cell *source_cells,
@@ -315,7 +325,7 @@ void cdo_compute_overlap_areas(unsigned N,
 
   for ( unsigned n = 0; n < N; n++ )
     {
-      partial_areas[n] = huiliers_area(overlap_buffer[n]);
+      partial_areas[n] = gridcell_area(overlap_buffer[n]);
     }
 
 #ifdef VERBOSE
@@ -323,6 +333,151 @@ void cdo_compute_overlap_areas(unsigned N,
     printf("overlap area : %lf\n", partial_areas[n]);
 #endif
 }
+
+static double const tol = 1.0e-12;
+
+enum cell_type {
+  UNDEF_CELL,
+  LON_LAT_CELL,
+  LAT_CELL,
+  GREAT_CIRCLE_CELL,
+  MIXED_CELL
+};
+/*
+static enum cell_type get_cell_type(struct grid_cell target_cell) {
+
+  int count_lat_edges = 0, count_great_circle_edges = 0;
+
+   if ((target_cell.num_corners == 4) &&
+       ((target_cell.edge_type[0] == LAT_CIRCLE &&
+         target_cell.edge_type[1] == LON_CIRCLE &&
+         target_cell.edge_type[2] == LAT_CIRCLE &&
+         target_cell.edge_type[3] == LON_CIRCLE) ||
+        (target_cell.edge_type[0] == LON_CIRCLE &&
+         target_cell.edge_type[1] == LAT_CIRCLE &&
+         target_cell.edge_type[2] == LON_CIRCLE &&
+         target_cell.edge_type[3] == LAT_CIRCLE)))
+      return LON_LAT_CELL;
+   else
+      for (unsigned i = 0; i < target_cell.num_corners; ++i)
+         if (target_cell.edge_type[i] == LON_CIRCLE ||
+             target_cell.edge_type[i] == GREAT_CIRCLE)
+            count_great_circle_edges++;
+         else
+            count_lat_edges++;
+
+   if (count_lat_edges && count_great_circle_edges)
+      return MIXED_CELL;
+   else if (count_lat_edges)
+      return LAT_CELL;
+   else
+      return GREAT_CIRCLE_CELL;
+}
+*/
+static
+void cdo_compute_concave_overlap_areas(unsigned N,
+				       struct grid_cell *overlap_buffer,
+				       struct grid_cell *source_cell,
+				       struct grid_cell  target_cell,
+				       double target_node_x,
+				       double target_node_y,
+				       double * partial_areas)
+{
+  /*
+  enum cell_type target_cell_type = UNDEF_CELL;
+
+  if ( target_cell.num_corners > 3 )
+    target_cell_type = get_cell_type(target_cell);
+
+  if ( target_cell.num_corners < 4 || target_cell_type == LON_LAT_CELL )
+    {
+      cdo_compute_overlap_areas(N, overlap_buffer, source_cell, target_cell, partial_areas);
+      return;
+    }
+
+  if ( target_node_x == NULL || target_node_y == NULL )
+    cdoAbort("Internal problem (cdo_compute_concave_overlap_areas): missing target point coordinates!");
+  */
+  struct grid_cell target_partial_cell =
+    {.coordinates_x   = (double[3]){-1, -1, -1},
+     .coordinates_y   = (double[3]){-1, -1, -1},
+     .coordinates_xyz = (double[3*3]){-1, -1, -1},
+     .edge_type       = (enum edge_type[3]) {GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE},
+     .num_corners     = 3};
+
+  /* Do the clipping and get the cell for the overlapping area */
+
+  for ( unsigned n = 0; n < N; n++) partial_areas[n] = 0.0;
+
+  // common node point to all partial target cells
+  target_partial_cell.coordinates_x[0] = target_node_x;
+  target_partial_cell.coordinates_y[0] = target_node_y;
+
+  LLtoXYZ ( target_node_x, target_node_y, target_partial_cell.coordinates_xyz );
+
+  for ( unsigned num_corners = 0; num_corners < target_cell.num_corners; ++num_corners )
+    {
+      unsigned corner_a = num_corners;
+      unsigned corner_b = (num_corners+1)%target_cell.num_corners;
+
+      // skip clipping and area calculation for degenerated triangles
+      //
+      // If this is not sufficient, instead we can try something like:
+      //
+      //     struct point_list target_list
+      //     init_point_list(&target_list);
+      //     generate_point_list(&target_list, target_cell);
+      //     struct grid_cell temp_target_cell;
+      //     generate_overlap_cell(target_list, temp_target_cell);
+      //     free_point_list(&target_list);
+      //
+      // and use temp_target_cell for triangulation.
+      //
+      // Compared to the if statement below the alternative seems
+      // to be quite costly.
+
+      if ( ( ( fabs(target_cell.coordinates_xyz[0+3*corner_a]-target_cell.coordinates_xyz[0+3*corner_b]) < tol ) &&
+	     ( fabs(target_cell.coordinates_xyz[1+3*corner_a]-target_cell.coordinates_xyz[1+3*corner_b]) < tol ) &&
+	     ( fabs(target_cell.coordinates_xyz[2+3*corner_a]-target_cell.coordinates_xyz[2+3*corner_b]) < tol ) ) ||
+	   ( ( fabs(target_cell.coordinates_xyz[0+3*corner_a]-target_partial_cell.coordinates_xyz[0]) < tol    ) &&
+	     ( fabs(target_cell.coordinates_xyz[1+3*corner_a]-target_partial_cell.coordinates_xyz[1]) < tol    ) &&
+	     ( fabs(target_cell.coordinates_xyz[2+3*corner_a]-target_partial_cell.coordinates_xyz[2]) < tol    ) ) ||
+	   ( ( fabs(target_cell.coordinates_xyz[0+3*corner_b]-target_partial_cell.coordinates_xyz[0]) < tol    ) &&
+	     ( fabs(target_cell.coordinates_xyz[1+3*corner_b]-target_partial_cell.coordinates_xyz[1]) < tol    ) &&
+	     ( fabs(target_cell.coordinates_xyz[2+3*corner_b]-target_partial_cell.coordinates_xyz[2]) < tol    ) ) )
+	continue;
+
+      target_partial_cell.coordinates_x[1] = target_cell.coordinates_x[corner_a];
+      target_partial_cell.coordinates_y[1] = target_cell.coordinates_y[corner_a];
+      target_partial_cell.coordinates_x[2] = target_cell.coordinates_x[corner_b];
+      target_partial_cell.coordinates_y[2] = target_cell.coordinates_y[corner_b];
+
+      target_partial_cell.coordinates_xyz[0+3*1] = target_cell.coordinates_xyz[0+3*corner_a];
+      target_partial_cell.coordinates_xyz[1+3*1] = target_cell.coordinates_xyz[1+3*corner_a];
+      target_partial_cell.coordinates_xyz[2+3*1] = target_cell.coordinates_xyz[2+3*corner_a];
+      target_partial_cell.coordinates_xyz[0+3*2] = target_cell.coordinates_xyz[0+3*corner_b];
+      target_partial_cell.coordinates_xyz[1+3*2] = target_cell.coordinates_xyz[1+3*corner_b];
+      target_partial_cell.coordinates_xyz[2+3*2] = target_cell.coordinates_xyz[2+3*corner_b];
+
+      cell_clipping(N, source_cell, target_partial_cell, overlap_buffer);
+
+      /* Get the partial areas for the overlapping regions as sum over the partial target cells. */
+
+      for (unsigned n = 0; n < N; n++)
+	{
+	  partial_areas[n] += gridcell_area(overlap_buffer[n]);
+	  // we cannot use pole_area because it is rather inaccurate for great circle
+	  // edges that are nearly circles of longitude
+	  //partial_areas[n] = pole_area (overlap_buffer[n]);
+	}
+    }
+
+#ifdef VERBOSE
+  for (unsigned n = 0; n < N; n++)
+    printf("overlap area %i: %lf \n", n, partial_areas[n]);
+#endif
+}
+
 //#endif
 
 static
@@ -373,10 +528,70 @@ int get_lonlat_circle_index(remapgrid_t *remap_grid)
 
   //printf("lonlat_circle_index %d\n", lonlat_circle_index);
 
-  return(lonlat_circle_index);
+  return (lonlat_circle_index);
 }
 
 
+
+static
+void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv)
+{
+  /* Include centroids in weights and normalize using destination area if requested */
+  long n;
+  long num_wts = rv->num_wts;
+  long num_links = rv->num_links;
+  long tgt_grid_add;       /* current linear address for target grid cell   */
+  double norm_factor = 0;  /* factor for normalizing wts */
+
+  if ( rv->norm_opt == NORM_OPT_DESTAREA )
+    {
+#if defined(SX)
+#pragma vdir nodep
+#endif
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+  shared(num_wts, num_links, rv, tgt_grid)	\
+  private(n, tgt_grid_add, norm_factor)
+#endif
+      for ( n = 0; n < num_links; ++n )
+	{
+	  tgt_grid_add = rv->tgt_grid_add[n];
+
+          if ( IS_NOT_EQUAL(tgt_grid->cell_area[tgt_grid_add], 0) )
+	    norm_factor = ONE/tgt_grid->cell_area[tgt_grid_add];
+          else
+            norm_factor = ZERO;
+
+	  rv->wts[n*num_wts] *= norm_factor;
+	}
+    }
+  else if ( rv->norm_opt == NORM_OPT_FRACAREA )
+    {
+#if defined(SX)
+#pragma vdir nodep
+#endif
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+  shared(num_wts, num_links, rv, tgt_grid)	\
+  private(n, tgt_grid_add, norm_factor)
+#endif
+      for ( n = 0; n < num_links; ++n )
+	{
+	  tgt_grid_add = rv->tgt_grid_add[n];
+
+          if ( IS_NOT_EQUAL(tgt_grid->cell_frac[tgt_grid_add], 0) )
+	    norm_factor = ONE/tgt_grid->cell_frac[tgt_grid_add];
+          else
+            norm_factor = ZERO;
+
+	  rv->wts[n*num_wts] *= norm_factor;
+	}
+    }
+  else if ( rv->norm_opt == NORM_OPT_NONE )
+    {
+    }
+}
+
 void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapvars_t *rv)
 {
   /* local variables */
@@ -396,9 +611,8 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
   long   max_srch_cells;     /* num cells in restricted search arrays  */
   long   num_srch_cells;     /* num cells in restricted search arrays  */
   long   srch_corners;       /* num of corners of srch cells           */
-  double norm_factor = 0;    /* factor for normalizing wts */
   int*   srch_add;           /* global address of cells in srch arrays */
-  int    ompthID, i;
+  int    i;
 
   /* Variables necessary if segment manages to hit pole */
   double findex = 0;
@@ -425,12 +639,19 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
   src_num_cell_corners = src_grid->num_cell_corners;
   tgt_num_cell_corners = tgt_grid->num_cell_corners;
 
-  enum edge_type great_circle_type[] = {GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE, GREAT_CIRCLE};
-  enum edge_type lonlat_circle_type[] = {LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE};
+  int max_num_cell_corners = src_num_cell_corners;
+  if ( tgt_num_cell_corners > max_num_cell_corners ) max_num_cell_corners = tgt_num_cell_corners;
+
+  enum edge_type great_circle_type[32];
+  for ( int i = 0; i < max_num_cell_corners; ++i ) great_circle_type[i] = GREAT_CIRCLE;
+
+  enum edge_type lonlat_circle_type[] = {LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE};
 
   enum edge_type *src_edge_type = great_circle_type;
   enum edge_type *tgt_edge_type = great_circle_type;
 
+  enum cell_type target_cell_type = UNDEF_CELL;
+
   if ( src_num_cell_corners == 4 )
     {
       int lonlat_circle_index = get_lonlat_circle_index(src_grid);
@@ -440,7 +661,17 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
   if ( tgt_num_cell_corners == 4 )
     {
       int lonlat_circle_index = get_lonlat_circle_index(tgt_grid);
-      if ( lonlat_circle_index >= 0 ) tgt_edge_type = &lonlat_circle_type[lonlat_circle_index];
+      if ( lonlat_circle_index >= 0 )
+	{
+	  target_cell_type = LON_LAT_CELL;
+	  tgt_edge_type = &lonlat_circle_type[lonlat_circle_index];
+	}
+    }
+
+  if ( !(tgt_num_cell_corners < 4 || target_cell_type == LON_LAT_CELL) )
+    {
+      if ( tgt_grid->cell_center_lon == NULL || tgt_grid->cell_center_lat == NULL )
+	cdoAbort("Internal problem (remap_weights_conserv): missing target point coordinates!");
     }
 
   double tgt_area;
@@ -514,25 +745,20 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 #pragma omp parallel for default(none) \
   shared(ompNumThreads, cdoTimer, lyac, nbins, num_wts, nx, src_remap_grid_type, tgt_remap_grid_type, src_grid_bound_box,	\
 	 src_edge_type, tgt_edge_type, partial_areas2, partial_weights2,  \
-         rv, cdoVerbose, max_srch_cells2, \
-	 tgt_num_cell_corners, srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, \
+         rv, cdoVerbose, max_srch_cells2, tgt_num_cell_corners, target_cell_type, \
+	 srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, \
 	 overlap_buffer2, src_grid_cells2, srch_add2, tgt_grid_cell2, findex, sum_srch_cells, sum_srch_cells2) \
-  private(ompthID, srch_add, tgt_grid_cell, tgt_area, n, k, num_weights, num_srch_cells, max_srch_cells,  \
+  private(srch_add, tgt_grid_cell, tgt_area, n, k, num_weights, num_srch_cells, max_srch_cells,  \
 	  partial_areas, partial_weights, overlap_buffer, src_grid_cells, src_grid_add, tgt_grid_add, ioffset)
 #endif
   for ( tgt_grid_add = 0; tgt_grid_add < tgt_grid_size; ++tgt_grid_add )
     {
-#if defined(_OPENMP)
-      ompthID = omp_get_thread_num();
-#else
-      ompthID = 0;
-#endif
-
+      int ompthID = cdo_omp_get_thread_num();
       int lprogress = 1;
       if ( ompthID != 0 ) lprogress = 0;
 
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
@@ -547,22 +773,30 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 	  double tgt_cell_bound_box[4];
 	  boundbox_from_corners_reg2d(tgt_grid_add, tgt_grid->dims, tgt_grid->reg2d_corner_lon, tgt_grid->reg2d_corner_lat, tgt_cell_bound_box);
 	  restrict_boundbox(src_grid_bound_box, tgt_cell_bound_box);
-	  if ( cdoVerbose )
+	  if ( 0 && cdoVerbose )
 	    printf("bound_box %ld  lon: %g %g lat: %g %g\n",
 		   tgt_grid_add, RAD2DEG*tgt_cell_bound_box[2],RAD2DEG*tgt_cell_bound_box[3],RAD2DEG*tgt_cell_bound_box[0],RAD2DEG*tgt_cell_bound_box[1] );
 	  num_srch_cells = get_srch_cells_reg2d(src_grid->dims, src_grid->reg2d_corner_lat, src_grid->reg2d_corner_lon,
 						tgt_cell_bound_box, srch_add);
+
+	  if ( num_srch_cells == 1 && src_grid->dims[0] == 1 && src_grid->dims[1] == 1 &&
+	       IS_EQUAL(src_grid->reg2d_corner_lat[0], src_grid->reg2d_corner_lat[1]) && 
+	       IS_EQUAL(src_grid->reg2d_corner_lon[0], src_grid->reg2d_corner_lon[1]) ) num_srch_cells = 0;
 	}
       else if ( src_remap_grid_type == REMAP_GRID_TYPE_REG2D )
 	{
 	  double tgt_cell_bound_box[4];
 	  boundbox_from_corners1(tgt_grid_add, tgt_num_cell_corners, tgt_grid->cell_corner_lon, tgt_grid->cell_corner_lat, tgt_cell_bound_box);
 	  restrict_boundbox(src_grid_bound_box, tgt_cell_bound_box);
-	  if ( cdoVerbose )
+	  if ( 0 && cdoVerbose )
 	    printf("bound_box %ld  lon: %g %g lat: %g %g\n",
 		   tgt_grid_add, RAD2DEG*tgt_cell_bound_box[2],RAD2DEG*tgt_cell_bound_box[3],RAD2DEG*tgt_cell_bound_box[0],RAD2DEG*tgt_cell_bound_box[1] );
 	  num_srch_cells = get_srch_cells_reg2d(src_grid->dims, src_grid->reg2d_corner_lat, src_grid->reg2d_corner_lon,
 						tgt_cell_bound_box, srch_add);
+
+	  if ( num_srch_cells == 1 && src_grid->dims[0] == 1 && src_grid->dims[1] == 1 &&
+	       IS_EQUAL(src_grid->reg2d_corner_lat[0], src_grid->reg2d_corner_lat[1]) && 
+	       IS_EQUAL(src_grid->reg2d_corner_lon[0], src_grid->reg2d_corner_lon[1]) ) num_srch_cells = 0;
 	}
       else
 	{
@@ -575,7 +809,7 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 
       sum_srch_cells += num_srch_cells;
 
-      if ( cdoVerbose )
+      if ( 0 && cdoVerbose )
 	printf("tgt_grid_add %ld  num_srch_cells %ld\n", tgt_grid_add, num_srch_cells);
 
       if ( num_srch_cells == 0 ) continue;
@@ -737,9 +971,18 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 	    }
 	}
 
-      cdo_compute_overlap_areas(num_srch_cells, overlap_buffer, src_grid_cells, *tgt_grid_cell, partial_areas);
+      if ( tgt_num_cell_corners < 4 || target_cell_type == LON_LAT_CELL )
+	{
+	  cdo_compute_overlap_areas(num_srch_cells, overlap_buffer, src_grid_cells, *tgt_grid_cell, partial_areas);
+	}
+      else
+	{
+	  double cell_center_lon = tgt_grid->cell_center_lon[tgt_grid_add];
+	  double cell_center_lat = tgt_grid->cell_center_lat[tgt_grid_add];
+	  cdo_compute_concave_overlap_areas(num_srch_cells, overlap_buffer, src_grid_cells, *tgt_grid_cell, cell_center_lon, cell_center_lat, partial_areas);
+	}
 
-      tgt_area = huiliers_area(*tgt_grid_cell);
+      tgt_area = gridcell_area(*tgt_grid_cell);
       // tgt_area = cell_area(tgt_grid_cell);
 
       for ( num_weights = 0, n = 0; n < num_srch_cells; ++n )
@@ -759,13 +1002,16 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 	partial_weights[n] = partial_areas[n] / tgt_area;
 
       correct_weights(num_weights, partial_weights);
+
+      for ( n = 0; n < num_weights; ++n )
+	partial_weights[n] *= tgt_area;
       //#endif
 
       for ( n = 0; n < num_weights; ++n )
 	{
 	  src_grid_add = srch_add[n];
 
-	  if ( cdoVerbose )
+	  if ( 0 && cdoVerbose )
 	    printf("tgt_grid_add %ld, src_grid_add %ld,  partial_weights[n] %g, tgt_area  %g\n", tgt_grid_add, src_grid_add, partial_weights[n], tgt_area);
 
 	  // src_grid_add = n;
@@ -798,13 +1044,13 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
 		src_grid->cell_area[src_grid_add] += partial_weights[n];
 	      }
 	    }
-
-	  tgt_grid->cell_area[tgt_grid_add] += partial_weights[n];
 	}
+      
+      tgt_grid->cell_area[tgt_grid_add] = tgt_area; 
       // printf("area %d %g %g\n", tgt_grid_add, tgt_grid->cell_area[tgt_grid_add], tgt_area);
     }
 
-  if ( cdoVerbose )
+  if ( 0 && cdoVerbose )
     {
       printf("sum_srch_cells : %d\n", sum_srch_cells);
       printf("sum_srch_cells2: %d\n", sum_srch_cells2);
@@ -844,57 +1090,10 @@ void remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
     }
 
   /* Normalize using destination area if requested */
+  normalize_weights(tgt_grid, rv);
 
   num_links = rv->num_links;
 
-  if ( rv->norm_opt == NORM_OPT_DESTAREA )
-    {
-#if defined(SX)
-#pragma vdir nodep
-#endif
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) \
-  shared(num_wts, num_links, rv, tgt_grid)	\
-  private(n, tgt_grid_add, norm_factor)
-#endif
-      for ( n = 0; n < num_links; ++n )
-	{
-	  tgt_grid_add = rv->tgt_grid_add[n];
-
-          if ( IS_NOT_EQUAL(tgt_grid->cell_area[tgt_grid_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_area[tgt_grid_add];
-          else
-            norm_factor = ZERO;
-
-	  rv->wts[n*num_wts] *= norm_factor;
-	}
-    }
-  else if ( rv->norm_opt == NORM_OPT_FRACAREA )
-    {
-#if defined(SX)
-#pragma vdir nodep
-#endif
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) \
-  shared(num_wts, num_links, rv, tgt_grid)	\
-  private(n, tgt_grid_add, norm_factor)
-#endif
-      for ( n = 0; n < num_links; ++n )
-	{
-	  tgt_grid_add = rv->tgt_grid_add[n];
-
-          if ( IS_NOT_EQUAL(tgt_grid->cell_frac[tgt_grid_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_frac[tgt_grid_add];
-          else
-            norm_factor = ZERO;
-
-	  rv->wts[n*num_wts] *= norm_factor;
-	}
-    }
-  else if ( rv->norm_opt == NORM_OPT_NONE )
-    {
-    }
-
   if ( cdoVerbose )
     cdoPrint("Total number of links = %ld", rv->num_links);
   
diff --git a/src/remap_conserv_scrip.c b/src/remap_conserv_scrip.c
index 1802932..3a7018d 100644
--- a/src/remap_conserv_scrip.c
+++ b/src/remap_conserv_scrip.c
@@ -988,6 +988,228 @@ void line_integral(double *weights, double in_phi1, double in_phi2,
 
 }  /* line_integral */
 
+static
+void correct_pole(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapvars_t *rv,
+		  double *src_centroid_lat, double *src_centroid_lon,
+		  double *tgt_centroid_lat, double *tgt_centroid_lon,
+		  grid_store_t *grid_store, int *link_add1[2], int *link_add2[2])
+{
+  /*
+     Correct for situations where N/S pole not explicitly included in
+     grid (i.e. as a grid corner point). If pole is missing from only
+     one grid, need to correct only the area and centroid of that 
+     grid.  If missing from both, do complete weight calculation.
+  */
+  long n;
+  long num_wts;
+  long src_grid_size;
+  long tgt_grid_size;
+  long src_grid_add;       /* current linear address for source grid cell   */
+  long tgt_grid_add;       /* current linear address for target grid cell   */
+  double weights[6];       /* local wgt array */
+
+  num_wts = rv->num_wts;
+
+  src_grid_size = src_grid->size;
+  tgt_grid_size = tgt_grid->size;
+
+  /* North Pole */
+  weights[0] =  PI2;
+  weights[1] =  PI*PI;
+  weights[2] =  ZERO;
+  weights[3] =  PI2;
+  weights[4] =  PI*PI;
+  weights[5] =  ZERO;
+
+  src_grid_add = -1;
+  /* pole_loop1 */
+  for ( n = 0; n < src_grid_size; ++n )
+    if ( src_grid->cell_area[n] < -THREE*PIH && src_grid->cell_center_lat[n] > ZERO )
+      {
+	src_grid_add = n;
+#ifndef SX
+	break;
+#endif
+      }
+
+  tgt_grid_add = -1;
+  /* pole_loop2 */
+  for ( n = 0; n < tgt_grid_size; ++n )
+    if ( tgt_grid->cell_area[n] < -THREE*PIH && tgt_grid->cell_center_lat[n] > ZERO )
+      {
+	tgt_grid_add = n;
+#ifndef SX
+	break;
+#endif
+      }
+
+  if ( src_grid_add != -1 )
+    {
+      src_grid->cell_area[src_grid_add] += weights[0];
+      src_centroid_lat[src_grid_add]    += weights[1];
+      src_centroid_lon[src_grid_add]    += weights[2];
+    }
+
+  if ( tgt_grid_add != -1 )
+    {
+      tgt_grid->cell_area[tgt_grid_add] += weights[3];
+      tgt_centroid_lat[tgt_grid_add]    += weights[4];
+      tgt_centroid_lon[tgt_grid_add]    += weights[5];
+    }
+
+  if ( src_grid_add != -1 && tgt_grid_add != -1 )
+    {
+      if ( remap_store_link_fast )
+	store_link_cnsrv_fast(rv, src_grid_add, tgt_grid_add, num_wts, weights, grid_store);
+      else
+	store_link_cnsrv(rv, src_grid_add, tgt_grid_add, weights, link_add1, link_add2);
+
+      src_grid->cell_frac[src_grid_add] += weights[0];
+      tgt_grid->cell_frac[tgt_grid_add] += weights[3];
+    }
+
+  /* South Pole */
+  weights[0] =  PI2;
+  weights[1] = -PI*PI;
+  weights[2] =  ZERO;
+  weights[3] =  PI2;
+  weights[4] = -PI*PI;
+  weights[5] =  ZERO;
+
+  src_grid_add = -1;
+  /* pole_loop3 */
+  for ( n = 0; n < src_grid_size; ++n )
+    if ( src_grid->cell_area[n] < -THREE*PIH && src_grid->cell_center_lat[n] < ZERO )
+      {
+	src_grid_add = n;
+#ifndef SX
+	break;
+#endif
+      }
+
+  tgt_grid_add = -1;
+  /* pole_loop4 */
+  for ( n = 0; n < tgt_grid_size; ++n )
+    if ( tgt_grid->cell_area[n] < -THREE*PIH && tgt_grid->cell_center_lat[n] < ZERO )
+      {
+	tgt_grid_add = n;
+#ifndef SX
+	break;
+#endif
+      }
+
+  if ( src_grid_add != -1 )
+    {
+      src_grid->cell_area[src_grid_add] += weights[0];
+      src_centroid_lat[src_grid_add]    += weights[1];
+      src_centroid_lon[src_grid_add]    += weights[2];
+    }
+
+  if ( tgt_grid_add != -1 )
+    {
+      tgt_grid->cell_area[tgt_grid_add] += weights[3];
+      tgt_centroid_lat[tgt_grid_add]    += weights[4];
+      tgt_centroid_lon[tgt_grid_add]    += weights[5];
+    }
+
+  if ( src_grid_add != -1 && tgt_grid_add != -1 )
+    {
+      if ( remap_store_link_fast )
+	store_link_cnsrv_fast(rv, src_grid_add, tgt_grid_add, num_wts, weights, grid_store);
+      else
+	store_link_cnsrv(rv, src_grid_add, tgt_grid_add, weights, link_add1, link_add2);
+
+      src_grid->cell_frac[src_grid_add] += weights[0];
+      tgt_grid->cell_frac[tgt_grid_add] += weights[3];
+    }
+}
+
+static
+void norm_weight(double norm_factor, double *weights, double src_centroid_lat, double src_centroid_lon)
+{
+  double weight0 = weights[0];
+
+  weights[0] =  weight0*norm_factor;
+  weights[1] = (weights[1] - weight0*src_centroid_lat)*norm_factor;
+  weights[2] = (weights[2] - weight0*src_centroid_lon)*norm_factor;
+}
+
+static
+void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv, double *src_centroid_lat, double *src_centroid_lon)
+{
+  /* Include centroids in weights and normalize using destination area if requested */
+  long n;
+  long num_links = rv->num_links;
+  long src_grid_add;       /* current linear address for source grid cell   */
+  long tgt_grid_add;       /* current linear address for target grid cell   */
+  double *weights = rv->wts;
+  double norm_factor = 0;  /* factor for normalizing wts */
+
+  if ( rv->norm_opt == NORM_OPT_DESTAREA )
+    {
+#if defined(SX)
+#pragma vdir nodep
+#endif
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+  shared(num_links, rv, weights, tgt_grid, src_centroid_lat, src_centroid_lon)		\
+  private(n, src_grid_add, tgt_grid_add, norm_factor)
+#endif
+      for ( n = 0; n < num_links; ++n )
+	{
+	  src_grid_add = rv->src_grid_add[n]; tgt_grid_add = rv->tgt_grid_add[n];
+
+          if ( IS_NOT_EQUAL(tgt_grid->cell_area[tgt_grid_add], 0) )
+	    norm_factor = ONE/tgt_grid->cell_area[tgt_grid_add];
+          else
+            norm_factor = ZERO;
+
+	  norm_weight(norm_factor, &weights[n*3], src_centroid_lat[src_grid_add], src_centroid_lon[src_grid_add]);
+	}
+    }
+  else if ( rv->norm_opt == NORM_OPT_FRACAREA )
+    {
+#if defined(SX)
+#pragma vdir nodep
+#endif
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+  shared(num_links, rv, weights, tgt_grid, src_centroid_lat, src_centroid_lon)		\
+  private(n, src_grid_add, tgt_grid_add, norm_factor)
+#endif
+      for ( n = 0; n < num_links; ++n )
+	{
+	  src_grid_add = rv->src_grid_add[n]; tgt_grid_add = rv->tgt_grid_add[n];
+
+          if ( IS_NOT_EQUAL(tgt_grid->cell_frac[tgt_grid_add], 0) )
+	    norm_factor = ONE/tgt_grid->cell_frac[tgt_grid_add];
+          else
+            norm_factor = ZERO;
+
+	  norm_weight(norm_factor, &weights[n*3], src_centroid_lat[src_grid_add], src_centroid_lon[src_grid_add]);
+	}
+    }
+  else if ( rv->norm_opt == NORM_OPT_NONE )
+    {
+#if defined(SX)
+#pragma vdir nodep
+#endif
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+  shared(num_links, rv, weights, tgt_grid, src_centroid_lat, src_centroid_lon)	\
+  private(n, src_grid_add, norm_factor)
+#endif
+      for ( n = 0; n < num_links; ++n )
+	{
+	  src_grid_add = rv->src_grid_add[n];;
+
+          norm_factor = ONE;
+
+	  norm_weight(norm_factor, &weights[n*3], src_centroid_lat[src_grid_add], src_centroid_lon[src_grid_add]);
+	}
+    }
+}
+
 /*
   -----------------------------------------------------------------------
 
@@ -1012,7 +1234,7 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
   long tgt_num_cell_corners;
   long src_grid_add;       /* current linear address for source grid cell   */
   long tgt_grid_add;       /* current linear address for target grid cell   */
-  long n, n3, k;        /* generic counters                        */
+  long n, k;            /* generic counters                        */
   long corner;          /* corner of cell that segment starts from */
   long next_corn;       /* corner of cell that segment ends on     */
   long nbins, num_links;
@@ -1039,7 +1261,7 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
   long    nsrch_corners;
   int*    srch_add;         /* global address of cells in srch arrays */
   int*    srch_add2[ompNumThreads];
-  int     ompthID, i;
+  int     i;
   double *srch_corner_lat;  /* lat of each corner of srch cells */
   double *srch_corner_lon;  /* lon of each corner of srch cells */
 
@@ -1162,7 +1384,7 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
          remap_store_link_fast, grid_store, link_add1, link_add2, rv, cdoVerbose, max_subseg, \
 	 srch_corner_lat2, srch_corner_lon2, max_srch_cells2, 		\
 	 src_num_cell_corners,	srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, srch_add2, findex) \
-  private(ompthID, srch_add, n, k, num_srch_cells, max_srch_cells, 	\
+  private(srch_add, n, k, num_srch_cells, max_srch_cells, 	\
 	  src_grid_add, tgt_grid_add, ioffset, nsrch_corners, corner, next_corn, beglat, beglon, \
 	  endlat, endlon, lrevers, begseg, lbegin, num_subseg, srch_corner_lat, srch_corner_lon, \
 	  weights, intrsct_lat, intrsct_lon, intrsct_lat_off, intrsct_lon_off, intrsct_x, intrsct_y, \
@@ -1170,17 +1392,12 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
 #endif
   for ( src_grid_add = 0; src_grid_add < src_grid_size; ++src_grid_add )
     {
-#if defined(_OPENMP)
-      ompthID = omp_get_thread_num();
-#else
-      ompthID = 0;
-#endif
-
+      int ompthID = cdo_omp_get_thread_num();
       int lprogress = 1;
       if ( ompthID != 0 ) lprogress = 0;
 
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 0.5, findex/src_grid_size);
@@ -1392,7 +1609,7 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
          remap_store_link_fast, grid_store, link_add1, link_add2, rv, cdoVerbose, max_subseg, \
 	 srch_corner_lat2, srch_corner_lon2, max_srch_cells2, 		\
 	 tgt_num_cell_corners, srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, srch_add2, findex) \
-  private(ompthID, srch_add, n, k, num_srch_cells, max_srch_cells,	\
+  private(srch_add, n, k, num_srch_cells, max_srch_cells,	\
 	  src_grid_add, tgt_grid_add, ioffset, nsrch_corners, corner, next_corn, beglat, beglon, \
 	  endlat, endlon, lrevers, begseg, lbegin, num_subseg, srch_corner_lat, srch_corner_lon, \
 	  weights, intrsct_lat, intrsct_lon, intrsct_lat_off, intrsct_lon_off, intrsct_x, intrsct_y, \
@@ -1400,17 +1617,12 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
 #endif
   for ( tgt_grid_add = 0; tgt_grid_add < tgt_grid_size; ++tgt_grid_add )
     {
-#if defined(_OPENMP)
-      ompthID = omp_get_thread_num();
-#else
-      ompthID = 0;
-#endif
-
+      int ompthID = cdo_omp_get_thread_num();
       int lprogress = 1;
       if ( ompthID != 0 ) lprogress = 0;
 
 #if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0.5, 0.5, findex/tgt_grid_size);
@@ -1602,116 +1814,11 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
      one grid, need to correct only the area and centroid of that 
      grid.  If missing from both, do complete weight calculation.
   */
+  correct_pole(src_grid, tgt_grid, rv,
+	       src_centroid_lat, src_centroid_lon,
+	       tgt_centroid_lat, tgt_centroid_lon,
+	       grid_store, link_add1, link_add2);
 
-  /* North Pole */
-  weights[0] =  PI2;
-  weights[1] =  PI*PI;
-  weights[2] =  ZERO;
-  weights[3] =  PI2;
-  weights[4] =  PI*PI;
-  weights[5] =  ZERO;
-
-  src_grid_add = -1;
-  /* pole_loop1 */
-  for ( n = 0; n < src_grid_size; ++n )
-    if ( src_grid->cell_area[n] < -THREE*PIH && src_grid->cell_center_lat[n] > ZERO )
-      {
-	src_grid_add = n;
-#ifndef SX
-	break;
-#endif
-      }
-
-  tgt_grid_add = -1;
-  /* pole_loop2 */
-  for ( n = 0; n < tgt_grid_size; ++n )
-    if ( tgt_grid->cell_area[n] < -THREE*PIH && tgt_grid->cell_center_lat[n] > ZERO )
-      {
-	tgt_grid_add = n;
-#ifndef SX
-	break;
-#endif
-      }
-
-  if ( src_grid_add != -1 )
-    {
-      src_grid->cell_area[src_grid_add]     += weights[0];
-      src_centroid_lat[src_grid_add] += weights[1];
-      src_centroid_lon[src_grid_add] += weights[2];
-    }
-
-  if ( tgt_grid_add != -1 )
-    {
-      tgt_grid->cell_area[tgt_grid_add]     += weights[3];
-      tgt_centroid_lat[tgt_grid_add] += weights[4];
-      tgt_centroid_lon[tgt_grid_add] += weights[5];
-    }
-
-  if ( src_grid_add != -1 && tgt_grid_add != -1 )
-    {
-      if ( remap_store_link_fast )
-	store_link_cnsrv_fast(rv, src_grid_add, tgt_grid_add, num_wts, weights, grid_store);
-      else
-	store_link_cnsrv(rv, src_grid_add, tgt_grid_add, weights, link_add1, link_add2);
-
-      src_grid->cell_frac[src_grid_add] += weights[0];
-      tgt_grid->cell_frac[tgt_grid_add] += weights[3];
-    }
-
-  /* South Pole */
-  weights[0] =  PI2;
-  weights[1] = -PI*PI;
-  weights[2] =  ZERO;
-  weights[3] =  PI2;
-  weights[4] = -PI*PI;
-  weights[5] =  ZERO;
-
-  src_grid_add = -1;
-  /* pole_loop3 */
-  for ( n = 0; n < src_grid_size; ++n )
-    if ( src_grid->cell_area[n] < -THREE*PIH && src_grid->cell_center_lat[n] < ZERO )
-      {
-	src_grid_add = n;
-#ifndef SX
-	break;
-#endif
-      }
-
-  tgt_grid_add = -1;
-  /* pole_loop4 */
-  for ( n = 0; n < tgt_grid_size; ++n )
-    if ( tgt_grid->cell_area[n] < -THREE*PIH && tgt_grid->cell_center_lat[n] < ZERO )
-      {
-	tgt_grid_add = n;
-#ifndef SX
-	break;
-#endif
-      }
-
-  if ( src_grid_add != -1 )
-    {
-      src_grid->cell_area[src_grid_add]     += weights[0];
-      src_centroid_lat[src_grid_add] += weights[1];
-      src_centroid_lon[src_grid_add] += weights[2];
-    }
-
-  if ( tgt_grid_add != -1 )
-    {
-      tgt_grid->cell_area[tgt_grid_add]     += weights[3];
-      tgt_centroid_lat[tgt_grid_add] += weights[4];
-      tgt_centroid_lon[tgt_grid_add] += weights[5];
-    }
-
-  if ( src_grid_add != -1 && tgt_grid_add != -1 )
-    {
-      if ( remap_store_link_fast )
-	store_link_cnsrv_fast(rv, src_grid_add, tgt_grid_add, num_wts, weights, grid_store);
-      else
-	store_link_cnsrv(rv, src_grid_add, tgt_grid_add, weights, link_add1, link_add2);
-
-      src_grid->cell_frac[src_grid_add] += weights[0];
-      tgt_grid->cell_frac[tgt_grid_add] += weights[3];
-    }
 
   if ( remap_store_link_fast )
     {
@@ -1777,85 +1884,10 @@ void scrip_remap_weights_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
   */
 
   /* Include centroids in weights and normalize using destination area if requested */
+  normalize_weights(tgt_grid, rv, src_centroid_lat, src_centroid_lon);
 
   num_links = rv->num_links;
 
-  if ( rv->norm_opt == NORM_OPT_DESTAREA )
-    {
-#if defined(SX)
-#pragma vdir nodep
-#endif
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) \
-  shared(num_links, rv, tgt_grid, src_centroid_lat, src_centroid_lon)		\
-  private(n, n3, src_grid_add, tgt_grid_add, weights, norm_factor)
-#endif
-      for ( n = 0; n < num_links; ++n )
-	{
-	  n3 = n*3;
-	  src_grid_add = rv->src_grid_add[n]; tgt_grid_add = rv->tgt_grid_add[n];
-	  weights[0] = rv->wts[n3]; weights[1] = rv->wts[n3+1]; weights[2] = rv->wts[n3+2];
-
-          if ( IS_NOT_EQUAL(tgt_grid->cell_area[tgt_grid_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_area[tgt_grid_add];
-          else
-            norm_factor = ZERO;
-
-	  rv->wts[n3  ] =  weights[0]*norm_factor;
-	  rv->wts[n3+1] = (weights[1] - weights[0]*src_centroid_lat[src_grid_add])*norm_factor;
-	  rv->wts[n3+2] = (weights[2] - weights[0]*src_centroid_lon[src_grid_add])*norm_factor;
-	}
-    }
-  else if ( rv->norm_opt == NORM_OPT_FRACAREA )
-    {
-#if defined(SX)
-#pragma vdir nodep
-#endif
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) \
-  shared(num_links, rv, tgt_grid, src_centroid_lat, src_centroid_lon)		\
-  private(n, n3, src_grid_add, tgt_grid_add, weights, norm_factor)
-#endif
-      for ( n = 0; n < num_links; ++n )
-	{
-	  n3 = n*3;
-	  src_grid_add = rv->src_grid_add[n]; tgt_grid_add = rv->tgt_grid_add[n];
-	  weights[0] = rv->wts[n3]; weights[1] = rv->wts[n3+1]; weights[2] = rv->wts[n3+2];
-
-          if ( IS_NOT_EQUAL(tgt_grid->cell_frac[tgt_grid_add], 0) )
-	    norm_factor = ONE/tgt_grid->cell_frac[tgt_grid_add];
-          else
-            norm_factor = ZERO;
-
-	  rv->wts[n3  ] =  weights[0]*norm_factor;
-	  rv->wts[n3+1] = (weights[1] - weights[0]*src_centroid_lat[src_grid_add])*norm_factor;
-	  rv->wts[n3+2] = (weights[2] - weights[0]*src_centroid_lon[src_grid_add])*norm_factor;
-	}
-    }
-  else if ( rv->norm_opt == NORM_OPT_NONE )
-    {
-#if defined(SX)
-#pragma vdir nodep
-#endif
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) \
-  shared(num_links, rv, tgt_grid, src_centroid_lat, src_centroid_lon)	\
-  private(n, n3, src_grid_add, tgt_grid_add, weights, norm_factor)
-#endif
-      for ( n = 0; n < num_links; ++n )
-	{
-	  n3 = n*3;
-	  src_grid_add = rv->src_grid_add[n]; tgt_grid_add = rv->tgt_grid_add[n];
-	  weights[0] = rv->wts[n3]; weights[1] = rv->wts[n3+1]; weights[2] = rv->wts[n3+2];
-
-          norm_factor = ONE;
-
-	  rv->wts[n3  ] =  weights[0]*norm_factor;
-	  rv->wts[n3+1] = (weights[1] - weights[0]*src_centroid_lat[src_grid_add])*norm_factor;
-	  rv->wts[n3+2] = (weights[2] - weights[0]*src_centroid_lon[src_grid_add])*norm_factor;
-	}
-    }
-
   if ( cdoVerbose )
     cdoPrint("Total number of links = %ld", rv->num_links);
 
diff --git a/src/remap_distwgt_scrip.c b/src/remap_distwgt_scrip.c
index b7f7bd5..ade6039 100644
--- a/src/remap_distwgt_scrip.c
+++ b/src/remap_distwgt_scrip.c
@@ -54,6 +54,7 @@ void nbr_store_distance(int nadd, double distance, int num_neighbors, int *restr
 {
   if ( num_neighbors == 1 )
     {
+      // if ( (distance+1.e-10) < nbr_dist[0] || ((fabs(distance-nbr_dist[0]) < 1.e-10) && nadd < nbr_add[0]) )
       if ( distance < nbr_dist[0] || (distance <= nbr_dist[0] && nadd < nbr_add[0]) )
 	{
 	  nbr_add[0]  = nadd;
@@ -122,7 +123,6 @@ double get_search_radius(void)
 static
 void grid_search_nbr_reg2d(int num_neighbors, remapgrid_t *src_grid, int *restrict nbr_add, double *restrict nbr_dist, 
 			   double plat, double plon, const int *restrict src_grid_dims,
-			   double coslat_dst, double coslon_dst, double sinlat_dst, double sinlon_dst,
 			   const double *restrict sinlat, const double *restrict coslat,
 			   const double *restrict sinlon, const double *restrict coslon,
 			   const double *restrict src_center_lat, const double *restrict src_center_lon)
@@ -148,12 +148,10 @@ void grid_search_nbr_reg2d(int num_neighbors, remapgrid_t *src_grid, int *restri
   int num_add = 0;
   double distance;   //  Angular distance
   double search_radius = get_search_radius();
-  /*
   double coslat_dst = cos(plat);  // cos(lat)  of the search point
   double coslon_dst = cos(plon);  // cos(lon)  of the search point
   double sinlat_dst = sin(plat);  // sin(lat)  of the search point
   double sinlon_dst = sin(plon);  // sin(lon)  of the search point
-  */
   nx = src_grid_dims[0];
   ny = src_grid_dims[1];
 
@@ -250,7 +248,6 @@ void grid_search_nbr_reg2d(int num_neighbors, remapgrid_t *src_grid, int *restri
 static
 void grid_search_nbr(int num_neighbors, remapgrid_t *src_grid, int *restrict nbr_add, double *restrict nbr_dist, 
 		     double plat, double plon, const int *restrict src_bin_add,
-		     double coslat_dst, double coslon_dst, double sinlat_dst, double sinlon_dst,
 		     const double *restrict sinlat, const double *restrict coslat,
 		     const double *restrict sinlon, const double *restrict coslon)
 {
@@ -271,12 +268,10 @@ void grid_search_nbr(int num_neighbors, remapgrid_t *src_grid, int *restrict nbr
   int n, nadd;
   int min_add, max_add;
   double search_radius = get_search_radius();
-  /* result changed a little on a few points with high resolution grid
-  double xcoslat_dst = cos(plat);  // cos(lat)  of the search point
-  double xcoslon_dst = cos(plon);  // cos(lon)  of the search point
-  double xsinlat_dst = sin(plat);  // sin(lat)  of the search point
-  double xsinlon_dst = sin(plon);  // sin(lon)  of the search point
-  */
+  double coslat_dst = cos(plat);  // cos(lat)  of the search point
+  double coslon_dst = cos(plon);  // cos(lon)  of the search point
+  double sinlat_dst = sin(plat);  // sin(lat)  of the search point
+  double sinlon_dst = sin(plon);  // sin(lon)  of the search point
   /* Loop over source grid and find nearest neighbors                         */
   /* restrict the search using search bins expand the bins to catch neighbors */
 
@@ -289,7 +284,7 @@ void grid_search_nbr(int num_neighbors, remapgrid_t *src_grid, int *restrict nbr
       nbr_dist[n] = BIGNUM;
     }
 
-  int i, j, ndist = max_add - min_add + 1;
+  int i, ndist = max_add - min_add + 1;
 
   if ( ndist <= 0 ) return;
 
@@ -297,10 +292,8 @@ void grid_search_nbr(int num_neighbors, remapgrid_t *src_grid, int *restrict nbr
   double *dist = (double*) malloc(ndist*sizeof(double));
   int    *adds = (int*) malloc(ndist*sizeof(int));
 
-#if defined(_OPENMP) && _OPENMP >= OPENMP4
-#pragma omp simd
-#endif
-  for ( j = 0, i = 0; i < ndist; ++i )
+  int j = 0;
+  for ( i = 0; i < ndist; ++i )
     {
       nadd = min_add+i;
       /* Find distance to this point */
@@ -428,14 +421,7 @@ void scrip_remap_weights_distwgt(int num_neighbors, remapgrid_t *src_grid, remap
   long tgt_grid_size;
   long n, nadds;
   long dst_add;                   /* destination address                         */
-  int nbr_mask[num_neighbors];    /* mask at nearest neighbors                   */
-  int nbr_add[num_neighbors];     /* source address at nearest neighbors         */
-  double nbr_dist[num_neighbors]; /* angular distance four nearest neighbors     */
   double dist_tot;                /* sum of neighbor distances (for normalizing) */
-  double coslat_dst;              /* cos(lat) of destination grid point          */
-  double coslon_dst;              /* cos(lon) of destination grid point          */
-  double sinlat_dst;              /* sin(lat) of destination grid point          */
-  double sinlon_dst;              /* sin(lon) of destination grid point          */
   double *coslat, *sinlat;        /* cosine, sine of grid lats (for distance)    */
   double *coslon, *sinlon;        /* cosine, sine of grid lons (for distance)    */
   double plat, plon;              /* lat/lon coords of destination point         */
@@ -506,17 +492,19 @@ void scrip_remap_weights_distwgt(int num_neighbors, remapgrid_t *src_grid, remap
 #if defined(_OPENMP)
 #pragma omp parallel for default(none) \
   shared(ompNumThreads, cdoTimer, num_neighbors, remap_grid_type, src_grid, tgt_grid, rv, tgt_grid_size, coslat, coslon, sinlat, sinlon, findex) \
-  private(dst_add, n, nadds, coslat_dst, coslon_dst, sinlat_dst, sinlon_dst, dist_tot, nbr_add, nbr_dist, nbr_mask, plat, plon) \
+  private(dst_add, n, nadds, dist_tot, plat, plon) \
   schedule(dynamic,1)
 #endif
   for ( dst_add = 0; dst_add < tgt_grid_size; ++dst_add )
     {
+      int nbr_mask[num_neighbors];    /* mask at nearest neighbors                   */
+      int nbr_add[num_neighbors];     /* source address at nearest neighbors         */
+      double nbr_dist[num_neighbors]; /* angular distance four nearest neighbors     */
       int lprogress = 1;
+      if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
+
 #if defined(_OPENMP)
-      if ( omp_get_thread_num() != 0 ) lprogress = 0;
-#endif
-#if defined(_OPENMP)
-#pragma omp atomic
+#include "pragma_omp_atomic_update.h"
 #endif
       findex++;
       if ( lprogress ) progressStatus(0, 1, findex/tgt_grid_size);
@@ -526,22 +514,15 @@ void scrip_remap_weights_distwgt(int num_neighbors, remapgrid_t *src_grid, remap
       plat = tgt_grid->cell_center_lat[dst_add];
       plon = tgt_grid->cell_center_lon[dst_add];
 
-      coslat_dst = cos(plat);
-      coslon_dst = cos(plon);
-      sinlat_dst = sin(plat);
-      sinlon_dst = sin(plon);
-
       /* Find nearest grid points on source grid and distances to each point */
       if ( remap_grid_type == REMAP_GRID_TYPE_REG2D )
 	grid_search_nbr_reg2d(num_neighbors, src_grid, nbr_add, nbr_dist, 
 			      plat, plon, src_grid->dims,
-			      coslat_dst, coslon_dst, sinlat_dst, sinlon_dst,
 			      sinlat, coslat, sinlon, coslon,
 			      src_grid->reg2d_center_lat, src_grid->reg2d_center_lon);
       else
 	grid_search_nbr(num_neighbors, src_grid, nbr_add, nbr_dist, 
 			plat, plon, src_grid->bin_addr,
-			coslat_dst, coslon_dst, sinlat_dst, sinlon_dst,
 			sinlat, coslat, sinlon, coslon);
 
       /* Compute weights based on inverse distance if mask is false, eliminate those points */
diff --git a/src/remap_store_link.c b/src/remap_store_link.c
index ac2c6f9..844b715 100644
--- a/src/remap_store_link.c
+++ b/src/remap_store_link.c
@@ -72,12 +72,13 @@ void grid_store_delete(grid_store_t* grid_store)
 	  grid_layer = grid_layer->next;
 	  free(grid_layer_f);
 	}
-
+      /*
       if ( cdoVerbose )
 	{
 	  fprintf(stderr, "block = %ld nlayers = %ld  allocated = %ld  used = %ld\n",
 		  iblk+1, nlayers, nlayers*blksize, j);
 	}
+      */
     }
 
   free(grid_store->blksize);
diff --git a/src/remaplib.c b/src/remaplib.c
index de60327..15d7671 100644
--- a/src/remaplib.c
+++ b/src/remaplib.c
@@ -588,13 +588,13 @@ void grid_check_lat_borders_rad(int n, double *ybounds)
 {
   if ( ybounds[0] > ybounds[n-1] )
     {
-      if ( RAD2DEG*ybounds[0]   >  88 ) ybounds[0]   =  PIH;
-      if ( RAD2DEG*ybounds[n-1] < -88 ) ybounds[n-1] = -PIH;
+      if ( RAD2DEG*ybounds[0]   >  PIH ) ybounds[0]   =  PIH;
+      if ( RAD2DEG*ybounds[n-1] < -PIH ) ybounds[n-1] = -PIH;
     }
   else
     {
-      if ( RAD2DEG*ybounds[0]   < -88 ) ybounds[0]   = -PIH;
-      if ( RAD2DEG*ybounds[n-1] >  88 ) ybounds[n-1] =  PIH;
+      if ( RAD2DEG*ybounds[0]   < -PIH ) ybounds[0]   = -PIH;
+      if ( RAD2DEG*ybounds[n-1] >  PIH ) ybounds[n-1] =  PIH;
     }
 }
 
@@ -678,8 +678,11 @@ void remap_define_grid(int map_type, int gridID, remapgrid_t *grid)
 
   grid->dims[0] = gridInqXsize(gridID);
   grid->dims[1] = gridInqYsize(gridID);
-  if ( grid->dims[0] == 0 ) cdoAbort("%s grid without longitude coordinates!", gridNamePtr(gridInqType(grid->gridID)));
-  if ( grid->dims[1] == 0 ) cdoAbort("%s grid without latitude coordinates!", gridNamePtr(gridInqType(grid->gridID)));
+  if ( gridInqType(grid->gridID) != GRID_UNSTRUCTURED )
+    {
+      if ( grid->dims[0] == 0 ) cdoAbort("%s grid without longitude coordinates!", gridNamePtr(gridInqType(grid->gridID)));
+      if ( grid->dims[1] == 0 ) cdoAbort("%s grid without latitude coordinates!", gridNamePtr(gridInqType(grid->gridID)));
+    }
 
   grid->is_cyclic = gridIsCircular(gridID);
 
@@ -982,29 +985,29 @@ void remap_vars_init(int map_type, long src_grid_size, long tgt_grid_size, remap
 #if defined(_OPENMP)
   if ( ompNumThreads > 1 )
     {
-      if      ( map_type == MAP_TYPE_CONSERV   ) rv->sort_add = TRUE;
+      if      ( map_type == MAP_TYPE_CONSERV     ) rv->sort_add = TRUE;
       else if ( map_type == MAP_TYPE_CONSERV_YAC ) rv->sort_add = TRUE;
-      else if ( map_type == MAP_TYPE_BILINEAR  ) rv->sort_add = TRUE;
-      else if ( map_type == MAP_TYPE_BICUBIC   ) rv->sort_add = TRUE;
-      else if ( map_type == MAP_TYPE_DISTWGT   ) rv->sort_add = TRUE;
+      else if ( map_type == MAP_TYPE_BILINEAR    ) rv->sort_add = TRUE;
+      else if ( map_type == MAP_TYPE_BICUBIC     ) rv->sort_add = TRUE;
+      else if ( map_type == MAP_TYPE_DISTWGT     ) rv->sort_add = TRUE;
       else cdoAbort("Unknown mapping method!");
     }
   else
 #endif
     {
-      if      ( map_type == MAP_TYPE_CONSERV   ) rv->sort_add = TRUE;
+      if      ( map_type == MAP_TYPE_CONSERV     ) rv->sort_add = TRUE;
       else if ( map_type == MAP_TYPE_CONSERV_YAC ) rv->sort_add = TRUE;
-      else if ( map_type == MAP_TYPE_BILINEAR  ) rv->sort_add = FALSE;
-      else if ( map_type == MAP_TYPE_BICUBIC   ) rv->sort_add = FALSE;
-      else if ( map_type == MAP_TYPE_DISTWGT   ) rv->sort_add = FALSE;
+      else if ( map_type == MAP_TYPE_BILINEAR    ) rv->sort_add = FALSE;
+      else if ( map_type == MAP_TYPE_BICUBIC     ) rv->sort_add = FALSE;
+      else if ( map_type == MAP_TYPE_DISTWGT     ) rv->sort_add = FALSE;
       else cdoAbort("Unknown mapping method!");
     }
 
-  if      ( map_type == MAP_TYPE_CONSERV   ) rv->num_wts = 3;
+  if      ( map_type == MAP_TYPE_CONSERV     ) rv->num_wts = 3;
   else if ( map_type == MAP_TYPE_CONSERV_YAC ) rv->num_wts = 1;
-  else if ( map_type == MAP_TYPE_BILINEAR  ) rv->num_wts = 1;
-  else if ( map_type == MAP_TYPE_BICUBIC   ) rv->num_wts = 4;
-  else if ( map_type == MAP_TYPE_DISTWGT   ) rv->num_wts = 1;
+  else if ( map_type == MAP_TYPE_BILINEAR    ) rv->num_wts = 1;
+  else if ( map_type == MAP_TYPE_BICUBIC     ) rv->num_wts = 4;
+  else if ( map_type == MAP_TYPE_DISTWGT     ) rv->num_wts = 1;
   else cdoAbort("Unknown mapping method!");
 
    /*
@@ -1248,7 +1251,6 @@ void remap_laf(double *restrict dst_array, double missval, long dst_size, long n
 #if defined(_OPENMP)
   double **src_cls2;
   double **src_wts2;
-  int ompthID;
 #endif
 
   for ( i = 0; i < dst_size; ++i ) dst_array[i] = missval;
@@ -1276,13 +1278,13 @@ void remap_laf(double *restrict dst_array, double missval, long dst_size, long n
 #if defined(_OPENMP)
 #pragma omp parallel for default(none) \
   shared(dst_size, src_cls2, src_wts2, num_links, dst_add, src_add, src_array, map_wts, num_wts, dst_array, max_cls)					\
-  private(i, n, k, ompthID, src_cls, src_wts, ncls, imax, wts) \
+  private(i, n, k, src_cls, src_wts, ncls, imax, wts) \
   schedule(dynamic,1)
 #endif
   for ( i = 0; i < dst_size; ++i )
     {
 #if defined(_OPENMP)
-      ompthID = omp_get_thread_num();
+      int ompthID = cdo_omp_get_thread_num();
       src_cls = src_cls2[ompthID];
       src_wts = src_wts2[ompthID];
 #endif
diff --git a/src/remapsort.c b/src/remapsort.c
index e60295c..6d6b30d 100644
--- a/src/remapsort.c
+++ b/src/remapsort.c
@@ -2,6 +2,10 @@
 #  include "config.h"
 #endif
 
+#if defined(_OPENMP)
+#include <omp.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/src/userlog.c b/src/userlog.c
index 224599f..b27ca65 100644
--- a/src/userlog.c
+++ b/src/userlog.c
@@ -196,6 +196,8 @@ float ibm2flt(unsigned char *ibm) {
 	return (float)value;
 }
 
+#if defined(HAVE_LOCK)
+#if defined(LOGPATH)
 /*
  * convert a float to an IBM single precision number v1.0
  *
@@ -268,7 +270,8 @@ int flt2ibm(float x, unsigned char *ibm) {
 
 	return 0;
 }
-
+#endif
+#endif
 
 #define  GET_UINT4(xb)        ((int) (((int)xb[0]<<24) + \
                                       ((int)xb[1]<<16) + \
diff --git a/src/util.c b/src/util.c
index b800d64..ec82877 100644
--- a/src/util.c
+++ b/src/util.c
@@ -19,6 +19,10 @@
 #define _XOPEN_SOURCE 600 /* ftello */
 #endif
 
+#if defined(_OPENMP)
+#  include <omp.h>
+#endif
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>   /* tolower */
@@ -30,6 +34,18 @@
 #include "util.h"
 
 
+int cdo_omp_get_thread_num(void)
+{
+  int threadnum = 0;
+
+#if defined(_OPENMP)
+  threadnum = omp_get_thread_num();
+#endif
+
+  return (threadnum);
+}
+
+
 char *getProgname(char *string)
 {
   char *progname;
diff --git a/test/Genweights.test.in b/test/Genweights.test.in
index 6cb92f0..b06ee00 100644
--- a/test/Genweights.test.in
+++ b/test/Genweights.test.in
@@ -50,7 +50,7 @@ for GRIDTYPE in "regular" "curvilinear" "unstructured"; do
       fi
 
       let NTEST+=1
-      rm -f $OFILE
+      rm -f $OFILE remapweights
     done
   done
 done
diff --git a/test/Makefile.am b/test/Makefile.am
index 5d0637d..15f54b6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -5,7 +5,7 @@ export
 TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
                   $(top_srcdir)/config/tap-driver.sh
 
-TESTS = Cat.test Gridarea.test Detrend.test Genweights.test Remap.test \
+TESTS = Read_netcdf.test Cat.test Gridarea.test Detrend.test Genweights.test Remap.test \
         Select.test Spectral.test Timstat.test Vertint.test
 
 #        $(top_srcdir)/test/test_Remap.sh \
diff --git a/test/Makefile.in b/test/Makefile.in
index f46b7fd..3091874 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -79,7 +79,8 @@ build_triplet = @build@
 host_triplet = @host@
 subdir = test
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/config/mkinstalldirs $(srcdir)/Cat.test.in \
+	$(top_srcdir)/config/mkinstalldirs \
+	$(srcdir)/Read_netcdf.test.in $(srcdir)/Cat.test.in \
 	$(srcdir)/Gridarea.test.in $(srcdir)/Genweights.test.in \
 	$(srcdir)/Remap.test.in $(srcdir)/Select.test.in \
 	$(srcdir)/Spectral.test.in $(srcdir)/Timstat.test.in \
@@ -94,9 +95,9 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/src/config.h
-CONFIG_CLEAN_FILES = Cat.test Gridarea.test Genweights.test Remap.test \
-	Select.test Spectral.test Timstat.test Vertint.test \
-	Detrend.test
+CONFIG_CLEAN_FILES = Read_netcdf.test Cat.test Gridarea.test \
+	Genweights.test Remap.test Select.test Spectral.test \
+	Timstat.test Vertint.test Detrend.test
 CONFIG_CLEAN_VPATH_FILES =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -494,7 +495,7 @@ CLEANFILES = `ls *.pyc`
 TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
                   $(top_srcdir)/config/tap-driver.sh
 
-TESTS = Cat.test Gridarea.test Detrend.test Genweights.test Remap.test \
+TESTS = Read_netcdf.test Cat.test Gridarea.test Detrend.test Genweights.test Remap.test \
         Select.test Spectral.test Timstat.test Vertint.test
 
 
@@ -544,6 +545,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(am__aclocal_m4_deps):
+Read_netcdf.test: $(top_builddir)/config.status $(srcdir)/Read_netcdf.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Cat.test: $(top_builddir)/config.status $(srcdir)/Cat.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Gridarea.test: $(top_builddir)/config.status $(srcdir)/Gridarea.test.in
diff --git a/test/Read_netcdf.test.in b/test/Read_netcdf.test.in
new file mode 100644
index 0000000..33cd888
--- /dev/null
+++ b/test/Read_netcdf.test.in
@@ -0,0 +1,48 @@
+#! @SHELL@
+echo 1..2 # Number of tests to be executed.
+#
+test -n "$CDO"      || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+CDOOUT=cout
+CDOERR=cerr
+#
+NTEST=1
+#
+for OPERATOR in "sinfon" "infon"; do
+  for FILE in "testfile01"; do
+    RSTAT=0
+    IFILE=$DATAPATH/netcdf_${FILE}.nc
+    OFILE=netcdf_${FILE}_${OPERATOR}
+    RFILE=$DATAPATH/${OFILE}_ref
+
+    CDOTEST="$OPERATOR $FILE"
+    CDOCOMMAND="$CDO $OPERATOR $IFILE"
+
+    if [ "@ENABLE_NETCDF@" = yes ] ; then
+      echo "Running test: $NTEST"
+      echo "$CDOCOMMAND"
+
+      $CDOCOMMAND > $OFILE
+      test $? -eq 0 || let RSTAT+=1
+
+      diff $OFILE $RFILE > $CDOOUT 2> $CDOERR
+      test $? -eq 0 || let RSTAT+=1
+
+      test -s $CDOERR && let RSTAT+=1
+      cat $CDOOUT $CDOERR
+
+      test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+      test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+    else
+      test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP netCDF not enabled"
+    fi
+
+    let NTEST+=1
+    rm -f $OFILE
+  done
+done
+#
+rm -f $CDOOUT $CDOERR
+#
+exit 0
diff --git a/test/data/._netcdf_testfile01.nc b/test/data/._netcdf_testfile01.nc
new file mode 100644
index 0000000..98ec9bb
Binary files /dev/null and b/test/data/._netcdf_testfile01.nc differ
diff --git a/test/data/Makefile.am b/test/data/Makefile.am
index f539c06..0add863 100644
--- a/test/data/Makefile.am
+++ b/test/data/Makefile.am
@@ -1,5 +1,7 @@
-INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data.grb detrend_data
+INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data.grb detrend_data \
+            netcdf_testfile01.nc
 
+NETCDF_REF   = netcdf_testfile01_sinfon_ref netcdf_testfile01_infon_ref
 TIMSTAT_REF  = timmin_ref timmax_ref timsum_ref timavg_ref timmean_ref timstd_ref timstd1_ref timvar_ref timvar1_ref
 SPECTRAL_REF = sp2gp_ref sp2gpl_ref gp2sp_ref gp2spl_ref
 VERTINT_REF  = ml2pl_ref
@@ -8,4 +10,4 @@ REMAP_REF    = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_
 SELECT_REF   = select1_ref select2_ref select3_ref select4_ref select5_ref
 DETREND_REF  = detrend_ref
 
-EXTRA_DIST = $(INPUTDATA) $(TIMSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF)
+EXTRA_DIST = $(INPUTDATA) $(NETCDF_REF) $(TIMSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF)
diff --git a/test/data/Makefile.in b/test/data/Makefile.in
index c8b7f36..08dd8b4 100644
--- a/test/data/Makefile.in
+++ b/test/data/Makefile.in
@@ -281,7 +281,10 @@ target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data.grb detrend_data
+INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data.grb detrend_data \
+            netcdf_testfile01.nc
+
+NETCDF_REF = netcdf_testfile01_sinfon_ref netcdf_testfile01_infon_ref
 TIMSTAT_REF = timmin_ref timmax_ref timsum_ref timavg_ref timmean_ref timstd_ref timstd1_ref timvar_ref timvar1_ref
 SPECTRAL_REF = sp2gp_ref sp2gpl_ref gp2sp_ref gp2spl_ref
 VERTINT_REF = ml2pl_ref
@@ -290,7 +293,7 @@ REMAP_REF = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_nn_
 
 SELECT_REF = select1_ref select2_ref select3_ref select4_ref select5_ref
 DETREND_REF = detrend_ref
-EXTRA_DIST = $(INPUTDATA) $(TIMSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF)
+EXTRA_DIST = $(INPUTDATA) $(NETCDF_REF) $(TIMSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF)
 all: all-am
 
 .SUFFIXES:
diff --git a/test/data/netcdf_testfile01.nc b/test/data/netcdf_testfile01.nc
new file mode 100644
index 0000000..019686a
Binary files /dev/null and b/test/data/netcdf_testfile01.nc differ
diff --git a/test/data/netcdf_testfile01_infon_ref b/test/data/netcdf_testfile01_infon_ref
new file mode 100644
index 0000000..b16b297
--- /dev/null
+++ b/test/data/netcdf_testfile01_infon_ref
@@ -0,0 +1,13 @@
+    -1 :       Date     Time   Level Gridsize    Miss :     Minimum        Mean     Maximum : Parameter name
+     1 : 0000-01-00 00:00:00       0     2592       0 :     -48.800      3.1647      32.000 : tem           
+     2 : 0000-02-00 00:00:00       0     2592       0 :     -48.700      2.4530      30.800 : tem           
+     3 : 0000-03-00 00:00:00       0     2592       0 :     -62.300      2.2681      30.900 : tem           
+     4 : 0000-04-00 00:00:00       0     2592       0 :     -68.500      3.5152      32.700 : tem           
+     5 : 0000-05-00 00:00:00       0     2592       0 :     -69.200      5.4965      34.100 : tem           
+     6 : 0000-06-00 00:00:00       0     2592       0 :     -69.000      6.9265      35.200 : tem           
+     7 : 0000-07-00 00:00:00       0     2592       0 :     -70.300      7.2876      35.700 : tem           
+     8 : 0000-08-00 00:00:00       0     2592       0 :     -70.200      6.9544      35.000 : tem           
+     9 : 0000-09-00 00:00:00       0     2592       0 :     -68.900      5.8637      32.900 : tem           
+    10 : 0000-10-00 00:00:00       0     2592       0 :     -60.800      4.6208      30.700 : tem           
+    11 : 0000-11-00 00:00:00       0     2592       0 :     -47.000      3.8041      31.000 : tem           
+    12 : 0000-12-00 00:00:00       0     2592       0 :     -46.300      3.5452      31.800 : tem           
diff --git a/test/data/netcdf_testfile01_sinfon_ref b/test/data/netcdf_testfile01_sinfon_ref
new file mode 100644
index 0000000..9216824
--- /dev/null
+++ b/test/data/netcdf_testfile01_sinfon_ref
@@ -0,0 +1,14 @@
+   File format : netCDF
+    -1 : Institut Source   Ttype    Levels Num    Points Num Dtype : Parameter name
+     1 : unknown  unknown  instant       1   1      2592   1  I16  : tem           
+   Grid coordinates :
+     1 : lonlat                   : points=2592 (72x36)
+                              lon : -177.5 to 177.5 by 5 degrees_east  circular
+                              lat : 87.5 to -87.5 by -5 degrees_north
+   Vertical coordinates :
+     1 : surface                  : levels=1
+   Time coordinate :  12 steps
+  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss
+  0000-01-00 00:00:00  0000-02-00 00:00:00  0000-03-00 00:00:00  0000-04-00 00:00:00
+  0000-05-00 00:00:00  0000-06-00 00:00:00  0000-07-00 00:00:00  0000-08-00 00:00:00
+  0000-09-00 00:00:00  0000-10-00 00:00:00  0000-11-00 00:00:00  0000-12-00 00:00:00

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cdo.git



More information about the debian-science-commits mailing list